Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reworked guard comparison. #2015

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions lib/less/tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,44 @@ tree.outputRuleset = function (env, output, rules) {
env.tabLevel--;
};

tree.compare = function (a, b) {
/* returns:
-1: a < b
0: a = b
1: a > b
and *any* other value for a != b (e.g. undefined, NaN, -2 etc.) */

if ((a.compare) &&
// for "symmetric results" force toCSS-based comparison
// of Quoted or Anonymous if either value is one of those
!(b.type === "Quoted" || b.type === "Anonymous")) {
return a.compare(b);
} else if (b.compare) {
return -b.compare(a);
} else if (a.type !== b.type) {
return undefined;
}

a = a.value;
b = b.value;
if (!Array.isArray(a)) {
return a === b ? 0 : undefined;
}
if (a.length !== b.length) {
return undefined;
}
for (var i = 0; i < a.length; i++) {
if (tree.compare(a[i], b[i]) !== 0) {
return undefined;
}
}
return 0;
};

tree.numericCompare = function (a, b) {
return a < b ? -1
: a === b ? 0
: a > b ? 1 : undefined;
};

})(require('./tree'));
15 changes: 2 additions & 13 deletions lib/less/tree/anonymous.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,8 @@ tree.Anonymous.prototype = {
eval: function () {
return new tree.Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines);
},
compare: function (x) {
if (!x.toCSS) {
return -1;
}

var left = this.toCSS(),
right = x.toCSS();

if (left === right) {
return 0;
}

return left < right ? -1 : 1;
compare: function (other) {
return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
},
genCSS: function (env, output) {
output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
Expand Down
9 changes: 3 additions & 6 deletions lib/less/tree/color.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,11 @@ tree.Color.prototype = {
return toHex([this.alpha * 255].concat(this.rgb));
},
compare: function (x) {
if (!x.rgb) {
return -1;
}

return (x.rgb[0] === this.rgb[0] &&
return (x.rgb &&
x.rgb[0] === this.rgb[0] &&
x.rgb[1] === this.rgb[1] &&
x.rgb[2] === this.rgb[2] &&
x.alpha === this.alpha) ? 0 : -1;
x.alpha === this.alpha) ? 0 : undefined;
}
};

Expand Down
28 changes: 7 additions & 21 deletions lib/less/tree/condition.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,20 @@ tree.Condition.prototype = {
this.rvalue = visitor.visit(this.rvalue);
},
eval: function (env) {
var a = this.lvalue.eval(env),
b = this.rvalue.eval(env);

var i = this.index, result;

result = (function (op) {
var result = (function (op, a, b) {
switch (op) {
case 'and':
return a && b;
case 'or':
return a || b;
case 'and': return a && b;
case 'or': return a || b;
default:
if (a.compare) {
result = a.compare(b);
} else if (b.compare) {
result = b.compare(a);
} else {
throw { type: "Type",
message: "Unable to perform comparison",
index: i };
}
switch (result) {
switch (tree.compare(a, b)) {
case -1: return op === '<' || op === '=<' || op === '<=';
case 0: return op === '=' || op === '>=' || op === '=<' || op === '<=';
case 1: return op === '>' || op === '>=';
default: return false;
}
}
})(this.op);
}) (this.op, this.lvalue.eval(env), this.rvalue.eval(env));

return this.negate ? !result : result;
}
};
Expand Down
43 changes: 17 additions & 26 deletions lib/less/tree/dimension.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,33 +88,24 @@ tree.Dimension.prototype = {
},

compare: function (other) {
if (other instanceof tree.Dimension) {
var a, b,
aValue, bValue;

if (this.unit.isEmpty() || other.unit.isEmpty()) {
a = this;
b = other;
} else {
a = this.unify();
b = other.unify();
if (a.unit.compare(b.unit) !== 0) {
return -1;
}
}
aValue = a.value;
bValue = b.value;

if (bValue > aValue) {
return -1;
} else if (bValue < aValue) {
return 1;
} else {
return 0;
}
var a, b;

if (!(other instanceof tree.Dimension)) {
return undefined;
}

if (this.unit.isEmpty() || other.unit.isEmpty()) {
a = this;
b = other;
} else {
return -1;
a = this.unify();
b = other.unify();
if (a.unit.compare(b.unit) !== 0) {
return undefined;
}
}

return tree.numericCompare(a.value, b.value);
},

unify: function () {
Expand Down Expand Up @@ -220,7 +211,7 @@ tree.Unit.prototype = {
},

compare: function (other) {
return this.is(other.toString()) ? 0 : -1;
return this.is(other.toString()) ? 0 : undefined;
},

is: function (unitString) {
Expand Down
9 changes: 1 addition & 8 deletions lib/less/tree/keyword.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,7 @@ tree.Keyword.prototype = {
if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; }
output.add(this.value);
},
toCSS: tree.toCSS,
compare: function (other) {
if (other instanceof tree.Keyword) {
return other.value === this.value ? 0 : 1;
} else {
return -1;
}
}
toCSS: tree.toCSS
};

tree.True = new(tree.Keyword)('true');
Expand Down
22 changes: 4 additions & 18 deletions lib/less/tree/quoted.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,13 @@ tree.Quoted.prototype = {
});
return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
},
compare: function (x) {
if (!x.toCSS) {
return -1;
}

var left, right;

compare: function (other) {
// when comparing quoted strings allow the quote to differ
if (x.type === "Quoted" && !this.escaped && !x.escaped) {
left = x.value;
right = this.value;
if (other.type === "Quoted" && !this.escaped && !other.escaped) {
return tree.numericCompare(this.value, other.value);
} else {
left = this.toCSS();
right = x.toCSS();
return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
}

if (left === right) {
return 0;
}

return left < right ? -1 : 1;
}
};

Expand Down
74 changes: 74 additions & 0 deletions test/css/mixins-guards.css
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,80 @@
content: theme1 is not 'theme2';
content: theme1 is theme1;
}
.variouse-types-comparision {
/**/
content: true is not equal to false;
content: false is not equal to true too;
/**/
content: 1 is not equal to true;
content: true is not equal to 1 too;
/**/
content: 2 is equal to 2px;
content: 2px is equal to 2 too;
/**/
content: 3 is equal to 3;
content: 3 is equal to 3 too;
/**/
content: 5 is not equal to 4;
content: 4 is not equal to 5 too;
/**/
content: abc is equal to abc;
content: abc is equal to abc too;
/**/
content: abc is not equal to "abc";
content: "abc" is not equal to abc too;
/**/
content: 'abc' is less than "abd";
content: "abd" is greater than 'abc' too;
content: 'abc' is not equal to "abd";
content: "abd" is not equal to 'abc' too;
/**/
content: 6 is equal to 6;
content: 6 is equal to 6 too;
/**/
content: 8 is less than 9 too;
content: 9 is greater than 8;
content: 9 is not equal to 8;
content: 8 is not equal to 9 too;
/**/
content: a is not equal to b;
content: b is not equal to a too;
/**/
content: 1 2 is not equal to 3;
content: 3 is not equal to 1 2 too;
}
.list-comparision {
/**/
content: a b c is equal to a b c;
content: a b c is equal to a b c too;
/**/
content: a b c is not equal to a b d;
content: a b d is not equal to a b c too;
/**/
content: a, b, c is equal to a, b, c;
content: a, b, c is equal to a, b, c too;
/**/
content: a, b, c is not equal to a, b, d;
content: a, b, d is not equal to a, b, c too;
/**/
content: 1 2px 300ms is equal to 1em 2 0.3s;
content: 1em 2 0.3s is equal to 1 2px 300ms too;
/**/
content: 1 2 3 is not equal to 1, 2, 3;
content: 1, 2, 3 is not equal to 1 2 3 too;
/**/
content: 1, 2, 3 is equal to 1, 2, 3;
content: 1, 2, 3 is equal to 1, 2, 3 too;
/**/
content: 1 2 3 1, 2, 3 is equal to 1 2 3 1, 2, 3;
content: 1 2 3 1, 2, 3 is equal to 1 2 3 1, 2, 3 too;
/**/
content: 1 2 3 1, 2, 3 is not equal to 1, 2, 3 1 2 3;
content: 1, 2, 3 1 2 3 is not equal to 1 2 3 1, 2, 3 too;
/**/
content: 1 2 3 1, 2, 3 4 is equal to 1 2 3 1, 2, 3 4;
content: 1 2 3 1, 2, 3 4 is equal to 1 2 3 1, 2, 3 4 too;
}
#tryNumberPx {
catch: all;
declare: 4;
Expand Down
43 changes: 43 additions & 0 deletions test/less/mixins-guards.less
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,49 @@
.stringguard(theme1);
}

