mirror of
https://github.com/danog/dart-sass.git
synced 2024-11-27 04:34:59 +01:00
Make SassList.contents private (#227)
This forces users to use Value.asList, which encourages them to be aware that every value counts as a list.
This commit is contained in:
parent
854e7f57d6
commit
f1e58e083e
@ -375,7 +375,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
|
||||
new BuiltInCallable("adjust-color", r"$color, $kwargs...", (arguments) {
|
||||
var color = arguments[0].assertColor("color");
|
||||
var argumentList = arguments[1] as SassArgumentList;
|
||||
if (argumentList.contents.isNotEmpty) {
|
||||
if (argumentList.asList.isNotEmpty) {
|
||||
throw new SassScriptException(
|
||||
"Only only positional argument is allowed. All other arguments must "
|
||||
"be passed by name.");
|
||||
@ -428,7 +428,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
|
||||
new BuiltInCallable("scale-color", r"$color, $kwargs...", (arguments) {
|
||||
var color = arguments[0].assertColor("color");
|
||||
var argumentList = arguments[1] as SassArgumentList;
|
||||
if (argumentList.contents.isNotEmpty) {
|
||||
if (argumentList.asList.isNotEmpty) {
|
||||
throw new SassScriptException(
|
||||
"Only only positional argument is allowed. All other arguments must "
|
||||
"be passed by name.");
|
||||
@ -489,7 +489,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
|
||||
new BuiltInCallable("change-color", r"$color, $kwargs...", (arguments) {
|
||||
var color = arguments[0].assertColor("color");
|
||||
var argumentList = arguments[1] as SassArgumentList;
|
||||
if (argumentList.contents.isNotEmpty) {
|
||||
if (argumentList.asList.isNotEmpty) {
|
||||
throw new SassScriptException(
|
||||
"Only only positional argument is allowed. All other arguments must "
|
||||
"be passed by name.");
|
||||
@ -766,10 +766,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
|
||||
}),
|
||||
|
||||
new BuiltInCallable("zip", r"$lists...", (arguments) {
|
||||
var lists = (arguments[0] as SassArgumentList)
|
||||
.contents
|
||||
.map((list) => list.asList)
|
||||
.toList();
|
||||
var lists = arguments[0].asList.map((list) => list.asList).toList();
|
||||
var i = 0;
|
||||
var results = <SassList>[];
|
||||
while (lists.every((list) => i != list.length)) {
|
||||
@ -814,9 +811,9 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
|
||||
|
||||
new BuiltInCallable("map-remove", r"$map, $keys...", (arguments) {
|
||||
var map = arguments[0].assertMap("map");
|
||||
var keys = arguments[1] as SassArgumentList;
|
||||
var keys = arguments[1];
|
||||
var mutableMap = new Map<Value, Value>.from(map.contents);
|
||||
for (var key in keys.contents) {
|
||||
for (var key in keys.asList) {
|
||||
mutableMap.remove(key);
|
||||
}
|
||||
return new SassMap(mutableMap);
|
||||
@ -854,7 +851,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
|
||||
// ## Selectors
|
||||
|
||||
new BuiltInCallable("selector-nest", r"$selectors...", (arguments) {
|
||||
var selectors = (arguments[0] as SassArgumentList).contents;
|
||||
var selectors = arguments[0].asList;
|
||||
if (selectors.isEmpty) {
|
||||
throw new SassScriptException(
|
||||
"\$selectors: At least one selector must be passed.");
|
||||
@ -867,7 +864,7 @@ final List<BuiltInCallable> coreFunctions = new UnmodifiableListView([
|
||||
}),
|
||||
|
||||
new BuiltInCallable("selector-append", r"$selectors...", (arguments) {
|
||||
var selectors = (arguments[0] as SassArgumentList).contents;
|
||||
var selectors = arguments[0].asList;
|
||||
if (selectors.isEmpty) {
|
||||
throw new SassScriptException(
|
||||
"\$selectors: At least one selector must be passed.");
|
||||
|
@ -185,11 +185,11 @@ abstract class Value implements ext.Value {
|
||||
if (this is SassString) return (this as SassString).text;
|
||||
if (this is! SassList) return null;
|
||||
var list = this as SassList;
|
||||
if (list.contents.isEmpty) return null;
|
||||
if (list.asList.isEmpty) return null;
|
||||
|
||||
var result = <String>[];
|
||||
if (list.separator == ListSeparator.comma) {
|
||||
for (var complex in list.contents) {
|
||||
for (var complex in list.asList) {
|
||||
if (complex is SassString) {
|
||||
result.add(complex.text);
|
||||
} else if (complex is SassList &&
|
||||
@ -202,7 +202,7 @@ abstract class Value implements ext.Value {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var compound in list.contents) {
|
||||
for (var compound in list.asList) {
|
||||
if (compound is SassString) {
|
||||
result.add(compound.text);
|
||||
} else {
|
||||
|
8
lib/src/value/external/list.dart
vendored
8
lib/src/value/external/list.dart
vendored
@ -10,14 +10,6 @@ import 'value.dart';
|
||||
|
||||
/// A SassScript list.
|
||||
abstract class SassList extends Value {
|
||||
// TODO(nweiz): Use persistent data structures rather than copying here. An
|
||||
// RRB vector should fit our use-cases well.
|
||||
//
|
||||
// We may also want to fall back to a plain unmodifiable List for small lists
|
||||
// (<32 items?).
|
||||
/// The contents of the list.
|
||||
List<Value> get contents;
|
||||
|
||||
ListSeparator get separator;
|
||||
|
||||
bool get hasBrackets;
|
||||
|
@ -8,27 +8,32 @@ import '../value.dart';
|
||||
import 'external/value.dart' as ext;
|
||||
|
||||
class SassList extends Value implements ext.SassList {
|
||||
final List<Value> contents;
|
||||
// TODO(nweiz): Use persistent data structures rather than copying here. An
|
||||
// RRB vector should fit our use-cases well.
|
||||
//
|
||||
// We may also want to fall back to a plain unmodifiable List for small lists
|
||||
// (<32 items?).
|
||||
final List<Value> _contents;
|
||||
|
||||
final ListSeparator separator;
|
||||
|
||||
final bool hasBrackets;
|
||||
|
||||
bool get isBlank => contents.every((element) => element.isBlank);
|
||||
bool get isBlank => asList.every((element) => element.isBlank);
|
||||
|
||||
List<Value> get asList => contents;
|
||||
List<Value> get asList => _contents;
|
||||
|
||||
int get lengthAsList => contents.length;
|
||||
int get lengthAsList => asList.length;
|
||||
|
||||
const SassList.empty({ListSeparator separator, bool brackets: false})
|
||||
: contents = const [],
|
||||
: _contents = const [],
|
||||
separator = separator ?? ListSeparator.undecided,
|
||||
hasBrackets = brackets;
|
||||
|
||||
SassList(Iterable<Value> contents, this.separator, {bool brackets: false})
|
||||
: contents = new List.unmodifiable(contents),
|
||||
: _contents = new List.unmodifiable(contents),
|
||||
hasBrackets = brackets {
|
||||
if (separator == ListSeparator.undecided && contents.length > 1) {
|
||||
if (separator == ListSeparator.undecided && asList.length > 1) {
|
||||
throw new ArgumentError(
|
||||
"A list with more than one element must have an explicit separator.");
|
||||
}
|
||||
@ -37,16 +42,16 @@ class SassList extends Value implements ext.SassList {
|
||||
T accept<T>(ValueVisitor<T> visitor) => visitor.visitList(this);
|
||||
|
||||
SassMap assertMap([String name]) =>
|
||||
contents.isEmpty ? const SassMap.empty() : super.assertMap(name);
|
||||
asList.isEmpty ? const SassMap.empty() : super.assertMap(name);
|
||||
|
||||
bool operator ==(other) =>
|
||||
(other is SassList &&
|
||||
other.separator == separator &&
|
||||
other.hasBrackets == hasBrackets &&
|
||||
listEquals(other.contents, contents)) ||
|
||||
(contents.isEmpty && other is SassMap && other.contents.isEmpty);
|
||||
listEquals(other.asList, asList)) ||
|
||||
(asList.isEmpty && other is SassMap && other.asList.isEmpty);
|
||||
|
||||
int get hashCode => listHash(contents);
|
||||
int get hashCode => listHash(asList);
|
||||
}
|
||||
|
||||
/// An enum of list separator types.
|
||||
|
@ -36,7 +36,7 @@ class SassMap extends Value implements ext.SassMap {
|
||||
bool operator ==(other) =>
|
||||
(other is SassMap &&
|
||||
const MapEquality().equals(other.contents, contents)) ||
|
||||
(contents.isEmpty && other is SassList && other.contents.isEmpty);
|
||||
(contents.isEmpty && other is SassList && other.asList.isEmpty);
|
||||
|
||||
int get hashCode => contents.isEmpty
|
||||
? const SassList.empty().hashCode
|
||||
|
@ -493,8 +493,8 @@ class _EvaluateVisitor
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns whether [value] is an empty [SassList].
|
||||
bool _isEmptyList(Value value) => value is SassList && value.contents.isEmpty;
|
||||
/// Returns whether [value] is an empty list.
|
||||
bool _isEmptyList(Value value) => value.asList.isEmpty;
|
||||
|
||||
Future<Value> visitEachRule(EachRule node) async {
|
||||
var list = await node.list.accept(this);
|
||||
|
@ -5,7 +5,7 @@
|
||||
// DO NOT EDIT. This file was generated from async_evaluate.dart.
|
||||
// See tool/synchronize.dart for details.
|
||||
//
|
||||
// Checksum: 0d20d8293daaad022a0a20115cc88b80704e2ad7
|
||||
// Checksum: 199b3bd52a5c5c147444ee45c2f3d46ef8af2d28
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
@ -492,8 +492,8 @@ class _EvaluateVisitor
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns whether [value] is an empty [SassList].
|
||||
bool _isEmptyList(Value value) => value is SassList && value.contents.isEmpty;
|
||||
/// Returns whether [value] is an empty list.
|
||||
bool _isEmptyList(Value value) => value.asList.isEmpty;
|
||||
|
||||
Value visitEachRule(EachRule node) {
|
||||
var list = node.list.accept(this);
|
||||
|
@ -512,7 +512,7 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
|
||||
void visitList(SassList value) {
|
||||
if (value.hasBrackets) {
|
||||
_buffer.writeCharCode($lbracket);
|
||||
} else if (value.contents.isEmpty) {
|
||||
} else if (value.asList.isEmpty) {
|
||||
if (!_inspect) {
|
||||
throw new SassScriptException("() isn't a valid CSS value");
|
||||
}
|
||||
@ -521,14 +521,14 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
|
||||
}
|
||||
|
||||
var singleton = _inspect &&
|
||||
value.contents.length == 1 &&
|
||||
value.asList.length == 1 &&
|
||||
value.separator == ListSeparator.comma;
|
||||
if (singleton && !value.hasBrackets) _buffer.writeCharCode($lparen);
|
||||
|
||||
_writeBetween<Value>(
|
||||
_inspect
|
||||
? value.contents
|
||||
: value.contents.where((element) => !element.isBlank),
|
||||
? value.asList
|
||||
: value.asList.where((element) => !element.isBlank),
|
||||
value.separator == ListSeparator.space ? " " : _commaSeparator,
|
||||
_inspect
|
||||
? (element) {
|
||||
@ -553,7 +553,7 @@ class _SerializeVisitor implements CssVisitor, ValueVisitor, SelectorVisitor {
|
||||
/// given [separator].
|
||||
bool _elementNeedsParens(ListSeparator separator, Value value) {
|
||||
if (value is SassList) {
|
||||
if (value.contents.length < 2) return false;
|
||||
if (value.asList.length < 2) return false;
|
||||
if (value.hasBrackets) return false;
|
||||
return separator == ListSeparator.comma
|
||||
? value.separator == ListSeparator.comma
|
||||
|
Loading…
Reference in New Issue
Block a user