Skip to content

Commit 3aa3f08

Browse files
committed
[Slash Separator] Parse / as a separator rather than a division operator
Closes #663
1 parent 75555e6 commit 3aa3f08

File tree

20 files changed

+792
-620
lines changed

20 files changed

+792
-620
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## 2.0.0
22

3+
* **Breaking change:** `/` is now used for slash-separated lists rather than
4+
division in SassScript. You can still use it for division within `calc()` and
5+
other calculation expressions, or use `math.div()` instead.
6+
37
* **Breaking change:** `@elseif` is no longer treated as equivalent to `@else
48
if`, and is now treated like any other unknown plain CSS at-rule.
59

lib/src/ast/sass/expression/binary_operation.dart

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,6 @@ final class BinaryOperationExpression extends Expression {
2424
/// The right-hand operand.
2525
final Expression right;
2626

27-
/// Whether this is a [BinaryOperator.dividedBy] operation that may be
28-
/// interpreted as slash-separated numbers.
29-
///
30-
/// @nodoc
31-
@internal
32-
final bool allowsSlash;
33-
3427
FileSpan get span {
3528
// Avoid creating a bunch of intermediate spans for multiple binary
3629
// expressions in a row by moving to the left- and right-most expressions.
@@ -57,17 +50,7 @@ final class BinaryOperationExpression extends Expression {
5750
.trim()
5851
: span;
5952

60-
BinaryOperationExpression(this.operator, this.left, this.right)
61-
: allowsSlash = false;
62-
63-
/// Creates a [BinaryOperator.dividedBy] operation that may be interpreted as
64-
/// slash-separated numbers.
65-
///
66-
/// @nodoc
67-
@internal
68-
BinaryOperationExpression.slash(this.left, this.right)
69-
: operator = BinaryOperator.dividedBy,
70-
allowsSlash = true;
53+
BinaryOperationExpression(this.operator, this.left, this.right);
7154

7255
T accept<T>(ExpressionVisitor<T> visitor) =>
7356
visitor.visitBinaryOperationExpression(this);
@@ -151,6 +134,10 @@ enum BinaryOperator {
151134
times('times', '*', 6, associative: true),
152135

153136
/// The division operator, `/`.
137+
///
138+
/// **Note:** This is never directly parsed by the Sass stylesheet. It's only
139+
/// ever generated at runtime by reorienting the precedence of slash-separated
140+
/// lists.
154141
dividedBy('divided by', '/', 6),
155142

156143
/// The modulo operator, `%`.

lib/src/deprecation.dart

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ enum Deprecation {
1515
// DO NOT EDIT. This section was generated from the language repo.
1616
// See tool/grind/generate_deprecations.dart for details.
1717
//
18-
// Checksum: 0be67f32391e119205f8e98cd15fa8e7382b6dd2
18+
// Checksum: 0bd4067eac410d6d9ab05aab30a1f5bf0e602144
1919

2020
/// Deprecation for passing a string directly to meta.call().
2121
callString('call-string',
@@ -40,7 +40,6 @@ enum Deprecation {
4040
/// Deprecation for declaring new variables with !global.
4141
newGlobal('new-global',
4242
deprecatedIn: '1.17.2',
43-
obsoleteIn: '2.0.0',
4443
description: 'Declaring new variables with !global.'),
4544

4645
/// Deprecation for using color module functions in place of plain CSS functions.
@@ -51,7 +50,9 @@ enum Deprecation {
5150

5251
/// Deprecation for / operator for division.
5352
slashDiv('slash-div',
54-
deprecatedIn: '1.33.0', description: '/ operator for division.'),
53+
deprecatedIn: '1.33.0',
54+
obsoleteIn: '2.0.0',
55+
description: '/ operator for division.'),
5556

5657
/// Deprecation for leading, trailing, and repeated combinators.
5758
bogusCombinators('bogus-combinators',
@@ -145,6 +146,10 @@ enum Deprecation {
145146
deprecatedIn: '1.91.0',
146147
description: 'A rest parameter before a positional or named parameter.'),
147148

149+
/// Deprecation for the list.slash() function.
150+
listSlash('list-slash',
151+
deprecatedIn: '2.0.0', description: 'The list.slash() function.'),
152+
148153
// END AUTOGENERATED CODE
149154

150155
/// Used for deprecations coming from user-authored code.

lib/src/functions/color.dart

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,34 +1806,9 @@ Value _parseChannels(
18061806
"${pluralize('was', inputList.length, plural: 'were')} passed.",
18071807
name,
18081808
),
1809-
[...var initial, SassString(hasQuotes: false, :var text)] => switch (
1810-
text.split('/')) {
1811-
[_] => (input, null),
1812-
[var channel3, var alpha] => (
1813-
SassList([
1814-
...initial,
1815-
_parseNumberOrString(channel3),
1816-
], ListSeparator.space),
1817-
_parseNumberOrString(alpha),
1818-
),
1819-
_ => null,
1820-
},
1821-
[...var initial, SassNumber(asSlash: (var before, var after))] => (
1822-
SassList([...initial, before], ListSeparator.space),
1823-
after,
1824-
),
18251809
_ => (input, null),
18261810
};
18271811

1828-
/// Parses [text] as either a Sass number or an unquoted Sass string.
1829-
Value _parseNumberOrString(String text) {
1830-
try {
1831-
return ScssParser(text).parseNumber();
1832-
} on SassFormatException {
1833-
return SassString(text, quotes: false);
1834-
}
1835-
}
1836-
18371812
/// Creates a [SassColor] for the given [space] from the given channel values,
18381813
/// or throws a [SassScriptException] if the channel values are invalid.
18391814
///

lib/src/functions/list.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import 'dart:collection';
77
import 'package:collection/collection.dart';
88

99
import '../callable.dart';
10+
import '../deprecation.dart';
11+
import '../evaluation_context.dart';
1012
import '../exception.dart';
1113
import '../module/built_in.dart';
1214
import '../value.dart';
@@ -152,6 +154,14 @@ final _isBracketed = _function(
152154
);
153155

154156
final _slash = _function("slash", r"$elements...", (arguments) {
157+
warnForDeprecation(
158+
'list.slash() is no longer necessary. Sass now supports slash-separated '
159+
'list literals.\n'
160+
'This function is deprecated and will be removed in Dart 3.0.0.\n'
161+
'More info and automated migrator: https://sass-lang.com/d/slash-div',
162+
Deprecation.listSlash,
163+
);
164+
155165
var list = arguments[0].asList;
156166
if (list.length < 2) {
157167
throw SassScriptException("At least two elements are required.");

lib/src/functions/math.dart

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,8 @@ final _randomFunction = _function("random", r"$limit: null", (arguments) {
257257
});
258258

259259
final _div = _function("div", r"$number1, $number2", (arguments) {
260-
var number1 = arguments[0];
261-
var number2 = arguments[1];
262-
263-
if (number1 is! SassNumber || number2 is! SassNumber) {
264-
warn(
265-
"math.div() will only support number arguments in a future release.\n"
266-
"Use list.slash() instead for a slash separator.",
267-
);
268-
}
269-
260+
var number1 = arguments[0].assertNumber('number1');
261+
var number2 = arguments[1].assertNumber('number2');
270262
return number1.dividedBy(number2);
271263
});
272264

0 commit comments

Comments
 (0)