.generic(@a, @b) {/**/}
.generic(@a, @b) when (@a = @b) {content: @a is equal to @b}
.generic(@a, @b) when (@b = @a) {content: @b is equal to @a too}
.generic(@a, @b) when (@a < @b) {content: @a is less than @b}
.generic(@a, @b) when (@b < @a) {content: @b is less than @a too}
.generic(@a, @b) when (@a > @b) {content: @a is greater than @b}
.generic(@a, @b) when (@b > @a) {content: @b is greater than @a too}
.generic(@a, @b) when not(@a = @b) {content: @a is not equal to @b}
.generic(@a, @b) when not(@b = @a) {content: @b is not equal to @a too}

.variouse-types-comparision {
.generic(true, false);
.generic(1, true);
.generic(2, 2px);
.generic(3, ~"3");
.generic(5, ~"4");
.generic(abc, ~"abc");
.generic(abc, "abc");
.generic('abc', "abd");
.generic(6, e("6"));
.generic(`9`, 8);
.generic(a, b);
.generic(1 2, 3);
}

.list-comparision {
.generic(a b c, a b c);
.generic(a b c, a b d);
.generic(a, b, c; a, b, c);
.generic(a, b, c; a, b, d);
.generic(1 2px 300ms, 1em 2 .3s);

@space-list: 1 2 3;
@comma-list: 1, 2, 3;
@compound: @space-list @comma-list;

.generic(@space-list, @comma-list);
.generic(@comma-list, ~"1, 2, 3");
.generic(@compound, @space-list @comma-list);
.generic(@compound, @comma-list @space-list);
.generic(@compound 4, ~"1 2 3 1, 2, 3 4");
}

.mixin(...) {
catch:all;
}
Expand Down