Skip to content

Commit 5466dd7

Browse files
authored
Give SassScriptException a name parameter (#1798)
This avoids the need to copy around the same `_exception()` helper all over the place.
1 parent e2f9705 commit 5466dd7

File tree

9 files changed

+56
-51
lines changed

9 files changed

+56
-51
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 1.55.0
2+
3+
### Dart API
4+
5+
* Add an optional `argumentName` parameter to `SassScriptException()` to make it
6+
easier to throw exceptions associated with particular argument names.
7+
18
## 1.54.9
29

310
* Fix an incorrect span in certain `@media` query deprecation warnings.

lib/src/exception.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,13 @@ class SassScriptException {
165165
/// The error message.
166166
final String message;
167167

168-
SassScriptException(this.message);
168+
/// Creates a [SassScriptException] with the given [message].
169+
///
170+
/// The [argumentName] is the name of the Sass function argument that
171+
/// triggered this exception. If it's not null, it's automatically included in
172+
/// [message].
173+
SassScriptException(String message, [String? argumentName])
174+
: message = argumentName == null ? message : "\$$argumentName: $message";
169175

170176
String toString() => "$message\n\nBUG: This should include a source span!";
171177
}

lib/src/value.dart

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ abstract class Value {
121121
/// argument name (without the `$`). It's used for error reporting.
122122
int sassIndexToListIndex(Value sassIndex, [String? name]) {
123123
var index = sassIndex.assertNumber(name).assertInt(name);
124-
if (index == 0) throw _exception("List index may not be 0.", name);
124+
if (index == 0) throw SassScriptException("List index may not be 0.", name);
125125
if (index.abs() > lengthAsList) {
126-
throw _exception(
126+
throw SassScriptException(
127127
"Invalid index $sassIndex for a list with $lengthAsList elements.",
128128
name);
129129
}
@@ -139,35 +139,35 @@ abstract class Value {
139139
/// If this came from a function argument, [name] is the argument name
140140
/// (without the `$`). It's used for error reporting.
141141
SassBoolean assertBoolean([String? name]) =>
142-
throw _exception("$this is not a boolean.", name);
142+
throw SassScriptException("$this is not a boolean.", name);
143143

144144
/// Throws a [SassScriptException] if [this] isn't a calculation.
145145
///
146146
/// If this came from a function argument, [name] is the argument name
147147
/// (without the `$`). It's used for error reporting.
148148
SassCalculation assertCalculation([String? name]) =>
149-
throw _exception("$this is not a calculation.", name);
149+
throw SassScriptException("$this is not a calculation.", name);
150150

151151
/// Throws a [SassScriptException] if [this] isn't a color.
152152
///
153153
/// If this came from a function argument, [name] is the argument name
154154
/// (without the `$`). It's used for error reporting.
155155
SassColor assertColor([String? name]) =>
156-
throw _exception("$this is not a color.", name);
156+
throw SassScriptException("$this is not a color.", name);
157157

158158
/// Throws a [SassScriptException] if [this] isn't a function reference.
159159
///
160160
/// If this came from a function argument, [name] is the argument name
161161
/// (without the `$`). It's used for error reporting.
162162
SassFunction assertFunction([String? name]) =>
163-
throw _exception("$this is not a function reference.", name);
163+
throw SassScriptException("$this is not a function reference.", name);
164164

165165
/// Throws a [SassScriptException] if [this] isn't a map.
166166
///
167167
/// If this came from a function argument, [name] is the argument name
168168
/// (without the `$`). It's used for error reporting.
169169
SassMap assertMap([String? name]) =>
170-
throw _exception("$this is not a map.", name);
170+
throw SassScriptException("$this is not a map.", name);
171171

172172
/// Returns [this] as a [SassMap] if it is one (including empty lists, which
173173
/// count as empty maps) or returns `null` if it's not.
@@ -178,14 +178,14 @@ abstract class Value {
178178
/// If this came from a function argument, [name] is the argument name
179179
/// (without the `$`). It's used for error reporting.
180180
SassNumber assertNumber([String? name]) =>
181-
throw _exception("$this is not a number.", name);
181+
throw SassScriptException("$this is not a number.", name);
182182

183183
/// Throws a [SassScriptException] if [this] isn't a string.
184184
///
185185
/// If this came from a function argument, [name] is the argument name
186186
/// (without the `$`). It's used for error reporting.
187187
SassString assertString([String? name]) =>
188-
throw _exception("$this is not a string.", name);
188+
throw SassScriptException("$this is not a string.", name);
189189

190190
/// Converts a `selector-parse()`-style input into a string that can be
191191
/// parsed.
@@ -196,7 +196,7 @@ abstract class Value {
196196
var string = _selectorStringOrNull();
197197
if (string != null) return string;
198198

199-
throw _exception(
199+
throw SassScriptException(
200200
"$this is not a valid selector: it must be a string,\n"
201201
"a list of strings, or a list of lists of strings.",
202202
name);
@@ -384,10 +384,6 @@ abstract class Value {
384384
/// won't reflect the user's output settings. [toCssString] should be used
385385
/// instead to convert [this] to CSS.
386386
String toString() => serializeValue(this, inspect: true);
387-
388-
/// Throws a [SassScriptException] with the given [message].
389-
SassScriptException _exception(String message, [String? name]) =>
390-
SassScriptException(name == null ? message : "\$$name: $message");
391387
}
392388

393389
/// Extension methods that are only visible through the `sass_api` package.
@@ -414,7 +410,7 @@ extension SassApiValue on Value {
414410
// TODO(nweiz): colorize this if we're running in an environment where
415411
// that works.
416412
throwWithTrace(
417-
_exception(error.toString().replaceFirst("Error: ", ""), name),
413+
SassScriptException(error.toString().replaceFirst("Error: ", ""), name),
418414
stackTrace);
419415
}
420416
}
@@ -437,7 +433,7 @@ extension SassApiValue on Value {
437433
// TODO(nweiz): colorize this if we're running in an environment where
438434
// that works.
439435
throwWithTrace(
440-
_exception(error.toString().replaceFirst("Error: ", ""), name),
436+
SassScriptException(error.toString().replaceFirst("Error: ", ""), name),
441437
stackTrace);
442438
}
443439
}
@@ -460,7 +456,7 @@ extension SassApiValue on Value {
460456
// TODO(nweiz): colorize this if we're running in an environment where
461457
// that works.
462458
throwWithTrace(
463-
_exception(error.toString().replaceFirst("Error: ", ""), name),
459+
SassScriptException(error.toString().replaceFirst("Error: ", ""), name),
464460
stackTrace);
465461
}
466462
}
@@ -483,7 +479,7 @@ extension SassApiValue on Value {
483479
// TODO(nweiz): colorize this if we're running in an environment where
484480
// that works.
485481
throwWithTrace(
486-
_exception(error.toString().replaceFirst("Error: ", ""), name),
482+
SassScriptException(error.toString().replaceFirst("Error: ", ""), name),
487483
stackTrace);
488484
}
489485
}

lib/src/value/calculation.dart

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,11 @@ class SassCalculation extends Value {
235235
return arg;
236236
} else if (arg is SassString) {
237237
if (!arg.hasQuotes) return arg;
238-
throw _exception("Quoted string $arg can't be used in a calculation.");
238+
throw SassScriptException("Quoted string $arg can't be used in a calculation.");
239239
} else if (arg is SassCalculation) {
240240
return arg.name == 'calc' ? arg.arguments[0] : arg;
241241
} else if (arg is Value) {
242-
throw _exception("Value $arg can't be used in a calculation.");
242+
throw SassScriptException("Value $arg can't be used in a calculation.");
243243
} else {
244244
throw ArgumentError("Unexpected calculation argument $arg.");
245245
}
@@ -255,7 +255,7 @@ class SassCalculation extends Value {
255255
for (var arg in args) {
256256
if (arg is! SassNumber) continue;
257257
if (arg.numeratorUnits.length > 1 || arg.denominatorUnits.isNotEmpty) {
258-
throw _exception("Number $arg isn't compatible with CSS calculations.");
258+
throw SassScriptException("Number $arg isn't compatible with CSS calculations.");
259259
}
260260
}
261261

@@ -267,7 +267,7 @@ class SassCalculation extends Value {
267267
var number2 = args[j];
268268
if (number2 is! SassNumber) continue;
269269
if (number1.hasPossiblyCompatibleUnits(number2)) continue;
270-
throw _exception("$number1 and $number2 are incompatible.");
270+
throw SassScriptException("$number1 and $number2 are incompatible.");
271271
}
272272
}
273273
}
@@ -280,7 +280,7 @@ class SassCalculation extends Value {
280280
.any((arg) => arg is SassString || arg is CalculationInterpolation)) {
281281
return;
282282
}
283-
throw _exception(
283+
throw SassScriptException(
284284
"$expectedLength arguments required, but only ${args.length} "
285285
"${pluralize('was', args.length, plural: 'were')} passed.");
286286
}
@@ -319,10 +319,6 @@ class SassCalculation extends Value {
319319
listEquals(arguments, other.arguments);
320320

321321
int get hashCode => name.hashCode ^ listHash(arguments);
322-
323-
/// Throws a [SassScriptException] with the given [message].
324-
static SassScriptException _exception(String message, [String? name]) =>
325-
SassScriptException(name == null ? message : "\$$name: $message");
326322
}
327323

328324
/// A binary operation that can appear in a [SassCalculation].

lib/src/value/number.dart

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ abstract class SassNumber extends Value {
332332
int assertInt([String? name]) {
333333
var integer = fuzzyAsInt(value);
334334
if (integer != null) return integer;
335-
throw _exception("$this is not an int.", name);
335+
throw SassScriptException("$this is not an int.", name);
336336
}
337337

338338
/// If [value] is between [min] and [max], returns it.
@@ -344,7 +344,7 @@ abstract class SassNumber extends Value {
344344
num valueInRange(num min, num max, [String? name]) {
345345
var result = fuzzyCheckRange(value, min, max);
346346
if (result != null) return result;
347-
throw _exception(
347+
throw SassScriptException(
348348
"Expected $this to be within $min$unitString and $max$unitString.",
349349
name);
350350
}
@@ -361,7 +361,7 @@ abstract class SassNumber extends Value {
361361
num valueInRangeWithUnit(num min, num max, String name, String unit) {
362362
var result = fuzzyCheckRange(value, min, max);
363363
if (result != null) return result;
364-
throw _exception(
364+
throw SassScriptException(
365365
"Expected $this to be within $min$unit and $max$unit.", name);
366366
}
367367

@@ -395,7 +395,7 @@ abstract class SassNumber extends Value {
395395
/// (without the `$`). It's used for error reporting.
396396
void assertUnit(String unit, [String? name]) {
397397
if (hasUnit(unit)) return;
398-
throw _exception('Expected $this to have unit "$unit".', name);
398+
throw SassScriptException('Expected $this to have unit "$unit".', name);
399399
}
400400

401401
/// Throws a [SassScriptException] unless [this] has no units.
@@ -404,7 +404,7 @@ abstract class SassNumber extends Value {
404404
/// (without the `$`). It's used for error reporting.
405405
void assertNoUnits([String? name]) {
406406
if (!hasUnits) return;
407-
throw _exception('Expected $this to have no units.', name);
407+
throw SassScriptException('Expected $this to have no units.', name);
408408
}
409409

410410
/// Returns a copy of this number, converted to the units represented by
@@ -601,16 +601,16 @@ abstract class SassNumber extends Value {
601601
if (!hasUnits || !otherHasUnits) {
602602
message.write(" (one has units and the other doesn't)");
603603
}
604-
return _exception("$message.", name);
604+
return SassScriptException("$message.", name);
605605
} else if (!otherHasUnits) {
606-
return _exception("Expected $this to have no units.", name);
606+
return SassScriptException("Expected $this to have no units.", name);
607607
} else {
608608
if (newNumerators.length == 1 && newDenominators.isEmpty) {
609609
var type = _typesByUnit[newNumerators.first];
610610
if (type != null) {
611611
// If we're converting to a unit of a named type, use that type name
612612
// and make it clear exactly which units are convertible.
613-
return _exception(
613+
return SassScriptException(
614614
"Expected $this to have ${a(type)} unit "
615615
"(${_unitsByType[type]!.join(', ')}).",
616616
name);
@@ -619,7 +619,7 @@ abstract class SassNumber extends Value {
619619

620620
var unit =
621621
pluralize('unit', newNumerators.length + newDenominators.length);
622-
return _exception(
622+
return SassScriptException(
623623
"Expected $this to have $unit "
624624
"${_unitString(newNumerators, newDenominators)}.",
625625
name);
@@ -946,8 +946,4 @@ abstract class SassNumber extends Value {
946946
var innerMap = _conversions[unit];
947947
return innerMap == null ? 1 : 1 / innerMap.values.first;
948948
}
949-
950-
/// Throws a [SassScriptException] with the given [message].
951-
SassScriptException _exception(String message, [String? name]) =>
952-
SassScriptException(name == null ? message : "\$$name: $message");
953949
}

lib/src/value/string.dart

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,10 @@ class SassString extends Value {
170170
/// argument name (without the `$`). It's used for error reporting.
171171
int sassIndexToRuneIndex(Value sassIndex, [String? name]) {
172172
var index = sassIndex.assertNumber(name).assertInt(name);
173-
if (index == 0) throw _exception("String index may not be 0.", name);
174-
if (index.abs() > sassLength) {
175-
throw _exception(
173+
if (index == 0) {
174+
throw SassScriptException("String index may not be 0.", name);
175+
} else if (index.abs() > sassLength) {
176+
throw SassScriptException(
176177
"Invalid index $sassIndex for a string with $sassLength characters.",
177178
name);
178179
}
@@ -199,8 +200,4 @@ class SassString extends Value {
199200
bool operator ==(Object other) => other is SassString && text == other.text;
200201

201202
int get hashCode => _hashCache ??= text.hashCode;
202-
203-
/// Throws a [SassScriptException] with the given [message].
204-
SassScriptException _exception(String message, [String? name]) =>
205-
SassScriptException(name == null ? message : "\$$name: $message");
206203
}

pkg/sass_api/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 3.1.0
2+
3+
### Dart API
4+
5+
* Add an optional `argumentName` parameter to `SassScriptException()` to make it
6+
easier to throw exceptions associated with particular argument names.
7+
18
## 3.0.4
29

310
* `UnaryOperationExpression`s with operator `not` now include a correct span,

pkg/sass_api/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ name: sass_api
22
# Note: Every time we add a new Sass AST node, we need to bump the *major*
33
# version because it's a breaking change for anyone who's implementing the
44
# visitor interface(s).
5-
version: 3.0.4
5+
version: 3.1.0
66
description: Additional APIs for Dart Sass.
77
homepage: https://github.com/sass/dart-sass
88

99
environment:
1010
sdk: ">=2.17.0 <3.0.0"
1111

1212
dependencies:
13-
sass: 1.54.9
13+
sass: 1.55.0
1414

1515
dev_dependencies:
1616
dartdoc: ^5.0.0

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: sass
2-
version: 1.54.9
2+
version: 1.55.0
33
description: A Sass implementation in Dart.
44
homepage: https://github.com/sass/dart-sass
55

0 commit comments

Comments
 (0)