Skip to content

Commit 0fe3fee

Browse files
authored
[Function Units] Implement the breaking changes (#2656)
Closes #1776
1 parent b0785f5 commit 0fe3fee

File tree

7 files changed

+30
-194
lines changed

7 files changed

+30
-194
lines changed

lib/src/deprecation.dart

Lines changed: 2 additions & 1 deletion
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: da3a1fd53f628e2633aef3b7560951c00d48e1a1
18+
// Checksum: 212de63e7334243c6de7f9be29bbad0e1eaa2eea
1919

2020
/// Deprecation for passing a string directly to meta.call().
2121
callString('call-string',
@@ -68,6 +68,7 @@ enum Deprecation {
6868
/// Deprecation for passing invalid units to built-in functions.
6969
functionUnits('function-units',
7070
deprecatedIn: '1.56.0',
71+
obsoleteIn: '2.0.0',
7172
description: 'Passing invalid units to built-in functions.'),
7273

7374
/// Deprecation for using !default or !global multiple times for one variable.

lib/src/functions/color.dart

Lines changed: 7 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,19 +1102,8 @@ SassColor _changeColor(
11021102
SassNumber(hasUnits: false) => alphaArg.valueInRange(0, 1, "alpha"),
11031103
SassNumber() when alphaArg.hasUnit('%') =>
11041104
alphaArg.valueInRangeWithUnit(0, 100, "alpha", "%") / 100,
1105-
SassNumber() => () {
1106-
warnForDeprecation(
1107-
"\$alpha: Passing a unit other than % ($alphaArg) is "
1108-
"deprecated.\n"
1109-
"\n"
1110-
"To preserve current behavior: "
1111-
"${alphaArg.unitSuggestion('alpha')}\n"
1112-
"\n"
1113-
"See https://sass-lang.com/d/function-units",
1114-
Deprecation.functionUnits,
1115-
);
1116-
return alphaArg.valueInRange(0, 1, "alpha");
1117-
}(),
1105+
SassNumber() => throw SassScriptException(
1106+
'$alphaArg must have no units or unit %', 'alpha'),
11181107
_ => throw SassScriptException(
11191108
'$alphaArg is not a number or unquoted "none".',
11201109
'alpha',
@@ -1260,37 +1249,6 @@ double? _adjustChannel(
12601249

12611250
if (oldValue == null) _missingChannelError(color, channel.name);
12621251

1263-
switch ((color.space, channel)) {
1264-
case (ColorSpace.hsl || ColorSpace.hwb, ColorChannel(isPolarAngle: true)):
1265-
// `_channelFromValue` expects all hue values to be compatible with `deg`,
1266-
// but we're still in the deprecation period where we allow non-`deg`
1267-
// values for HSL and HWB so we have to handle that ahead-of-time.
1268-
adjustmentArg = SassNumber(_angleValue(adjustmentArg, 'hue'));
1269-
1270-
case (ColorSpace.hsl, LinearChannel(name: 'saturation' || 'lightness')):
1271-
// `_channelFromValue` expects lightness/saturation to be `%`, but we're
1272-
// still in the deprecation period where we allow non-`%` values so we
1273-
// have to handle that ahead-of-time.
1274-
_checkPercent(adjustmentArg, channel.name);
1275-
adjustmentArg = SassNumber(adjustmentArg.value, '%');
1276-
1277-
case (_, ColorChannel.alpha) when adjustmentArg.hasUnits:
1278-
// `_channelFromValue` expects alpha to be unitless or `%`, but we're
1279-
// still in the deprecation period where we allow other values (and
1280-
// interpret `%` as unitless) so we have to handle that ahead-of-time.
1281-
warnForDeprecation(
1282-
"\$alpha: Passing a number with unit ${adjustmentArg.unitString} is "
1283-
"deprecated.\n"
1284-
"\n"
1285-
"To preserve current behavior: "
1286-
"${adjustmentArg.unitSuggestion('alpha')}\n"
1287-
"\n"
1288-
"More info: https://sass-lang.com/d/function-units",
1289-
Deprecation.functionUnits,
1290-
);
1291-
adjustmentArg = SassNumber(adjustmentArg.value);
1292-
}
1293-
12941252
var result =
12951253
oldValue + _channelFromValue(channel, adjustmentArg, clamp: false)!;
12961254
return switch (channel) {
@@ -1448,35 +1406,14 @@ Value _hsl(String name, List<Value> arguments) {
14481406
}
14491407

14501408
/// Asserts that [angle] is a number and returns its value in degrees.
1451-
///
1452-
/// Prints a deprecation warning if [angle] has a non-angle unit.
1453-
double _angleValue(Value angleValue, String name) {
1454-
var angle = angleValue.assertNumber(name);
1455-
if (angle.compatibleWithUnit('deg')) return angle.coerceValueToUnit('deg');
1456-
1457-
warnForDeprecation(
1458-
"\$$name: Passing a unit other than deg ($angle) is deprecated.\n"
1459-
"\n"
1460-
"To preserve current behavior: ${angle.unitSuggestion(name)}\n"
1461-
"\n"
1462-
"See https://sass-lang.com/d/function-units",
1463-
Deprecation.functionUnits,
1464-
);
1465-
return angle.value;
1466-
}
1409+
double _angleValue(Value angleValue, String name) =>
1410+
angleValue.assertNumber(name).coerceValueToUnit('deg');
14671411

14681412
/// Prints a deprecation warning if [number] doesn't have unit `%`.
14691413
void _checkPercent(SassNumber number, String name) {
1470-
if (number.hasUnit('%')) return;
1471-
1472-
warnForDeprecation(
1473-
"\$$name: Passing a number without unit % ($number) is deprecated.\n"
1474-
"\n"
1475-
"To preserve current behavior: ${number.unitSuggestion(name, '%')}\n"
1476-
"\n"
1477-
"More info: https://sass-lang.com/d/function-units",
1478-
Deprecation.functionUnits,
1479-
);
1414+
if (!number.hasUnit('%')) {
1415+
throw SassScriptException('Expected $number to have unit %.', name);
1416+
}
14801417
}
14811418

14821419
/// Asserts that [number] is a percentage or has no units, and normalizes the

lib/src/functions/math.dart

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -233,27 +233,13 @@ final _randomFunction = _function("random", r"$limit: null", (arguments) {
233233
if (arguments[0] == sassNull) return SassNumber(_random.nextDouble());
234234
var limit = arguments[0].assertNumber("limit");
235235

236-
if (limit.hasUnits) {
237-
warnForDeprecation(
238-
"math.random() will no longer ignore \$limit units ($limit) in a "
239-
"future release.\n"
240-
"\n"
241-
"Recommendation: "
242-
"math.random(math.div(\$limit, 1${limit.unitString})) * 1${limit.unitString}\n"
243-
"\n"
244-
"To preserve current behavior: "
245-
"math.random(math.div(\$limit, 1${limit.unitString}))\n"
246-
"\n"
247-
"More info: https://sass-lang.com/d/function-units",
248-
Deprecation.functionUnits,
249-
);
250-
}
251-
252236
var limitScalar = limit.assertInt("limit");
253237
if (limitScalar < 1) {
254238
throw SassScriptException("\$limit: Must be greater than 0, was $limit.");
255239
}
256-
return SassNumber(_random.nextInt(limitScalar) + 1);
240+
return SassNumber.withUnits(_random.nextInt(limitScalar) + 1,
241+
numeratorUnits: limit.numeratorUnits,
242+
denominatorUnits: limit.denominatorUnits);
257243
});
258244

259245
final _div = _function("div", r"$number1, $number2", (arguments) {

lib/src/value.dart

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import 'package:meta/meta.dart';
66

77
import 'ast/selector.dart';
8-
import 'deprecation.dart';
9-
import 'evaluation_context.dart';
108
import 'exception.dart';
119
import 'utils.dart';
1210
import 'value/boolean.dart';
@@ -124,21 +122,8 @@ abstract class Value {
124122
/// [asList]. If [sassIndex] came from a function argument, [name] is the
125123
/// argument name (without the `$`). It's used for error reporting.
126124
int sassIndexToListIndex(Value sassIndex, [String? name]) {
127-
var indexValue = sassIndex.assertNumber(name);
128-
if (indexValue.hasUnits) {
129-
warnForDeprecation(
130-
"\$$name: Passing a number with unit ${indexValue.unitString} is "
131-
"deprecated.\n"
132-
"\n"
133-
"To preserve current behavior: "
134-
"${indexValue.unitSuggestion(name ?? 'index')}\n"
135-
"\n"
136-
"More info: https://sass-lang.com/d/function-units",
137-
Deprecation.functionUnits,
138-
);
139-
}
140-
141-
var index = indexValue.assertInt(name);
125+
var index =
126+
(sassIndex.assertNumber(name)..assertNoUnits(name)).assertInt(name);
142127
if (index == 0) throw SassScriptException("List index may not be 0.", name);
143128
if (index.abs() > lengthAsList) {
144129
throw SassScriptException(

lib/src/value/number.dart

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -962,21 +962,4 @@ abstract class SassNumber extends Value {
962962
var innerMap = _conversions[unit];
963963
return innerMap == null ? 1 : 1 / innerMap.values.first;
964964
}
965-
966-
/// Returns a suggested Sass snippet for converting a variable named [name]
967-
/// (without `%`) containing this number into a number with the same value and
968-
/// the given [unit].
969-
///
970-
/// If [unit] is null, this forces the number to be unitless.
971-
///
972-
/// This is used for deprecation warnings when restricting which units are
973-
/// allowed for a given function.
974-
@internal
975-
String unitSuggestion(String name, [String? unit]) {
976-
var result = "\$$name" +
977-
denominatorUnits.map((unit) => " * 1$unit").join() +
978-
numeratorUnits.map((unit) => " / 1$unit").join() +
979-
(unit == null ? "" : " * 1$unit");
980-
return numeratorUnits.isEmpty ? result : "calc($result)";
981-
}
982965
}

test/cli/shared/deprecations.dart

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,12 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
118118

119119
group("an evaluation-time deprecation", () {
120120
setUp(
121-
() => d.file("test.scss", """
122-
@use 'sass:math';
123-
a {b: math.random(1px)}
124-
""").create(),
121+
() => d.file("test.scss", "a {b: nth(1 2 3, 1)}").create(),
125122
);
126123

127124
test("in immediate mode", () async {
128125
var sass = await runSass([
129-
"--silence-deprecation=function-units",
126+
"--silence-deprecation=global-builtin",
130127
"test.scss",
131128
]);
132129
expect(sass.stderr, emitsDone);
@@ -137,7 +134,7 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
137134
var sass = await runSass([
138135
"--watch",
139136
"--poll",
140-
"--silence-deprecation=function-units",
137+
"--silence-deprecation=global-builtin",
141138
"test.scss:out.css",
142139
]);
143140
expect(sass.stderr, emitsDone);
@@ -152,15 +149,13 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
152149
test("in repl mode", () async {
153150
var sass = await runSass([
154151
"--interactive",
155-
"--silence-deprecation=function-units",
152+
"--silence-deprecation=global-builtin",
156153
]);
157154
expect(sass.stderr, emitsDone);
158-
sass.stdin.writeln("@use 'sass:math'");
159-
await expectLater(sass.stdout, emits(">> @use 'sass:math'"));
160-
sass.stdin.writeln("math.random(1px)");
155+
sass.stdin.writeln("nth(1 2 3, 1)");
161156
await expectLater(
162157
sass.stdout,
163-
emitsInOrder([">> math.random(1px)", "1"]),
158+
emitsInOrder([">> nth(1 2 3, 1)", "1"]),
164159
);
165160
await sass.kill();
166161
});
@@ -250,15 +245,12 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
250245

251246
group("an evaluation-time deprecation", () {
252247
setUp(
253-
() => d.file("test.scss", """
254-
@use 'sass:math';
255-
a {b: math.random(1px)}
256-
""").create(),
248+
() => d.file("test.scss", "a {b: nth(1 2 3, 1)}").create(),
257249
);
258250

259251
test("in immediate mode", () async {
260252
var sass = await runSass([
261-
"--fatal-deprecation=function-units",
253+
"--fatal-deprecation=global-builtin",
262254
"test.scss",
263255
]);
264256
expect(sass.stderr, emits(startsWith("Error: ")));
@@ -269,7 +261,7 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
269261
var sass = await runSass([
270262
"--watch",
271263
"--poll",
272-
"--fatal-deprecation=function-units",
264+
"--fatal-deprecation=global-builtin",
273265
"test.scss:out.css",
274266
]);
275267
await expectLater(sass.stderr, emits(startsWith("Error: ")));
@@ -286,15 +278,13 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
286278
test("in repl mode", () async {
287279
var sass = await runSass([
288280
"--interactive",
289-
"--fatal-deprecation=function-units",
281+
"--fatal-deprecation=global-builtin",
290282
]);
291-
sass.stdin.writeln("@use 'sass:math'");
292-
await expectLater(sass.stdout, emits(">> @use 'sass:math'"));
293-
sass.stdin.writeln("math.random(1px)");
283+
sass.stdin.writeln("nth(1 2 3, 1)");
294284
await expectLater(
295285
sass.stdout,
296286
emitsInOrder([
297-
">> math.random(1px)",
287+
">> nth(1 2 3, 1)",
298288
emitsThrough(startsWith("Error: ")),
299289
emitsThrough(contains("Remove this setting")),
300290
]),
@@ -316,12 +306,12 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
316306

317307
test("in immediate mode", () async {
318308
var sass = await runSass([
319-
"--future-deprecation=function-units",
309+
"--future-deprecation=global-builtin",
320310
"test.scss",
321311
]);
322312
expect(
323313
sass.stderr,
324-
emits(contains("function-units is not a future deprecation")),
314+
emits(contains("global-builtin is not a future deprecation")),
325315
);
326316
await sass.shouldExit(0);
327317
});
@@ -330,12 +320,12 @@ void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
330320
var sass = await runSass([
331321
"--watch",
332322
"--poll",
333-
"--future-deprecation=function-units",
323+
"--future-deprecation=global-builtin",
334324
"test.scss:out.css",
335325
]);
336326
expect(
337327
sass.stderr,
338-
emits(contains("function-units is not a future deprecation")),
328+
emits(contains("global-builtin is not a future deprecation")),
339329
);
340330

341331
await expectLater(

test/deprecations_test.dart

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -67,52 +67,6 @@ void main() {
6767
Deprecation.compileStringRelativeUrl);
6868
});
6969
});
70-
71-
// Deprecated in various Sass versions <=1.56.0
72-
group("functionUnits is violated by", () {
73-
test("a hue with a non-angle unit", () {
74-
_expectDeprecation("a {b: hsl(10px, 0%, 0%)}", Deprecation.functionUnits);
75-
});
76-
77-
test("a saturation/lightness with a non-percent unit", () {
78-
_expectDeprecation(
79-
"a {b: hsl(10deg, 0px, 0%)}",
80-
Deprecation.functionUnits,
81-
);
82-
});
83-
84-
test("a saturation/lightness with no unit", () {
85-
_expectDeprecation("a {b: hsl(10deg, 0%, 0)}", Deprecation.functionUnits);
86-
});
87-
88-
test("an alpha value with a non-percent unit", () {
89-
_expectDeprecation(
90-
r"@use 'sass:color'; a {b: color.change(red, $alpha: 1px)}",
91-
Deprecation.functionUnits,
92-
);
93-
});
94-
95-
test("calling math.random with units", () {
96-
_expectDeprecation(
97-
"@use 'sass:math'; a {b: math.random(100px)}",
98-
Deprecation.functionUnits,
99-
);
100-
});
101-
102-
test("calling list.nth with units", () {
103-
_expectDeprecation(
104-
"@use 'sass:list'; a {b: list.nth(1 2, 1px)}",
105-
Deprecation.functionUnits,
106-
);
107-
});
108-
109-
test("calling list.set-nth with units", () {
110-
_expectDeprecation(
111-
"@use 'sass:list'; a {b: list.set-nth(1 2, 1px, 3)}",
112-
Deprecation.functionUnits,
113-
);
114-
});
115-
});
11670
}
11771

11872
/// Confirms that [source] will error if [deprecation] is fatal.

0 commit comments

Comments
 (0)