InternalException -> SassScriptException

This commit is contained in:
Natalie Weizenbaum 2016-10-16 18:46:38 -07:00
parent c41f2bb023
commit 604fa597e5
9 changed files with 91 additions and 87 deletions

View File

@ -88,12 +88,12 @@ class SelectorList extends Selector {
/// ///
/// The given [parent] may be `null`, indicating that this has no parents. If /// The given [parent] may be `null`, indicating that this has no parents. If
/// so, this list is returned as-is if it doesn't contain any explicit /// so, this list is returned as-is if it doesn't contain any explicit
/// [ParentSelector]s. If it does, this throws an [InternalException]. /// [ParentSelector]s. If it does, this throws a [SassScriptException].
SelectorList resolveParentSelectors(SelectorList parent, SelectorList resolveParentSelectors(SelectorList parent,
{bool implicitParent: true}) { {bool implicitParent: true}) {
if (parent == null) { if (parent == null) {
if (!_containsParentSelector) return this; if (!_containsParentSelector) return this;
throw new InternalException( throw new SassScriptException(
'Top-level selectors may not contain the parent selector "&".'); 'Top-level selectors may not contain the parent selector "&".');
} }
@ -186,7 +186,7 @@ class SelectorList extends Selector {
return parent.components.map((complex) { return parent.components.map((complex) {
var lastComponent = complex.components.last; var lastComponent = complex.components.last;
if (lastComponent is! CompoundSelector) { if (lastComponent is! CompoundSelector) {
throw new InternalException( throw new SassScriptException(
'Parent "$complex" is incompatible with this selector.'); 'Parent "$complex" is incompatible with this selector.');
} }

View File

@ -42,9 +42,9 @@ abstract class SimpleSelector extends Selector {
/// written with [suffix] at the end. /// written with [suffix] at the end.
/// ///
/// Assumes [suffix] is a valid identifier suffix. If this wouldn't produce a /// Assumes [suffix] is a valid identifier suffix. If this wouldn't produce a
/// valid [SimpleSelector], throws an [InternalException]. /// valid [SimpleSelector], throws a [SassScriptException].
SimpleSelector addSuffix(String suffix) => SimpleSelector addSuffix(String suffix) =>
throw new InternalException('Invalid parent selector "$this"'); throw new SassScriptException('Invalid parent selector "$this"');
/// Returns the compoments of a [CompoundSelector] that matches only elements /// Returns the compoments of a [CompoundSelector] that matches only elements
/// matched by both this and [compound]. /// matched by both this and [compound].

View File

@ -41,16 +41,16 @@ class SassFormatException extends SourceSpanFormatException
SassFormatException(String message, FileSpan span) : super(message, span); SassFormatException(String message, FileSpan span) : super(message, span);
} }
/// An exception thrown by SassScript that doesn't yet have a [FileSpan] /// An exception thrown by SassScript.
/// associated with it.
/// ///
/// This is caught by Sass and converted to a [SassRuntimeException] with a /// This doesn't extends [SassException] because it doesn't (yet) have a
/// source span and a stack trace. /// [FileSpan] associated with it. It's caught by Sass's internals and converted
class InternalException { /// to a [SassRuntimeException] with a source span and a stack trace.
class SassScriptException {
/// The error message. /// The error message.
final String message; final String message;
InternalException(this.message); SassScriptException(this.message);
String toString() => "$message\n\nBUG: This should include a source span!"; String toString() => "$message\n\nBUG: This should include a source span!";
} }

View File

@ -263,7 +263,7 @@ void defineCoreFunctions(Environment environment) {
} }
assert(arguments.length != 1); assert(arguments.length != 1);
throw new InternalException( throw new SassScriptException(
"Only 1 argument allowed, but ${arguments.length} were passed."); "Only 1 argument allowed, but ${arguments.length} were passed.");
} }
])); ]));
@ -289,7 +289,7 @@ void defineCoreFunctions(Environment environment) {
var color = arguments[0].assertColor("color"); var color = arguments[0].assertColor("color");
var argumentList = arguments[1] as SassArgumentList; var argumentList = arguments[1] as SassArgumentList;
if (argumentList.contents.isNotEmpty) { if (argumentList.contents.isNotEmpty) {
throw new InternalException( throw new SassScriptException(
"Only only positional argument is allowed. All other arguments must " "Only only positional argument is allowed. All other arguments must "
"be passed by name."); "be passed by name.");
} }
@ -307,7 +307,7 @@ void defineCoreFunctions(Environment environment) {
var alpha = getInRange("alpha", -1, 1); var alpha = getInRange("alpha", -1, 1);
if (keywords.isNotEmpty) { if (keywords.isNotEmpty) {
throw new InternalException( throw new SassScriptException(
"No ${pluralize('argument', keywords.length)} named " "No ${pluralize('argument', keywords.length)} named "
"${toSentence(keywords.keys.map((name) => "\$$name"), 'or')}."); "${toSentence(keywords.keys.map((name) => "\$$name"), 'or')}.");
} }
@ -316,7 +316,7 @@ void defineCoreFunctions(Environment environment) {
var hasHsl = hue != null || saturation != null || lightness != null; var hasHsl = hue != null || saturation != null || lightness != null;
if (hasRgb) { if (hasRgb) {
if (hasHsl) { if (hasHsl) {
throw new InternalException( throw new SassScriptException(
"RGB parameters may not be passed along with HSL parameters."); "RGB parameters may not be passed along with HSL parameters.");
} }
@ -340,7 +340,7 @@ void defineCoreFunctions(Environment environment) {
var color = arguments[0].assertColor("color"); var color = arguments[0].assertColor("color");
var argumentList = arguments[1] as SassArgumentList; var argumentList = arguments[1] as SassArgumentList;
if (argumentList.contents.isNotEmpty) { if (argumentList.contents.isNotEmpty) {
throw new InternalException( throw new SassScriptException(
"Only only positional argument is allowed. All other arguments must " "Only only positional argument is allowed. All other arguments must "
"be passed by name."); "be passed by name.");
} }
@ -367,7 +367,7 @@ void defineCoreFunctions(Environment environment) {
var alpha = getScale("alpha"); var alpha = getScale("alpha");
if (keywords.isNotEmpty) { if (keywords.isNotEmpty) {
throw new InternalException( throw new SassScriptException(
"No ${pluralize('argument', keywords.length)} named " "No ${pluralize('argument', keywords.length)} named "
"${toSentence(keywords.keys.map((name) => "\$$name"), 'or')}."); "${toSentence(keywords.keys.map((name) => "\$$name"), 'or')}.");
} }
@ -376,7 +376,7 @@ void defineCoreFunctions(Environment environment) {
var hasHsl = saturation != null || lightness != null; var hasHsl = saturation != null || lightness != null;
if (hasRgb) { if (hasRgb) {
if (hasHsl) { if (hasHsl) {
throw new InternalException( throw new SassScriptException(
"RGB parameters may not be passed along with HSL parameters."); "RGB parameters may not be passed along with HSL parameters.");
} }
@ -400,7 +400,7 @@ void defineCoreFunctions(Environment environment) {
var color = arguments[0].assertColor("color"); var color = arguments[0].assertColor("color");
var argumentList = arguments[1] as SassArgumentList; var argumentList = arguments[1] as SassArgumentList;
if (argumentList.contents.isNotEmpty) { if (argumentList.contents.isNotEmpty) {
throw new InternalException( throw new SassScriptException(
"Only only positional argument is allowed. All other arguments must " "Only only positional argument is allowed. All other arguments must "
"be passed by name."); "be passed by name.");
} }
@ -418,7 +418,7 @@ void defineCoreFunctions(Environment environment) {
var alpha = getInRange("alpha", 0, 1); var alpha = getInRange("alpha", 0, 1);
if (keywords.isNotEmpty) { if (keywords.isNotEmpty) {
throw new InternalException( throw new SassScriptException(
"No ${pluralize('argument', keywords.length)} named " "No ${pluralize('argument', keywords.length)} named "
"${toSentence(keywords.keys.map((name) => "\$$name"), 'or')}."); "${toSentence(keywords.keys.map((name) => "\$$name"), 'or')}.");
} }
@ -427,7 +427,7 @@ void defineCoreFunctions(Environment environment) {
var hasHsl = saturation != null || lightness != null; var hasHsl = saturation != null || lightness != null;
if (hasRgb) { if (hasRgb) {
if (hasHsl) { if (hasHsl) {
throw new InternalException( throw new SassScriptException(
"RGB parameters may not be passed along with HSL parameters."); "RGB parameters may not be passed along with HSL parameters.");
} }
@ -542,7 +542,7 @@ void defineCoreFunctions(Environment environment) {
if (max == null || max.lessThan(number).isTruthy) max = number; if (max == null || max.lessThan(number).isTruthy) max = number;
} }
if (max != null) return max; if (max != null) return max;
throw new InternalException("At least one argument must be passed."); throw new SassScriptException("At least one argument must be passed.");
}); });
environment.defineFunction("min", r"$numbers...", (arguments) { environment.defineFunction("min", r"$numbers...", (arguments) {
@ -552,14 +552,14 @@ void defineCoreFunctions(Environment environment) {
if (min == null || min.greaterThan(number).isTruthy) min = number; if (min == null || min.greaterThan(number).isTruthy) min = number;
} }
if (min != null) return min; if (min != null) return min;
throw new InternalException("At least one argument must be passed."); throw new SassScriptException("At least one argument must be passed.");
}); });
environment.defineFunction("random", r"$limit: null", (arguments) { environment.defineFunction("random", r"$limit: null", (arguments) {
if (arguments[0] == sassNull) return new SassNumber(_random.nextDouble()); if (arguments[0] == sassNull) return new SassNumber(_random.nextDouble());
var limit = arguments[0].assertNumber("limit").assertInt("limit"); var limit = arguments[0].assertNumber("limit").assertInt("limit");
if (limit < 1) { if (limit < 1) {
throw new InternalException( throw new SassScriptException(
"\$limit: Must be greater than 0, was $limit."); "\$limit: Must be greater than 0, was $limit.");
} }
return new SassNumber(_random.nextInt(limit + 1) + 1); return new SassNumber(_random.nextInt(limit + 1) + 1);
@ -607,7 +607,7 @@ void defineCoreFunctions(Environment environment) {
} else if (separatorParam.text == "comma") { } else if (separatorParam.text == "comma") {
separator = ListSeparator.comma; separator = ListSeparator.comma;
} else { } else {
throw new InternalException( throw new SassScriptException(
'\$$separator: Must be "space", "comma", or "auto".'); '\$$separator: Must be "space", "comma", or "auto".');
} }
@ -636,7 +636,7 @@ void defineCoreFunctions(Environment environment) {
} else if (separatorParam.text == "comma") { } else if (separatorParam.text == "comma") {
separator = ListSeparator.comma; separator = ListSeparator.comma;
} else { } else {
throw new InternalException( throw new SassScriptException(
'\$$separator: Must be "space", "comma", or "auto".'); '\$$separator: Must be "space", "comma", or "auto".');
} }
@ -725,7 +725,7 @@ void defineCoreFunctions(Environment environment) {
return new SassMap( return new SassMap(
mapMap(argumentList.keywords, key: (key, _) => new SassString(key))); mapMap(argumentList.keywords, key: (key, _) => new SassString(key)));
} else { } else {
throw new InternalException( throw new SassScriptException(
"\$args: $argumentList is not an argument list."); "\$args: $argumentList is not an argument list.");
} }
}); });
@ -735,7 +735,7 @@ void defineCoreFunctions(Environment environment) {
environment.defineFunction("selector-nest", r"$selectors...", (arguments) { environment.defineFunction("selector-nest", r"$selectors...", (arguments) {
var selectors = (arguments[0] as SassArgumentList).contents; var selectors = (arguments[0] as SassArgumentList).contents;
if (selectors.isEmpty) { if (selectors.isEmpty) {
throw new InternalException( throw new SassScriptException(
"\$selectors: At least one selector must be passed."); "\$selectors: At least one selector must be passed.");
} }
@ -748,7 +748,7 @@ void defineCoreFunctions(Environment environment) {
environment.defineFunction("selector-append", r"$selectors...", (arguments) { environment.defineFunction("selector-append", r"$selectors...", (arguments) {
var selectors = (arguments[0] as SassArgumentList).contents; var selectors = (arguments[0] as SassArgumentList).contents;
if (selectors.isEmpty) { if (selectors.isEmpty) {
throw new InternalException( throw new SassScriptException(
"\$selectors: At least one selector must be passed."); "\$selectors: At least one selector must be passed.");
} }
@ -760,13 +760,13 @@ void defineCoreFunctions(Environment environment) {
if (compound is CompoundSelector) { if (compound is CompoundSelector) {
var newCompound = _prependParent(compound); var newCompound = _prependParent(compound);
if (newCompound == null) { if (newCompound == null) {
throw new InternalException("Can't append $complex to $parent."); throw new SassScriptException("Can't append $complex to $parent.");
} }
return new ComplexSelector( return new ComplexSelector(
[newCompound]..addAll(complex.components.skip(1))); [newCompound]..addAll(complex.components.skip(1)));
} else { } else {
throw new InternalException("Can't append $complex to $parent."); throw new SassScriptException("Can't append $complex to $parent.");
} }
})).resolveParentSelectors(parent); })).resolveParentSelectors(parent);
}).asSassList; }).asSassList;
@ -899,7 +899,7 @@ void defineCoreFunctions(Environment environment) {
/// ///
/// If [number] has no units, its value is clamped to be greater than `0` or /// If [number] has no units, its value is clamped to be greater than `0` or
/// less than [max] and returned. If [number] is a percentage, it's scaled to be /// less than [max] and returned. If [number] is a percentage, it's scaled to be
/// within `0` and [max]. Otherwise, this throws an [InternalException]. /// within `0` and [max]. Otherwise, this throws a [SassScriptException].
/// ///
/// [name] is used to identify the argument in the error message. /// [name] is used to identify the argument in the error message.
num _percentageOrUnitless(SassNumber number, num max, String name) { num _percentageOrUnitless(SassNumber number, num max, String name) {
@ -909,7 +909,7 @@ num _percentageOrUnitless(SassNumber number, num max, String name) {
} else if (number.hasUnit("%")) { } else if (number.hasUnit("%")) {
value = max * number.value / 100; value = max * number.value / 100;
} else { } else {
throw new InternalException( throw new SassScriptException(
'\$$name: Expected $number to have no units or "%".'); '\$$name: Expected $number to have no units or "%".');
} }

View File

@ -62,7 +62,7 @@ abstract class Value {
/// Calls the appropriate visit method on [visitor]. /// Calls the appropriate visit method on [visitor].
/*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor); /*=T*/ accept/*<T>*/(ValueVisitor/*<T>*/ visitor);
/// Throws an [InternalException] if [this] isn't a boolean. /// Throws a [SassScriptException] if [this] isn't a boolean.
/// ///
/// Note that generally, functions should use [isTruthy] rather than requiring /// Note that generally, functions should use [isTruthy] rather than requiring
/// a literal boolean. /// a literal boolean.
@ -72,28 +72,28 @@ abstract class Value {
SassBoolean assertBoolean([String name]) => SassBoolean assertBoolean([String name]) =>
throw _exception("$this is not a boolean.", name); throw _exception("$this is not a boolean.", name);
/// Throws an [InternalException] if [this] isn't a color. /// Throws a [SassScriptException] if [this] isn't a color.
/// ///
/// If this came from a function argument, [name] is the argument name /// If this came from a function argument, [name] is the argument name
/// (without the `$`). It's used for debugging. /// (without the `$`). It's used for debugging.
SassColor assertColor([String name]) => SassColor assertColor([String name]) =>
throw _exception("$this is not a color.", name); throw _exception("$this is not a color.", name);
/// Throws an [InternalException] if [this] isn't a map. /// Throws a [SassScriptException] if [this] isn't a map.
/// ///
/// If this came from a function argument, [name] is the argument name /// If this came from a function argument, [name] is the argument name
/// (without the `$`). It's used for debugging. /// (without the `$`). It's used for debugging.
SassMap assertMap([String name]) => SassMap assertMap([String name]) =>
throw _exception("$this is not a map.", name); throw _exception("$this is not a map.", name);
/// Throws an [InternalException] if [this] isn't a number. /// Throws a [SassScriptException] if [this] isn't a number.
/// ///
/// If this came from a function argument, [name] is the argument name /// If this came from a function argument, [name] is the argument name
/// (without the `$`). It's used for debugging. /// (without the `$`). It's used for debugging.
SassNumber assertNumber([String name]) => SassNumber assertNumber([String name]) =>
throw _exception("$this is not a number.", name); throw _exception("$this is not a number.", name);
/// Throws an [InternalException] if [this] isn't a string. /// Throws a [SassScriptException] if [this] isn't a string.
/// ///
/// If this came from a function argument, [name] is the argument name /// If this came from a function argument, [name] is the argument name
/// (without the `$`). It's used for debugging. /// (without the `$`). It's used for debugging.
@ -103,7 +103,7 @@ abstract class Value {
/// Parses [this] as a selector list, in the same manner as the /// Parses [this] as a selector list, in the same manner as the
/// `selector-parse()` function. /// `selector-parse()` function.
/// ///
/// Throws an [InternalException] if this isn't a type that can be parsed as a /// Throws a [SassScriptException] if this isn't a type that can be parsed as a
/// selector, or if parsing fails. If [allowParent] is `true`, this allows /// selector, or if parsing fails. If [allowParent] is `true`, this allows
/// [ParentSelector]s. Otherwise, they're considered parse errors. /// [ParentSelector]s. Otherwise, they're considered parse errors.
/// ///
@ -123,7 +123,7 @@ abstract class Value {
/// Parses [this] as a simple selector, in the same manner as the /// Parses [this] as a simple selector, in the same manner as the
/// `selector-parse()` function. /// `selector-parse()` function.
/// ///
/// Throws an [InternalException] if this isn't a type that can be parsed as a /// Throws a [SassScriptException] if this isn't a type that can be parsed as a
/// selector, or if parsing fails. If [allowParent] is `true`, this allows /// selector, or if parsing fails. If [allowParent] is `true`, this allows
/// [ParentSelector]s. Otherwise, they're considered parse errors. /// [ParentSelector]s. Otherwise, they're considered parse errors.
/// ///
@ -143,7 +143,7 @@ abstract class Value {
/// Parses [this] as a compound selector, in the same manner as the /// Parses [this] as a compound selector, in the same manner as the
/// `selector-parse()` function. /// `selector-parse()` function.
/// ///
/// Throws an [InternalException] if this isn't a type that can be parsed as a /// Throws a [SassScriptException] if this isn't a type that can be parsed as a
/// selector, or if parsing fails. If [allowParent] is `true`, this allows /// selector, or if parsing fails. If [allowParent] is `true`, this allows
/// [ParentSelector]s. Otherwise, they're considered parse errors. /// [ParentSelector]s. Otherwise, they're considered parse errors.
/// ///
@ -164,7 +164,7 @@ abstract class Value {
/// Converts a `selector-parse()`-style input into a string that can be /// Converts a `selector-parse()`-style input into a string that can be
/// parsed. /// parsed.
/// ///
/// Throws an [InternalException] if [this] isn't a type or a structure that /// Throws a [SassScriptException] if [this] isn't a type or a structure that
/// can be parsed as a selector. /// can be parsed as a selector.
String _selectorString([String name]) { String _selectorString([String name]) {
var string = _selectorStringOrNull(); var string = _selectorStringOrNull();
@ -229,27 +229,27 @@ abstract class Value {
/// The SassScript `>` operation. /// The SassScript `>` operation.
SassBoolean greaterThan(Value other) => SassBoolean greaterThan(Value other) =>
throw new InternalException('Undefined operation "$this > $other".'); throw new SassScriptException('Undefined operation "$this > $other".');
/// The SassScript `>=` operation. /// The SassScript `>=` operation.
SassBoolean greaterThanOrEquals(Value other) => SassBoolean greaterThanOrEquals(Value other) =>
throw new InternalException('Undefined operation "$this >= $other".'); throw new SassScriptException('Undefined operation "$this >= $other".');
/// The SassScript `<` operation. /// The SassScript `<` operation.
SassBoolean lessThan(Value other) => SassBoolean lessThan(Value other) =>
throw new InternalException('Undefined operation "$this < $other".'); throw new SassScriptException('Undefined operation "$this < $other".');
/// The SassScript `<=` operation. /// The SassScript `<=` operation.
SassBoolean lessThanOrEquals(Value other) => SassBoolean lessThanOrEquals(Value other) =>
throw new InternalException('Undefined operation "$this <= $other".'); throw new SassScriptException('Undefined operation "$this <= $other".');
/// The SassScript `*` operation. /// The SassScript `*` operation.
Value times(Value other) => Value times(Value other) =>
throw new InternalException('Undefined operation "$this * $other".'); throw new SassScriptException('Undefined operation "$this * $other".');
/// The SassScript `%` operation. /// The SassScript `%` operation.
Value modulo(Value other) => Value modulo(Value other) =>
throw new InternalException('Undefined operation "$this % $other".'); throw new SassScriptException('Undefined operation "$this % $other".');
/// The SassScript `+` operation. /// The SassScript `+` operation.
Value plus(Value other) { Value plus(Value other) {
@ -288,7 +288,7 @@ abstract class Value {
/// instead to convert [this] to CSS. /// instead to convert [this] to CSS.
String toString() => valueToCss(this, inspect: true); String toString() => valueToCss(this, inspect: true);
/// Throws an [InternalException] with the given [message]. /// Throws a [SassScriptException] with the given [message].
InternalException _exception(String message, [String name]) => SassScriptException _exception(String message, [String name]) =>
new InternalException(name == null ? message : "\$$name: $message"); new SassScriptException(name == null ? message : "\$$name: $message");
} }

View File

@ -107,23 +107,23 @@ class SassColor extends Value {
Value plus(Value other) { Value plus(Value other) {
if (other is! SassNumber && other is! SassColor) return super.plus(other); if (other is! SassNumber && other is! SassColor) return super.plus(other);
throw new InternalException('Undefined operation "$this + $other".'); throw new SassScriptException('Undefined operation "$this + $other".');
} }
Value minus(Value other) { Value minus(Value other) {
if (other is! SassNumber && other is! SassColor) return super.minus(other); if (other is! SassNumber && other is! SassColor) return super.minus(other);
throw new InternalException('Undefined operation "$this - $other".'); throw new SassScriptException('Undefined operation "$this - $other".');
} }
Value dividedBy(Value other) { Value dividedBy(Value other) {
if (other is! SassNumber && other is! SassColor) { if (other is! SassNumber && other is! SassColor) {
return super.dividedBy(other); return super.dividedBy(other);
} }
throw new InternalException('Undefined operation "$this / $other".'); throw new SassScriptException('Undefined operation "$this / $other".');
} }
Value modulo(Value other) => Value modulo(Value other) =>
throw new InternalException('Undefined operation "$this % $other".'); throw new SassScriptException('Undefined operation "$this % $other".');
bool operator ==(other) => bool operator ==(other) =>
other is SassColor && other is SassColor &&

View File

@ -206,7 +206,7 @@ class SassNumber extends Value {
/// Returns [value] as an [int], if it's an integer value according to /// Returns [value] as an [int], if it's an integer value according to
/// [isInt]. /// [isInt].
/// ///
/// Throws an [InternalException] if [value] isn't an integer. If this came /// Throws a [SassScriptException] if [value] isn't an integer. If this came
/// from a function argument, [name] is the argument name (without the `$`). /// from a function argument, [name] is the argument name (without the `$`).
/// It's used for debugging. /// It's used for debugging.
int assertInt([String name]) { int assertInt([String name]) {
@ -221,7 +221,7 @@ class SassNumber extends Value {
/// A Sass-style index is one-based, and uses negative numbers to count /// A Sass-style index is one-based, and uses negative numbers to count
/// backwards from the end of the list. /// backwards from the end of the list.
/// ///
/// Throws an [InternalException] if this isn't an integer or if it isn't a /// Throws a [SassScriptException] if this isn't an integer or if it isn't a
/// valid index for [list]. If this came from a function argument, [name] is /// valid index for [list]. If this came from a function argument, [name] is
/// the argument name (without the `$`). It's used for debugging. /// the argument name (without the `$`). It's used for debugging.
int assertIndexFor(List list, [String name]) { int assertIndexFor(List list, [String name]) {
@ -238,7 +238,7 @@ class SassNumber extends Value {
/// If [value] is between [min] and [max], returns it. /// If [value] is between [min] and [max], returns it.
/// ///
/// If [value] is [fuzzyEquals] to [min] or [max], it's clamped to the /// If [value] is [fuzzyEquals] to [min] or [max], it's clamped to the
/// appropriate value. Otherwise, this throws an [InternalException]. If this /// appropriate value. Otherwise, this throws a [SassScriptException]. If this
/// came from a function argument, [name] is the argument name (without the /// came from a function argument, [name] is the argument name (without the
/// `$`). It's used for debugging. /// `$`). It's used for debugging.
num valueInRange(num min, num max, [String name]) { num valueInRange(num min, num max, [String name]) {
@ -254,7 +254,7 @@ class SassNumber extends Value {
denominatorUnits.isEmpty && denominatorUnits.isEmpty &&
numeratorUnits.first == unit; numeratorUnits.first == unit;
/// Throws an [InternalException] unless [this] has [unit] as its only unit /// Throws a [SassScriptException] unless [this] has [unit] as its only unit
/// (and as a numerator). /// (and as a numerator).
/// ///
/// If this came from a function argument, [name] is the argument name /// If this came from a function argument, [name] is the argument name
@ -264,7 +264,7 @@ class SassNumber extends Value {
throw _exception('Expected $this to have unit "$unit".'); throw _exception('Expected $this to have unit "$unit".');
} }
/// Throws an [InternalException] unless [this] has no units. /// Throws a [SassScriptException] unless [this] has no units.
/// ///
/// If this came from a function argument, [name] is the argument name /// If this came from a function argument, [name] is the argument name
/// (without the `$`). It's used for debugging. /// (without the `$`). It's used for debugging.
@ -276,7 +276,7 @@ class SassNumber extends Value {
/// Returns [value], converted to the units represented by [newNumerators] and /// Returns [value], converted to the units represented by [newNumerators] and
/// [newDenominators]. /// [newDenominators].
/// ///
/// Throws an [InternalException] if this number's units aren't compatible /// Throws a [SassScriptException] if this number's units aren't compatible
/// with [newNumerators] and [newDenominators]. /// with [newNumerators] and [newDenominators].
num valueInUnits(List<String> newNumerators, List<String> newDenominators) { num valueInUnits(List<String> newNumerators, List<String> newDenominators) {
if ((newNumerators.isEmpty && newDenominators.isEmpty) || if ((newNumerators.isEmpty && newDenominators.isEmpty) ||
@ -295,7 +295,7 @@ class SassNumber extends Value {
value *= factor; value *= factor;
return true; return true;
}, orElse: () { }, orElse: () {
throw new InternalException("Incompatible units " throw new SassScriptException("Incompatible units "
"${_unitString(this.numeratorUnits, this.denominatorUnits)} and " "${_unitString(this.numeratorUnits, this.denominatorUnits)} and "
"${_unitString(newNumerators, newDenominators)}."); "${_unitString(newNumerators, newDenominators)}.");
}); });
@ -309,14 +309,14 @@ class SassNumber extends Value {
value *= factor; value *= factor;
return true; return true;
}, orElse: () { }, orElse: () {
throw new InternalException("Incompatible units " throw new SassScriptException("Incompatible units "
"${_unitString(this.numeratorUnits, this.denominatorUnits)} and " "${_unitString(this.numeratorUnits, this.denominatorUnits)} and "
"${_unitString(newNumerators, newDenominators)}."); "${_unitString(newNumerators, newDenominators)}.");
}); });
} }
if (oldNumerators.isNotEmpty || oldDenominators.isNotEmpty) { if (oldNumerators.isNotEmpty || oldDenominators.isNotEmpty) {
throw new InternalException("Incompatible units " throw new SassScriptException("Incompatible units "
"${_unitString(this.numeratorUnits, this.denominatorUnits)} and " "${_unitString(this.numeratorUnits, this.denominatorUnits)} and "
"${_unitString(newNumerators, newDenominators)}."); "${_unitString(newNumerators, newDenominators)}.");
} }
@ -333,7 +333,7 @@ class SassNumber extends Value {
try { try {
greaterThan(other); greaterThan(other);
return true; return true;
} on InternalException { } on SassScriptException {
return false; return false;
} }
} }
@ -343,7 +343,7 @@ class SassNumber extends Value {
return new SassBoolean( return new SassBoolean(
_coerceUnits(other, (num1, num2) => fuzzyGreaterThan(num1, num2))); _coerceUnits(other, (num1, num2) => fuzzyGreaterThan(num1, num2)));
} }
throw new InternalException('Undefined operation "$this > $other".'); throw new SassScriptException('Undefined operation "$this > $other".');
} }
SassBoolean greaterThanOrEquals(Value other) { SassBoolean greaterThanOrEquals(Value other) {
@ -351,7 +351,7 @@ class SassNumber extends Value {
return new SassBoolean(_coerceUnits( return new SassBoolean(_coerceUnits(
other, (num1, num2) => fuzzyGreaterThanOrEquals(num1, num2))); other, (num1, num2) => fuzzyGreaterThanOrEquals(num1, num2)));
} }
throw new InternalException('Undefined operation "$this >= $other".'); throw new SassScriptException('Undefined operation "$this >= $other".');
} }
SassBoolean lessThan(Value other) { SassBoolean lessThan(Value other) {
@ -359,7 +359,7 @@ class SassNumber extends Value {
return new SassBoolean( return new SassBoolean(
_coerceUnits(other, (num1, num2) => fuzzyLessThan(num1, num2))); _coerceUnits(other, (num1, num2) => fuzzyLessThan(num1, num2)));
} }
throw new InternalException('Undefined operation "$this < $other".'); throw new SassScriptException('Undefined operation "$this < $other".');
} }
SassBoolean lessThanOrEquals(Value other) { SassBoolean lessThanOrEquals(Value other) {
@ -367,14 +367,14 @@ class SassNumber extends Value {
return new SassBoolean(_coerceUnits( return new SassBoolean(_coerceUnits(
other, (num1, num2) => fuzzyLessThanOrEquals(num1, num2))); other, (num1, num2) => fuzzyLessThanOrEquals(num1, num2)));
} }
throw new InternalException('Undefined operation "$this <= $other".'); throw new SassScriptException('Undefined operation "$this <= $other".');
} }
Value modulo(Value other) { Value modulo(Value other) {
if (other is SassNumber) { if (other is SassNumber) {
return new SassNumber(_coerceUnits(other, (num1, num2) => num1 % num2)); return new SassNumber(_coerceUnits(other, (num1, num2) => num1 % num2));
} }
throw new InternalException('Undefined operation "$this % $other".'); throw new SassScriptException('Undefined operation "$this % $other".');
} }
Value plus(Value other) { Value plus(Value other) {
@ -382,7 +382,7 @@ class SassNumber extends Value {
return new SassNumber(_coerceUnits(other, (num1, num2) => num1 + num2)); return new SassNumber(_coerceUnits(other, (num1, num2) => num1 + num2));
} }
if (other is! SassColor) return super.plus(other); if (other is! SassColor) return super.plus(other);
throw new InternalException('Undefined operation "$this + $other".'); throw new SassScriptException('Undefined operation "$this + $other".');
} }
Value minus(Value other) { Value minus(Value other) {
@ -390,7 +390,7 @@ class SassNumber extends Value {
return new SassNumber(_coerceUnits(other, (num1, num2) => num1 - num2)); return new SassNumber(_coerceUnits(other, (num1, num2) => num1 - num2));
} }
if (other is! SassColor) return super.minus(other); if (other is! SassColor) return super.minus(other);
throw new InternalException('Undefined operation "$this - $other".'); throw new SassScriptException('Undefined operation "$this - $other".');
} }
Value times(Value other) { Value times(Value other) {
@ -398,7 +398,7 @@ class SassNumber extends Value {
return _multiplyUnits(this.value * other.value, this.numeratorUnits, return _multiplyUnits(this.value * other.value, this.numeratorUnits,
this.denominatorUnits, other.numeratorUnits, other.denominatorUnits); this.denominatorUnits, other.numeratorUnits, other.denominatorUnits);
} }
throw new InternalException('Undefined operation "$this * $other".'); throw new SassScriptException('Undefined operation "$this * $other".');
} }
Value dividedBy(Value other) { Value dividedBy(Value other) {
@ -407,7 +407,7 @@ class SassNumber extends Value {
this.denominatorUnits, other.denominatorUnits, other.numeratorUnits); this.denominatorUnits, other.denominatorUnits, other.numeratorUnits);
} }
if (other is! SassColor) super.dividedBy(other); if (other is! SassColor) super.dividedBy(other);
throw new InternalException('Undefined operation "$this / $other".'); throw new SassScriptException('Undefined operation "$this / $other".');
} }
Value unaryPlus() => this; Value unaryPlus() => this;
@ -417,7 +417,7 @@ class SassNumber extends Value {
/// Converts [other]'s value to be compatible with this number's, and calls /// Converts [other]'s value to be compatible with this number's, and calls
/// [operation] with the resulting numbers. /// [operation] with the resulting numbers.
/// ///
/// Throws an [InternalException] if the two numbers' units are incompatible. /// Throws a [SassScriptException] if the two numbers' units are incompatible.
/*=T*/ _coerceUnits/*<T>*/( /*=T*/ _coerceUnits/*<T>*/(
SassNumber other, /*=T*/ operation(num num1, num num2)) { SassNumber other, /*=T*/ operation(num num1, num num2)) {
num num1; num num1;
@ -530,7 +530,7 @@ class SassNumber extends Value {
int get hashCode => fuzzyHashCode(value); int get hashCode => fuzzyHashCode(value);
/// Throws an [InternalException] with the given [message]. /// Throws a [SassScriptException] with the given [message].
InternalException _exception(String message, [String name]) => SassScriptException _exception(String message, [String name]) =>
new InternalException(name == null ? message : "\$$name: $message"); new SassScriptException(name == null ? message : "\$$name: $message");
} }

View File

@ -1229,12 +1229,12 @@ class _PerformVisitor implements StatementVisitor, ExpressionVisitor<Value> {
} }
} }
/// Runs [callback], and converts any [InternalException]s it throws to /// Runs [callback], and converts any [SassScriptException]s it throws to
/// [SassRuntimeException]s with [span]. /// [SassRuntimeException]s with [span].
/*=T*/ _addExceptionSpan/*<T>*/(FileSpan span, /*=T*/ callback()) { /*=T*/ _addExceptionSpan/*<T>*/(FileSpan span, /*=T*/ callback()) {
try { try {
return callback(); return callback();
} on InternalException catch (error) { } on SassScriptException catch (error) {
throw _exception(error.message, span); throw _exception(error.message, span);
} }
} }

View File

@ -45,7 +45,7 @@ String toCss(CssNode node, {OutputStyle style, bool inspect: false}) {
/// If [inspect] is `true`, this will emit an unambiguous representation of the /// If [inspect] is `true`, this will emit an unambiguous representation of the
/// source structure. Note however that, although this will be valid SCSS, it /// source structure. Note however that, although this will be valid SCSS, it
/// may not be valid CSS. If [inspect] is `false` and [value] can't be /// may not be valid CSS. If [inspect] is `false` and [value] can't be
/// represented in plain CSS, throws an [InternalException]. /// represented in plain CSS, throws a [SassScriptException].
String valueToCss(Value value, {bool inspect: false}) { String valueToCss(Value value, {bool inspect: false}) {
var visitor = new _SerializeCssVisitor(inspect: inspect); var visitor = new _SerializeCssVisitor(inspect: inspect);
value.accept(visitor); value.accept(visitor);
@ -57,7 +57,7 @@ String valueToCss(Value value, {bool inspect: false}) {
/// If [inspect] is `true`, this will emit an unambiguous representation of the /// If [inspect] is `true`, this will emit an unambiguous representation of the
/// source structure. Note however that, although this will be valid SCSS, it /// source structure. Note however that, although this will be valid SCSS, it
/// may not be valid CSS. If [inspect] is `false` and [selector] can't be /// may not be valid CSS. If [inspect] is `false` and [selector] can't be
/// represented in plain CSS, throws an [InternalException]. /// represented in plain CSS, throws a [SassScriptException].
String selectorToCss(Selector selector, {bool inspect: false}) { String selectorToCss(Selector selector, {bool inspect: false}) {
var visitor = new _SerializeCssVisitor(inspect: inspect); var visitor = new _SerializeCssVisitor(inspect: inspect);
selector.accept(visitor); selector.accept(visitor);
@ -247,11 +247,11 @@ class _SerializeCssVisitor
// ## Values // ## Values
/// Converts [value] to a plain CSS string, converting any /// Converts [value] to a plain CSS string, converting any
/// [InternalException]s to [SassException]s. /// [SassScriptException]s to [SassException]s.
void _visitValue(CssValue<Value> value) { void _visitValue(CssValue<Value> value) {
try { try {
value.value.accept(this); value.value.accept(this);
} on InternalException catch (error) { } on SassScriptException catch (error) {
throw new SassException(error.message, value.span); throw new SassException(error.message, value.span);
} }
} }
@ -283,7 +283,9 @@ class _SerializeCssVisitor
if (value.hasBrackets) { if (value.hasBrackets) {
_buffer.writeCharCode($lbracket); _buffer.writeCharCode($lbracket);
} else if (value.contents.isEmpty) { } else if (value.contents.isEmpty) {
if (!_inspect) throw new InternalException("() isn't a valid CSS value"); if (!_inspect) {
throw new SassScriptException("() isn't a valid CSS value");
}
_buffer.write("()"); _buffer.write("()");
return; return;
} }
@ -317,7 +319,9 @@ class _SerializeCssVisitor
} }
void visitMap(SassMap map) { void visitMap(SassMap map) {
if (!_inspect) throw new InternalException("$map isn't a valid CSS value."); if (!_inspect) {
throw new SassScriptException("$map isn't a valid CSS value.");
}
_buffer.writeCharCode($lparen); _buffer.writeCharCode($lparen);
_writeBetween(map.contents.keys, ", ", (key) { _writeBetween(map.contents.keys, ", ", (key) {
_writeMapElement(key); _writeMapElement(key);
@ -347,7 +351,7 @@ class _SerializeCssVisitor
if (!_inspect) { if (!_inspect) {
if (value.numeratorUnits.length > 1 || if (value.numeratorUnits.length > 1 ||
value.denominatorUnits.isNotEmpty) { value.denominatorUnits.isNotEmpty) {
throw new InternalException("$value isn't a valid CSS value."); throw new SassScriptException("$value isn't a valid CSS value.");
} }
if (value.numeratorUnits.isNotEmpty) { if (value.numeratorUnits.isNotEmpty) {