2016-05-24 20:56:53 +02:00
|
|
|
// Copyright 2016 Google Inc. Use of this source code is governed by an
|
|
|
|
// MIT-style license that can be found in the LICENSE file or at
|
|
|
|
// https://opensource.org/licenses/MIT.
|
|
|
|
|
2016-08-15 07:32:00 +02:00
|
|
|
import '../utils.dart';
|
2016-08-15 08:51:29 +02:00
|
|
|
import '../visitor/interface/value.dart';
|
2016-05-24 20:56:53 +02:00
|
|
|
import '../value.dart';
|
2018-01-13 10:30:42 +01:00
|
|
|
import 'external/value.dart' as ext;
|
2016-05-24 20:56:53 +02:00
|
|
|
|
2018-01-13 10:30:42 +01:00
|
|
|
class SassList extends Value implements ext.SassList {
|
2018-02-03 02:36:29 +01:00
|
|
|
// 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;
|
2016-05-24 20:56:53 +02:00
|
|
|
|
|
|
|
final ListSeparator separator;
|
|
|
|
|
2016-09-22 18:20:32 +02:00
|
|
|
final bool hasBrackets;
|
2016-08-15 00:49:50 +02:00
|
|
|
|
2018-02-03 02:36:29 +01:00
|
|
|
bool get isBlank => asList.every((element) => element.isBlank);
|
2016-06-03 22:36:20 +02:00
|
|
|
|
2018-02-03 02:36:29 +01:00
|
|
|
List<Value> get asList => _contents;
|
2016-09-07 19:18:30 +02:00
|
|
|
|
2018-02-03 02:36:29 +01:00
|
|
|
int get lengthAsList => asList.length;
|
2018-01-14 22:38:43 +01:00
|
|
|
|
2016-09-22 19:13:54 +02:00
|
|
|
const SassList.empty({ListSeparator separator, bool brackets: false})
|
2018-02-03 02:36:29 +01:00
|
|
|
: _contents = const [],
|
2016-09-22 19:13:54 +02:00
|
|
|
separator = separator ?? ListSeparator.undecided,
|
|
|
|
hasBrackets = brackets;
|
|
|
|
|
2016-09-22 18:20:32 +02:00
|
|
|
SassList(Iterable<Value> contents, this.separator, {bool brackets: false})
|
2018-02-03 02:36:29 +01:00
|
|
|
: _contents = new List.unmodifiable(contents),
|
2016-09-22 18:27:01 +02:00
|
|
|
hasBrackets = brackets {
|
2018-02-03 02:36:29 +01:00
|
|
|
if (separator == ListSeparator.undecided && asList.length > 1) {
|
2016-09-22 18:27:01 +02:00
|
|
|
throw new ArgumentError(
|
|
|
|
"A list with more than one element must have an explicit separator.");
|
|
|
|
}
|
|
|
|
}
|
2016-05-24 20:56:53 +02:00
|
|
|
|
2017-05-19 01:47:22 +02:00
|
|
|
T accept<T>(ValueVisitor<T> visitor) => visitor.visitList(this);
|
2016-05-28 01:09:03 +02:00
|
|
|
|
2016-09-22 19:13:54 +02:00
|
|
|
SassMap assertMap([String name]) =>
|
2018-02-03 02:36:29 +01:00
|
|
|
asList.isEmpty ? const SassMap.empty() : super.assertMap(name);
|
2016-09-22 19:13:54 +02:00
|
|
|
|
2016-08-15 07:32:00 +02:00
|
|
|
bool operator ==(other) =>
|
2016-09-22 19:13:54 +02:00
|
|
|
(other is SassList &&
|
|
|
|
other.separator == separator &&
|
|
|
|
other.hasBrackets == hasBrackets &&
|
2018-02-03 02:36:29 +01:00
|
|
|
listEquals(other.asList, asList)) ||
|
|
|
|
(asList.isEmpty && other is SassMap && other.asList.isEmpty);
|
2016-08-15 07:32:00 +02:00
|
|
|
|
2018-02-03 02:36:29 +01:00
|
|
|
int get hashCode => listHash(asList);
|
2016-05-24 20:56:53 +02:00
|
|
|
}
|
|
|
|
|
2016-10-15 11:57:29 +02:00
|
|
|
/// An enum of list separator types.
|
2016-05-24 20:56:53 +02:00
|
|
|
class ListSeparator {
|
2016-10-15 11:57:29 +02:00
|
|
|
/// A space-separated list.
|
2017-05-25 21:56:12 +02:00
|
|
|
static const space = const ListSeparator._("space", " ");
|
2016-10-15 11:57:29 +02:00
|
|
|
|
|
|
|
/// A comma-separated list.
|
2017-05-25 21:56:12 +02:00
|
|
|
static const comma = const ListSeparator._("comma", ",");
|
2016-10-15 11:57:29 +02:00
|
|
|
|
|
|
|
/// A separator that hasn't yet been determined.
|
|
|
|
///
|
|
|
|
/// Singleton lists and empty lists don't have separators defiend. This means
|
|
|
|
/// that list functions will prefer other lists' separators if possible.
|
2017-05-25 21:56:12 +02:00
|
|
|
static const undecided = const ListSeparator._("undecided", null);
|
2016-05-24 20:56:53 +02:00
|
|
|
|
2016-10-15 11:57:29 +02:00
|
|
|
final String _name;
|
2016-05-24 20:56:53 +02:00
|
|
|
|
2017-05-25 21:56:12 +02:00
|
|
|
/// The separator character.
|
|
|
|
///
|
|
|
|
/// If the separator of a list has not been decided, this value will be
|
|
|
|
/// `null`.
|
|
|
|
final String separator;
|
|
|
|
|
|
|
|
const ListSeparator._(this._name, this.separator);
|
2016-05-24 20:56:53 +02:00
|
|
|
|
2016-10-15 11:57:29 +02:00
|
|
|
String toString() => _name;
|
2016-05-24 20:56:53 +02:00
|
|
|
}
|