mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 11:03:19 +00:00
Add missing methods to List and Map implementations.
Optimize FollowedBy when the operands have efficient length. Change-Id: I0af59240d70b929358c06b8d57a85df2deee6aaf Reviewed-on: https://dart-review.googlesource.com/43665 Commit-Queue: Lasse R.H. Nielsen <lrn@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com> Reviewed-by: Leaf Petersen <leafp@google.com>
This commit is contained in:
parent
4a11a27b53
commit
9ee735b659
|
@ -26,12 +26,14 @@ class InvocationImpl extends Invocation {
|
|||
namedArguments = _namedArgsToSymbols(namedArguments),
|
||||
typeArguments = typeArguments == null
|
||||
? const []
|
||||
: typeArguments.map(wrapType).toList();
|
||||
: new List.unmodifiable(typeArguments.map(wrapType));
|
||||
|
||||
static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
|
||||
if (namedArgs == null) return {};
|
||||
return new Map.fromIterable(getOwnPropertyNames(namedArgs),
|
||||
key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k));
|
||||
if (namedArgs == null) return const {};
|
||||
return new Map.unmodifiable(new Map.fromIterable(
|
||||
getOwnPropertyNames(namedArgs),
|
||||
key: _dartSymbol,
|
||||
value: (k) => JS('', '#[#]', namedArgs, k)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +208,7 @@ _toDisplayName(name) => JS('', '''(() => {
|
|||
// Names starting with _ are escaped names used to disambiguate Dart and
|
||||
// JS names.
|
||||
if ($name[0] === '_') {
|
||||
// Inverse of
|
||||
// Inverse of
|
||||
switch($name) {
|
||||
case '_get':
|
||||
return '[]';
|
||||
|
@ -293,7 +295,7 @@ _checkAndCall(f, ftype, obj, typeArgs, args, name) => JS('', '''(() => {
|
|||
// Apply type arguments
|
||||
if ($ftype instanceof $GenericFunctionType) {
|
||||
let formalCount = $ftype.formalCount;
|
||||
|
||||
|
||||
if ($typeArgs == null) {
|
||||
$typeArgs = $ftype.instantiateDefaultBounds();
|
||||
} else if ($typeArgs.length != formalCount) {
|
||||
|
|
|
@ -598,17 +598,10 @@ class JSArray<E> implements List<E>, JSIndexable<E> {
|
|||
Type get runtimeType =>
|
||||
dart.wrapType(JS('', '#(#)', dart.getGenericClass(List), E));
|
||||
|
||||
Iterable<E> followedBy(Iterable<E> other) sync* {
|
||||
yield* this;
|
||||
yield* other;
|
||||
}
|
||||
Iterable<E> followedBy(Iterable<E> other) =>
|
||||
new FollowedByIterable<E>.firstEfficient(this, other);
|
||||
|
||||
Iterable<T> whereType<T>() sync* {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
var element = this[i];
|
||||
if (element is T) yield element;
|
||||
}
|
||||
}
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
List<E> operator +(List<E> other) {
|
||||
int totalLength = this.length + other.length;
|
||||
|
|
|
@ -20,7 +20,7 @@ class _Vector extends core::Object {
|
|||
}
|
||||
operator *([@vm.inferred-type.metadata=#lib::_Vector] self::_Vector a) → core::double {
|
||||
core::double result = 0.0;
|
||||
for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
|
||||
for (core::int i = 0; i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
|
||||
result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] a.{self::_Vector::[]}(i)));
|
||||
return result;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class _Vector extends core::Object {
|
|||
[@vm.inferred-type.metadata=dart.core::_Double]static field core::double x = 0.0;
|
||||
static method main(core::List<core::String> args) → dynamic {
|
||||
core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t1.{core::Stopwatch::start}() in #t1;
|
||||
for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
|
||||
for (core::int i = 0; i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
|
||||
self::x = [@vm.direct-call.metadata=dart.core::_Double::+] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=dart.core::_Double] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=#lib::_Vector] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector] self::v));
|
||||
}
|
||||
[@vm.direct-call.metadata=dart.core::Stopwatch::stop] timer.{core::Stopwatch::stop}();
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
// whether a parameter was passed.
|
||||
class _GrowableArrayMarker implements int {
|
||||
const _GrowableArrayMarker();
|
||||
noSuchMethod(_) {
|
||||
throw new UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
|
||||
|
|
|
@ -1863,7 +1863,7 @@ class _Bigint extends _IntegerImplementation {
|
|||
}
|
||||
|
||||
// Interface for modular reduction.
|
||||
class _Reduction {
|
||||
abstract class _Reduction {
|
||||
// Return the number of digits used by r_digits.
|
||||
int _convert(_Bigint x, Uint32List r_digits);
|
||||
int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used,
|
||||
|
|
|
@ -5,12 +5,21 @@
|
|||
// part of "core_patch.dart";
|
||||
|
||||
/// Immutable map class for compiler generated map literals.
|
||||
// TODO(lrn): Extend MapBase with UnmodifiableMapMixin when mixins
|
||||
// support forwarding const constructors.
|
||||
class _ImmutableMap<K, V> implements Map<K, V> {
|
||||
final _ImmutableList _kvPairs;
|
||||
|
||||
const _ImmutableMap._create(_ImmutableList keyValuePairs)
|
||||
: _kvPairs = keyValuePairs;
|
||||
|
||||
Map<K2, V2> cast<K2, V2>() {
|
||||
Map<Object, Object> self = this;
|
||||
return (self is Map<K2, V2>) ? self : this.retype<K2, V2>();
|
||||
}
|
||||
|
||||
Map<K2, V2> retype<K2, V2>() => Map.castFrom<K, V, K2, V2>(this);
|
||||
|
||||
V operator [](Object key) {
|
||||
// To preserve the key-value order of the map literal, the keys are
|
||||
// not sorted. Need to do linear search or implement an additional
|
||||
|
@ -69,6 +78,10 @@ class _ImmutableMap<K, V> implements Map<K, V> {
|
|||
throw new UnsupportedError("Cannot set value in unmodifiable Map");
|
||||
}
|
||||
|
||||
void addAll(Map<K, V> other) {
|
||||
throw new UnsupportedError("Cannot set value in unmodifiable Map");
|
||||
}
|
||||
|
||||
V putIfAbsent(K key, V ifAbsent()) {
|
||||
throw new UnsupportedError("Cannot set value in unmodifiable Map");
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import "dart:_internal"
|
|||
ClassID,
|
||||
CodeUnits,
|
||||
ExpandIterable,
|
||||
FollowedByIterable,
|
||||
IterableElementError,
|
||||
ListMapView,
|
||||
Lists,
|
||||
|
@ -23,6 +24,7 @@ import "dart:_internal"
|
|||
SubListIterable,
|
||||
TakeWhileIterable,
|
||||
WhereIterable,
|
||||
WhereTypeIterable,
|
||||
patch;
|
||||
|
||||
import "dart:collection" show ListBase;
|
||||
|
@ -112,6 +114,11 @@ abstract class _IntListMixin implements List<int> {
|
|||
|
||||
List<int> _createList(int length);
|
||||
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
Iterable<int> followedBy(Iterable<int> other) =>
|
||||
new FollowedByIterable<int>.firstEfficient(this, other);
|
||||
|
||||
List<R> cast<R>() {
|
||||
List<Object> self = this;
|
||||
return self is List<R> ? self : List.castFrom<int, R>(this);
|
||||
|
@ -466,6 +473,11 @@ abstract class _DoubleListMixin implements List<double> {
|
|||
|
||||
List<double> _createList(int length);
|
||||
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
Iterable<double> followedBy(Iterable<double> other) =>
|
||||
new FollowedByIterable<double>.firstEfficient(this, other);
|
||||
|
||||
List<R> cast<R>() {
|
||||
List<Object> self = this;
|
||||
return self is List<R> ? self : List.castFrom<double, R>(this);
|
||||
|
@ -823,6 +835,11 @@ abstract class _Float32x4ListMixin implements List<Float32x4> {
|
|||
|
||||
List<Float32x4> _createList(int length);
|
||||
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
Iterable<Float32x4> followedBy(Iterable<Float32x4> other) =>
|
||||
new FollowedByIterable<Float32x4>.firstEfficient(this, other);
|
||||
|
||||
List<R> cast<R>() {
|
||||
List<Object> self = this;
|
||||
return self is List<R> ? self : List.castFrom<Float32x4, R>(this);
|
||||
|
@ -1184,6 +1201,11 @@ abstract class _Int32x4ListMixin implements List<Int32x4> {
|
|||
|
||||
List<Int32x4> _createList(int length);
|
||||
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
Iterable<Int32x4> followedBy(Iterable<Int32x4> other) =>
|
||||
new FollowedByIterable<Int32x4>.firstEfficient(this, other);
|
||||
|
||||
List<R> cast<R>() {
|
||||
List<Object> self = this;
|
||||
return self is List<R> ? self : List.castFrom<Int32x4, R>(this);
|
||||
|
@ -1544,6 +1566,11 @@ abstract class _Float64x2ListMixin implements List<Float64x2> {
|
|||
|
||||
List<Float64x2> _createList(int length);
|
||||
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
Iterable<Float64x2> followedBy(Iterable<Float64x2> other) =>
|
||||
new FollowedByIterable<Float64x2>.firstEfficient(this, other);
|
||||
|
||||
List<R> cast<R>() {
|
||||
List<Object> self = this;
|
||||
return self is List<R> ? self : List.castFrom<Float64x2, R>(this);
|
||||
|
|
|
@ -635,17 +635,10 @@ class JSArray<E> extends Interceptor implements List<E>, JSIndexable {
|
|||
return new ListMapView<E>(this);
|
||||
}
|
||||
|
||||
Iterable<E> followedBy(Iterable<E> other) sync* {
|
||||
yield* this;
|
||||
yield* other;
|
||||
}
|
||||
Iterable<E> followedBy(Iterable<E> other) =>
|
||||
new FollowedByIterable<E>.firstEfficient(this, other);
|
||||
|
||||
Iterable<T> whereType<T>() sync* {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
var element = this[i];
|
||||
if (element is T) yield element;
|
||||
}
|
||||
}
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
List<E> operator +(List<E> other) {
|
||||
int totalLength = this.length + other.length;
|
||||
|
|
|
@ -26,18 +26,19 @@ abstract class IterableMixin<E> implements Iterable<E> {
|
|||
|
||||
Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
|
||||
|
||||
Iterable<T> whereType<T>() sync* {
|
||||
for (Object element in this) if (element is T) yield element;
|
||||
}
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
Iterable<T> expand<T>(Iterable<T> f(E element)) =>
|
||||
new ExpandIterable<E, T>(this, f);
|
||||
|
||||
Iterable<E> followedBy(Iterable<E> other) sync* {
|
||||
// TODO(lrn): Optimize this (some operations can be more efficient,
|
||||
// and the concatenation has efficient length if the source iterables do).
|
||||
yield* this;
|
||||
yield* other;
|
||||
Iterable<E> followedBy(Iterable<E> other) {
|
||||
// Type workaround because IterableMixin<E> doesn't promote
|
||||
// to EfficientLengthIterable<E>.
|
||||
Iterable<E> self = this;
|
||||
if (self is EfficientLengthIterable<E>) {
|
||||
return new FollowedByIterable<E>.firstEfficient(self, other);
|
||||
}
|
||||
return new FollowedByIterable<E>(this, other);
|
||||
}
|
||||
|
||||
bool contains(Object element) {
|
||||
|
|
|
@ -59,12 +59,8 @@ abstract class ListMixin<E> implements List<E> {
|
|||
|
||||
E elementAt(int index) => this[index];
|
||||
|
||||
Iterable<E> followedBy(Iterable<E> other) sync* {
|
||||
for (var i = 0; i < length; i++) {
|
||||
yield this[i];
|
||||
}
|
||||
yield* other;
|
||||
}
|
||||
Iterable<E> followedBy(Iterable<E> other) =>
|
||||
new FollowedByIterable<E>.firstEfficient(this, other);
|
||||
|
||||
void forEach(void action(E element)) {
|
||||
int length = this.length;
|
||||
|
@ -195,9 +191,7 @@ abstract class ListMixin<E> implements List<E> {
|
|||
|
||||
Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test);
|
||||
|
||||
Iterable<T> whereType<T>() sync* {
|
||||
for (var element in this) if (element is T) yield (element as T);
|
||||
}
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
Iterable<T> map<T>(T f(E element)) => new MappedListIterable<E, T>(this, f);
|
||||
|
||||
|
|
|
@ -58,16 +58,10 @@ abstract class SetMixin<E> implements Set<E> {
|
|||
|
||||
Set<R> retype<R>() => Set.castFrom<E, R>(this);
|
||||
|
||||
Iterable<E> followedBy(Iterable<E> other) sync* {
|
||||
// TODO(lrn): Optimize this (some operations can be more efficient,
|
||||
// and the concatenation has efficient length if the source iterables do).
|
||||
yield* this;
|
||||
yield* other;
|
||||
}
|
||||
Iterable<E> followedBy(Iterable<E> other) =>
|
||||
new FollowedByIterable<E>.firstEfficient(this, other);
|
||||
|
||||
Iterable<T> whereType<T>() sync* {
|
||||
for (Object element in this) if (element is T) yield element;
|
||||
}
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
void clear() {
|
||||
removeAll(toList());
|
||||
|
|
|
@ -186,11 +186,11 @@ abstract class Iterable<E> {
|
|||
* and, after that, the elements of [other], in the same order as in the
|
||||
* original iterables.
|
||||
*/
|
||||
Iterable<E> followedBy(Iterable<E> other) sync* {
|
||||
// TODO(lrn): Optimize this (some operations can be more efficient,
|
||||
// and the concatenation has efficient length if the source iterables do).
|
||||
yield* this;
|
||||
yield* other;
|
||||
Iterable<E> followedBy(Iterable<E> other) {
|
||||
if (this is EfficientLengthIterable<E>) {
|
||||
return new FollowedByIterable<E>.firstEfficient(this, other);
|
||||
}
|
||||
return new FollowedByIterable<E>(this, other);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,9 +236,7 @@ abstract class Iterable<E> {
|
|||
* the returned [Iterable] may yield different results,
|
||||
* if the underlying elements change between iterations.
|
||||
*/
|
||||
Iterable<T> whereType<T>() sync* {
|
||||
for (var element in this) if (element is T) yield (element as T);
|
||||
}
|
||||
Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
|
||||
|
||||
/**
|
||||
* Expands each element of this [Iterable] into zero or more elements.
|
||||
|
|
|
@ -767,6 +767,125 @@ class EmptyIterator<E> implements Iterator<E> {
|
|||
E get current => null;
|
||||
}
|
||||
|
||||
class FollowedByIterable<E> extends Iterable<E> {
|
||||
final Iterable<E> _first;
|
||||
final Iterable<E> _second;
|
||||
FollowedByIterable(this._first, this._second);
|
||||
|
||||
factory FollowedByIterable.firstEfficient(
|
||||
EfficientLengthIterable<E> first, Iterable<E> second) {
|
||||
if (second is EfficientLengthIterable<E>) {
|
||||
return new EfficientLengthFollowedByIterable<E>(first, second);
|
||||
}
|
||||
return new FollowedByIterable<E>(first, second);
|
||||
}
|
||||
|
||||
Iterator<E> get iterator => new FollowedByIterator(_first, _second);
|
||||
|
||||
int get length => _first.length + _second.length;
|
||||
bool get isEmpty => _first.isEmpty && _second.isEmpty;
|
||||
bool get isNotEmpty => _first.isNotEmpty || _second.isNotEmpty;
|
||||
|
||||
// May be more efficient if either iterable is a Set.
|
||||
bool contains(Object value) =>
|
||||
_first.contains(value) || _second.contains(value);
|
||||
|
||||
E get first {
|
||||
var iterator = _first.iterator;
|
||||
if (iterator.moveNext()) return iterator.current;
|
||||
return _second.first;
|
||||
}
|
||||
|
||||
E get last {
|
||||
var iterator = _second.iterator;
|
||||
if (iterator.moveNext()) {
|
||||
E last = iterator.current;
|
||||
while (iterator.moveNext()) last = iterator.current;
|
||||
return last;
|
||||
}
|
||||
return _first.last;
|
||||
}
|
||||
|
||||
// If linear sequences of `followedBy` becomes an issue, we can flatten
|
||||
// into a list of iterables instead of a tree or spine.
|
||||
}
|
||||
|
||||
class EfficientLengthFollowedByIterable<E> extends FollowedByIterable<E>
|
||||
implements EfficientLengthIterable<E> {
|
||||
EfficientLengthFollowedByIterable(
|
||||
EfficientLengthIterable<E> first, EfficientLengthIterable<E> second)
|
||||
: super(first, second);
|
||||
|
||||
Iterable<E> skip(int count) {
|
||||
int firstLength = _first.length;
|
||||
if (count >= firstLength) return _second.skip(count - firstLength);
|
||||
return new EfficientLengthFollowedByIterable<E>(
|
||||
_first.skip(count), _second);
|
||||
}
|
||||
|
||||
Iterable<E> take(int count) {
|
||||
int firstLength = _first.length;
|
||||
if (count <= firstLength) return _first.take(count);
|
||||
return new EfficientLengthFollowedByIterable<E>(
|
||||
_first, _second.take(count - firstLength));
|
||||
}
|
||||
|
||||
E elementAt(int index) {
|
||||
int firstLength = _first.length;
|
||||
if (index < firstLength) return _first.elementAt(index);
|
||||
return _second.elementAt(index - firstLength);
|
||||
}
|
||||
|
||||
E get first {
|
||||
if (_first.isNotEmpty) return _first.first;
|
||||
return _second.first;
|
||||
}
|
||||
|
||||
E get last {
|
||||
if (_second.isNotEmpty) return _second.last;
|
||||
return _first.last;
|
||||
}
|
||||
}
|
||||
|
||||
class FollowedByIterator<E> implements Iterator<E> {
|
||||
Iterator<E> _currentIterator;
|
||||
Iterable<E> _nextIterable;
|
||||
|
||||
FollowedByIterator(Iterable<E> first, this._nextIterable)
|
||||
: _currentIterator = first.iterator;
|
||||
|
||||
bool moveNext() {
|
||||
if (_currentIterator.moveNext()) return true;
|
||||
if (_nextIterable != null) {
|
||||
_currentIterator = _nextIterable.iterator;
|
||||
_nextIterable = null;
|
||||
return _currentIterator.moveNext();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
E get current => _currentIterator.current;
|
||||
}
|
||||
|
||||
class WhereTypeIterable<T> extends Iterable<T> {
|
||||
final Iterable<Object> _source;
|
||||
WhereTypeIterable(this._source);
|
||||
Iterator<T> get iterator => new WhereTypeIterator<T>(_source.iterator);
|
||||
}
|
||||
|
||||
class WhereTypeIterator<T> implements Iterator<T> {
|
||||
final Iterator<Object> _source;
|
||||
WhereTypeIterator(this._source);
|
||||
bool moveNext() {
|
||||
while (_source.moveNext()) {
|
||||
if (_source.current is T) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
T get current => _source.current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates errors throw by [Iterable] when the element count is wrong.
|
||||
*/
|
||||
|
|
|
@ -18,25 +18,7 @@ import 'package:async_helper/async_helper.dart';
|
|||
* the error/warning message in the list of white-listings for each file.
|
||||
*/
|
||||
// TODO(johnniwinther): Support canonical URIs as keys.
|
||||
const Map<String, List<String>> WHITE_LIST = const {
|
||||
"sdk/lib/_internal/js_runtime/lib/js_array.dart": const [
|
||||
"Method type variables do not have a runtime value.",
|
||||
],
|
||||
"sdk/lib/collection/iterable.dart": const [
|
||||
"Method type variables do not have a runtime value.",
|
||||
],
|
||||
"sdk/lib/collection/list.dart": const [
|
||||
"Method type variables do not have a runtime value.",
|
||||
"Method type variables are treated as `dynamic` in `as` expressions.",
|
||||
],
|
||||
"sdk/lib/collection/set.dart": const [
|
||||
"Method type variables do not have a runtime value.",
|
||||
],
|
||||
"sdk/lib/core/iterable.dart": const [
|
||||
"Method type variables do not have a runtime value.",
|
||||
"Method type variables are treated as `dynamic` in `as` expressions.",
|
||||
],
|
||||
};
|
||||
const Map<String, List<String>> WHITE_LIST = const {};
|
||||
|
||||
void main() {
|
||||
var uriList = new List<Uri>();
|
||||
|
|
|
@ -28,12 +28,6 @@ void main() {
|
|||
"memory:library.dart:41:47:'hest' is defined here.:info",
|
||||
"MessageKind.DUPLICATE_IMPORT:"
|
||||
"memory:main.dart:86:92:Duplicate import of 'hest'.:warning",
|
||||
"MessageKind.HIDDEN_WARNINGS:"
|
||||
"null:null:null:1 warning(s) suppressed in dart:_interceptors.:hint",
|
||||
"MessageKind.HIDDEN_WARNINGS_HINTS:"
|
||||
"null:null:null:1 warning(s) and 1 hint(s) suppressed in dart:core.:hint",
|
||||
"MessageKind.HIDDEN_WARNINGS_HINTS:"
|
||||
"null:null:null:3 warning(s) and 1 hint(s) suppressed in dart:collection.:hint",
|
||||
"MessageKind.IMPORTED_HERE:"
|
||||
"memory:main.dart:0:22:'hest' is imported here.:info",
|
||||
"MessageKind.IMPORTED_HERE:"
|
||||
|
|
|
@ -14,7 +14,7 @@ import '../memory_compiler.dart';
|
|||
|
||||
void check(String kind, Iterable<CollectedMessage> messages,
|
||||
List<MessageKind> expectedMessageKinds) {
|
||||
Expect.equals(messages.length, expectedMessageKinds.length,
|
||||
Expect.equals(expectedMessageKinds.length, messages.length,
|
||||
"Unexpected $kind count: $messages");
|
||||
int i = 0;
|
||||
messages.forEach((CollectedMessage message) {
|
||||
|
@ -56,11 +56,7 @@ library lib.foo;
|
|||
"""
|
||||
}, warnings: [
|
||||
MessageKind.DUPLICATED_LIBRARY_RESOURCE
|
||||
], hints: [
|
||||
MessageKind.HIDDEN_WARNINGS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
]);
|
||||
], hints: []);
|
||||
|
||||
await test({
|
||||
'main.dart': """
|
||||
|
@ -79,11 +75,7 @@ library lib.bar;
|
|||
"""
|
||||
}, warnings: [
|
||||
MessageKind.DUPLICATED_LIBRARY_RESOURCE
|
||||
], hints: [
|
||||
MessageKind.HIDDEN_WARNINGS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
]);
|
||||
], hints: []);
|
||||
|
||||
await test({
|
||||
'main.dart': """
|
||||
|
@ -102,11 +94,7 @@ library lib.baz;
|
|||
"""
|
||||
}, warnings: [
|
||||
MessageKind.DUPLICATED_LIBRARY_RESOURCE
|
||||
], hints: [
|
||||
MessageKind.HIDDEN_WARNINGS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
]);
|
||||
], hints: []);
|
||||
|
||||
await test({
|
||||
'main.dart': """
|
||||
|
@ -130,11 +118,7 @@ library lib.boz;
|
|||
"""
|
||||
}, warnings: [
|
||||
MessageKind.DUPLICATED_LIBRARY_RESOURCE
|
||||
], hints: [
|
||||
MessageKind.HIDDEN_WARNINGS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
]);
|
||||
], hints: []);
|
||||
|
||||
await test({
|
||||
'main.dart': """
|
||||
|
@ -148,9 +132,6 @@ import 'pkg/lib/qux.dart';
|
|||
"""
|
||||
}, hints: [
|
||||
MessageKind.DUPLICATED_RESOURCE,
|
||||
MessageKind.HIDDEN_WARNINGS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
]);
|
||||
|
||||
await test({
|
||||
|
@ -169,9 +150,5 @@ library lib;
|
|||
}, warnings: [
|
||||
MessageKind.DUPLICATED_LIBRARY_NAME,
|
||||
MessageKind.DUPLICATED_LIBRARY_NAME
|
||||
], hints: [
|
||||
MessageKind.HIDDEN_WARNINGS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
MessageKind.HIDDEN_WARNINGS_HINTS,
|
||||
]);
|
||||
], hints: []);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ int_parse_radix_bad_handler_test: MissingCompileTimeError
|
|||
iterable_element_at_test/static: Pass
|
||||
num_sign_test: Crash, Pass # Issue 31768
|
||||
|
||||
[ $compiler == dart2js ]
|
||||
iterable_where_type_test: RuntimeError # issue 31718
|
||||
|
||||
[ $compiler != dartdevc ]
|
||||
error_stack_trace_test/static: MissingCompileTimeError
|
||||
|
||||
|
|
102
tests/corelib_2/iterable_followed_by_test.dart
Normal file
102
tests/corelib_2/iterable_followed_by_test.dart
Normal file
|
@ -0,0 +1,102 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "dart:collection" show Queue;
|
||||
import "dart:typed_data" show Int32List;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
// Tests behavior of result of an operation on a followedBy iterable.
|
||||
test(List expects, Iterable iterable, [String name]) {
|
||||
try {
|
||||
Expect.isFalse(iterable is List, "$name is! List");
|
||||
Expect.isFalse(iterable is Set, "$name is! Set");
|
||||
Expect.isFalse(iterable is Queue, "$name is! Queue");
|
||||
if (expects.isNotEmpty) {
|
||||
Expect.equals(expects.first, iterable.first, "$name: first");
|
||||
Expect.equals(expects.last, iterable.last, "$name: last");
|
||||
} else {
|
||||
Expect.throwsStateError(() => iterable.first, "$name: first");
|
||||
Expect.throwsStateError(() => iterable.last, "$name: last");
|
||||
}
|
||||
var it = iterable.iterator;
|
||||
for (int index = 0; index < expects.length; index++) {
|
||||
Expect.isTrue(it.moveNext(), "$name: has element $index");
|
||||
var expect = expects[index];
|
||||
Expect.equals(expect, it.current, "$name at $index");
|
||||
Expect.equals(
|
||||
expect, iterable.elementAt(index), "$name: elementAt($index)");
|
||||
Expect.isTrue(iterable.contains(expect), "$name:contains $index");
|
||||
}
|
||||
Expect.isFalse(it.moveNext(),
|
||||
"$name: extra element at ${expects.length}: ${it.current}");
|
||||
} on Error {
|
||||
print("Failed during: $name");
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// Tests various operations on the a followedBy iterable.
|
||||
tests(List<int> expects, Iterable<int> follow, [String name]) {
|
||||
int length = expects.length;
|
||||
test(expects, follow, name);
|
||||
for (int i = 0; i <= length; i++) {
|
||||
test(expects.sublist(i), follow.skip(i), "$name.skip($i)");
|
||||
}
|
||||
for (int i = 0; i <= length; i++) {
|
||||
test(expects.sublist(0, i), follow.take(i), "$name.take($i)");
|
||||
}
|
||||
for (int i = 0; i <= length; i++) {
|
||||
for (int j = 0; j <= length - i; j++) {
|
||||
test(expects.sublist(i, i + j), follow.skip(i).take(j),
|
||||
"$name.skiptake($i,${i+j})");
|
||||
test(expects.sublist(i, i + j), follow.take(i + j).skip(i),
|
||||
"$name.takeskip($i,${i+j})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests various different types of iterables as first and second operand.
|
||||
types(List expects, List<int> first, List<int> second, [String name]) {
|
||||
var conversions = <String, Iterable<int> Function(List<int>)>{
|
||||
"const": toConst,
|
||||
"list": toList,
|
||||
"unmod": toUnmodifiable,
|
||||
"set": toSet,
|
||||
"queue": toQueue,
|
||||
"eff-len-iter": toELIter,
|
||||
"non-eff-iter": toNEIter,
|
||||
"typed": toTyped,
|
||||
"keys": toKeys,
|
||||
"values": toValues,
|
||||
};
|
||||
conversions.forEach((n1, c1) {
|
||||
conversions.forEach((n2, c2) {
|
||||
tests(expects, c1(first).followedBy(c2(second)), "$name:$n1/$n2");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
List<int> toConst(List<int> elements) => elements;
|
||||
List<int> toList(List<int> elements) => elements.toList();
|
||||
List<int> toUnmodifiable(List<int> elements) =>
|
||||
new List<int>.unmodifiable(elements);
|
||||
Set<int> toSet(List<int> elements) => elements.toSet();
|
||||
Queue<int> toQueue(List<int> elements) => new Queue<int>.from(elements);
|
||||
// Creates an efficient-length iterable.
|
||||
Iterable<int> toELIter(List<int> elements) => elements.map<int>((x) => x);
|
||||
// Creates a non-efficient-length iterable.
|
||||
Iterable<int> toNEIter(List<int> elements) => elements.where((x) => true);
|
||||
List<int> toTyped(List<int> elements) => new Int32List.fromList(elements);
|
||||
Iterable<int> toKeys(List<int> elements) =>
|
||||
new Map<int, int>.fromIterables(elements, elements).keys;
|
||||
Iterable<int> toValues(List<int> elements) =>
|
||||
new Map<int, int>.fromIterables(elements, elements).values;
|
||||
|
||||
main() {
|
||||
types(<int>[], const <int>[], const <int>[], "0+0");
|
||||
types(<int>[1, 2, 3, 4], const <int>[], const <int>[1, 2, 3, 4], "0+4");
|
||||
types(<int>[1, 2, 3, 4], const <int>[1, 2], const <int>[3, 4], "2+2");
|
||||
types(<int>[1, 2, 3, 4], const <int>[1, 2, 3, 4], const <int>[], "4+0");
|
||||
}
|
105
tests/corelib_2/iterable_where_type_test.dart
Normal file
105
tests/corelib_2/iterable_where_type_test.dart
Normal file
|
@ -0,0 +1,105 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "dart:collection" show Queue;
|
||||
import "dart:typed_data" show Int32List;
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
// Tests behavior of result of an operation on a followedBy iterable.
|
||||
test(List expects, Iterable iterable, [String name]) {
|
||||
try {
|
||||
Expect.isFalse(iterable is List, "$name is! List");
|
||||
Expect.isFalse(iterable is Set, "$name is! Set");
|
||||
Expect.isFalse(iterable is Queue, "$name is! Queue");
|
||||
if (expects.isNotEmpty) {
|
||||
Expect.equals(expects.first, iterable.first, "$name: first");
|
||||
Expect.equals(expects.last, iterable.last, "$name: last");
|
||||
} else {
|
||||
Expect.throwsStateError(() => iterable.first, "$name: first");
|
||||
Expect.throwsStateError(() => iterable.last, "$name: last");
|
||||
}
|
||||
var it = iterable.iterator;
|
||||
for (int index = 0; index < expects.length; index++) {
|
||||
Expect.isTrue(it.moveNext(), "$name: has element $index");
|
||||
var expect = expects[index];
|
||||
Expect.equals(expect, it.current, "$name at $index");
|
||||
Expect.equals(
|
||||
expect, iterable.elementAt(index), "$name: elementAt($index)");
|
||||
Expect.isTrue(iterable.contains(expect), "$name:contains $index");
|
||||
}
|
||||
Expect.isFalse(it.moveNext(),
|
||||
"$name: extra element at ${expects.length}: ${it.current}");
|
||||
} on Error {
|
||||
print("Failed during: $name");
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
var conversions = <String, Iterable<int> Function(List<int>)>{
|
||||
"const": toConst,
|
||||
"list": toList,
|
||||
"unmod": toUnmodifiable,
|
||||
"set": toSet,
|
||||
"queue": toQueue,
|
||||
"eff-len-iter": toELIter,
|
||||
"non-eff-iter": toNEIter,
|
||||
"typed": toTyped,
|
||||
"keys": toKeys,
|
||||
"values": toValues,
|
||||
};
|
||||
for (var data in [
|
||||
const <int>[],
|
||||
const <int>[1],
|
||||
const <int>[1, 2, 3]
|
||||
]) {
|
||||
conversions.forEach((name, c) {
|
||||
test(data, c(data).whereType<int>(), "$name#${data.length}.wt<int>");
|
||||
test(data, c(data).whereType<num>(), "$name#${data.length}.wt<num>");
|
||||
test([], c(data).whereType<Null>(), "$name#${data.length}.wt<Null>");
|
||||
});
|
||||
}
|
||||
|
||||
test([1, 0.1], ["a", 1, new Object(), 0.1, null].whereType<num>(), "mixed");
|
||||
|
||||
var o = new Object();
|
||||
var a = new A();
|
||||
var b = new B();
|
||||
var c = new C();
|
||||
var d = new D();
|
||||
var n = null;
|
||||
test([o, a, b, c, d, n], [o, a, b, c, d, n].whereType<Object>(), "Object");
|
||||
test([a, b, c, d], [o, a, b, c, d, n].whereType<A>(), "A");
|
||||
test([b, d], [o, a, b, c, d, n].whereType<B>(), "B");
|
||||
test([c, d], [o, a, b, c, d, n].whereType<C>(), "C");
|
||||
test([d], [o, a, b, c, d, n].whereType<D>(), "D");
|
||||
test([n], [o, a, b, c, d, n].whereType<Null>(), "Null");
|
||||
|
||||
test([d], <B>[d].whereType<C>(), "Unrelated");
|
||||
}
|
||||
|
||||
class A {}
|
||||
|
||||
class B implements A {}
|
||||
|
||||
class C implements A {}
|
||||
|
||||
class D implements B, C {}
|
||||
|
||||
List<int> toConst(List<int> elements) => elements; // Argument is const.
|
||||
List<int> toList(List<int> elements) => elements.toList();
|
||||
List<int> toUnmodifiable(List<int> elements) =>
|
||||
new List<int>.unmodifiable(elements);
|
||||
Set<int> toSet(List<int> elements) => elements.toSet();
|
||||
Queue<int> toQueue(List<int> elements) => new Queue<int>.from(elements);
|
||||
// Creates an efficient-length iterable.
|
||||
Iterable<int> toELIter(List<int> elements) => elements.map<int>((x) => x);
|
||||
// Creates a non-efficient-length iterable.
|
||||
Iterable<int> toNEIter(List<int> elements) => elements.where((x) => true);
|
||||
List<int> toTyped(List<int> elements) => new Int32List.fromList(elements);
|
||||
Iterable<int> toKeys(List<int> elements) =>
|
||||
new Map<int, int>.fromIterables(elements, elements).keys;
|
||||
Iterable<int> toValues(List<int> elements) =>
|
||||
new Map<int, int>.fromIterables(elements, elements).values;
|
|
@ -8,45 +8,76 @@ import "package:expect/expect.dart";
|
|||
import 'dart:collection';
|
||||
|
||||
void main() {
|
||||
test(const {1: 37});
|
||||
test(new UnmodifiableMapView({1: 37}));
|
||||
testNum(const {1: 37}, "const");
|
||||
testNum(const <num, num>{1: 37}.cast<int, int>(), "const.cast");
|
||||
testNum(const <num, num>{1: 37}.retype<int, int>(), "const.retype");
|
||||
|
||||
test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}));
|
||||
test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}));
|
||||
testNum(new UnmodifiableMapView({1: 37}), "unmod");
|
||||
testNum(new UnmodifiableMapView<num, num>(<num, num>{1: 37}), "unmod.cast");
|
||||
testNum(new UnmodifiableMapView<num, num>(<int, int>{1: 37}), "unmod.retype");
|
||||
|
||||
test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).cast<int, int>());
|
||||
test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).cast<int, int>());
|
||||
test(new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
|
||||
.cast<int, int>());
|
||||
test(new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
|
||||
.cast<num, num>());
|
||||
testNum(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).cast<int, int>(),
|
||||
"unmodView<num>.cast<int>");
|
||||
testNum(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).cast<int, int>(),
|
||||
"unmodView<int>.cast<int>");
|
||||
testNum(
|
||||
new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
|
||||
.cast<int, int>(),
|
||||
"unmodView<Object>(num).cast<int>");
|
||||
testNum(
|
||||
new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
|
||||
.cast<num, num>(),
|
||||
"unmodView<Object>(int).cast<num>");
|
||||
|
||||
test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).retype<int, int>());
|
||||
test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).retype<int, int>());
|
||||
test(new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
|
||||
.retype<int, int>());
|
||||
test(new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
|
||||
.retype<num, num>());
|
||||
testNum(
|
||||
new UnmodifiableMapView<num, num>(<num, num>{1: 37}).retype<int, int>(),
|
||||
"unmodView<num>(num).retype<int>");
|
||||
testNum(
|
||||
new UnmodifiableMapView<num, num>(<int, int>{1: 37}).retype<int, int>(),
|
||||
"unmodView<num>(int).retype<int>");
|
||||
testNum(
|
||||
new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
|
||||
.retype<int, int>(),
|
||||
"unmodView<Object>(num).retype<int>");
|
||||
testNum(
|
||||
new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
|
||||
.retype<num, num>(),
|
||||
"unmodView<Object>(int).retype<num>");
|
||||
|
||||
var m2 = new Map<num, num>.unmodifiable({1: 37});
|
||||
test(m2);
|
||||
test(m2.cast<int, int>());
|
||||
testNum(m2, "Map<num>.unmod");
|
||||
testNum(m2.cast<int, int>(), "Map<num>.unmod.cast<int>");
|
||||
|
||||
Map<Symbol, dynamic> nsm = new NsmMap().foo(a: 0);
|
||||
test(nsm, #a, 0, "nsm");
|
||||
test(nsm.cast<Object, int>(), #a, 0, "nsm.cast");
|
||||
test(nsm.retype<Object, int>(), #a, 0, "nsm.retype");
|
||||
}
|
||||
|
||||
void test(Map map) {
|
||||
Expect.isTrue(map.containsKey(1));
|
||||
Expect.equals(1, map.length);
|
||||
Expect.equals(1, map.keys.first);
|
||||
Expect.equals(37, map.values.first);
|
||||
|
||||
Expect.throws(map.clear);
|
||||
Expect.throws(() {
|
||||
map.remove(1);
|
||||
});
|
||||
Expect.throws(() {
|
||||
map[2] = 42;
|
||||
});
|
||||
Expect.throws(() {
|
||||
map.addAll(<int, int>{2: 42});
|
||||
});
|
||||
void testNum(Map<Object, Object> map, String name) {
|
||||
test(map, 1, 37, name);
|
||||
}
|
||||
|
||||
void test(
|
||||
Map<Object, Object> map, Object firstKey, Object firstValue, String name) {
|
||||
Expect.isTrue(map.containsKey(firstKey), "$name.containsKey");
|
||||
Expect.equals(1, map.length, "$name.length");
|
||||
Expect.equals(firstKey, map.keys.first, "$name.keys.first");
|
||||
Expect.equals(firstValue, map.values.first, "$name.values.first");
|
||||
|
||||
Expect.throwsUnsupportedError(map.clear, "$name.clear");
|
||||
Expect.throwsUnsupportedError(() {
|
||||
map.remove(firstKey);
|
||||
}, "$name.remove");
|
||||
Expect.throwsUnsupportedError(() {
|
||||
map[null] = null;
|
||||
}, "$name[]=");
|
||||
Expect.throwsUnsupportedError(() {
|
||||
map.addAll(<Null, Null>{null: null});
|
||||
}, "$name.addAll");
|
||||
}
|
||||
|
||||
class NsmMap {
|
||||
noSuchMethod(i) => i.namedArguments;
|
||||
foo({a, b, c, d});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue