mirror of
https://github.com/dart-lang/sdk
synced 2024-10-03 00:09:20 +00:00
Add Object.hash
and Object.hashAll
static helper methods.
Fixes #11617. Bug: http://dartbug.com/11617 Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/73360 Commit-Queue: Lasse R.H. Nielsen <lrn@google.com> Reviewed-by: Nate Bosch <nbosch@google.com> Reviewed-by: Stephen Adams <sra@google.com>
This commit is contained in:
parent
843bd00c71
commit
83376bf1ee
|
@ -27,6 +27,10 @@
|
|||
daylight saving changes that are not precisely one hour.
|
||||
(No change on the Web which uses the JavaScript `Date` object.)
|
||||
|
||||
* Adds static methods `hash`, `hashAll` and `hashAllUnordered` to the
|
||||
`Object` class. These can be used to combine the hash codes of
|
||||
multiple objects in a consistent way.
|
||||
|
||||
#### `dart:ffi`
|
||||
|
||||
* Adds the `DynamicLibrary.providesSymbol` function to check whether a symbol
|
||||
|
|
|
@ -146,4 +146,418 @@ class Object {
|
|||
|
||||
/// A representation of the runtime type of the object.
|
||||
external Type get runtimeType;
|
||||
|
||||
/// Creates a combined hash code for a number of objects.
|
||||
///
|
||||
/// The hash code is computed for all arguments that are actually
|
||||
/// supplied, even if they are `null`, by numerically combining the
|
||||
/// [Object.hashCode] of each argument.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// class SomeObject {
|
||||
/// final Object a, b, c;
|
||||
/// SomeObject(this.a, this.b, this.c);
|
||||
/// bool operator=(Object other) =>
|
||||
/// other is SomeObject && a == other.a && b == other.b && c == other.c;
|
||||
/// int get hashCode => Object.hash(a, b, c);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The computed value will be consistent when the function is called
|
||||
/// with the same arguments multiple times
|
||||
/// during the execution of a single program.
|
||||
///
|
||||
/// The hash value generated by this function is *not* guaranteed to be stable
|
||||
/// over different runs of the same program,
|
||||
/// or between code run in different isolates of the same program.
|
||||
/// The exact algorithm used may differ between different platforms,
|
||||
/// or between different versions of the platform libraries,
|
||||
/// and it may depend on values that change on each program execution.
|
||||
///
|
||||
/// The [hashAll] function gives the same result as this function when
|
||||
/// called with a collection containing the actual arguments
|
||||
/// to this function in the same order.
|
||||
@Since("2.14")
|
||||
static int hash(Object? object1, Object? object2,
|
||||
[Object? object3 = sentinelValue,
|
||||
Object? object4 = sentinelValue,
|
||||
Object? object5 = sentinelValue,
|
||||
Object? object6 = sentinelValue,
|
||||
Object? object7 = sentinelValue,
|
||||
Object? object8 = sentinelValue,
|
||||
Object? object9 = sentinelValue,
|
||||
Object? object10 = sentinelValue,
|
||||
Object? object11 = sentinelValue,
|
||||
Object? object12 = sentinelValue,
|
||||
Object? object13 = sentinelValue,
|
||||
Object? object14 = sentinelValue,
|
||||
Object? object15 = sentinelValue,
|
||||
Object? object16 = sentinelValue,
|
||||
Object? object17 = sentinelValue,
|
||||
Object? object18 = sentinelValue,
|
||||
Object? object19 = sentinelValue,
|
||||
Object? object20 = sentinelValue]) {
|
||||
if (sentinelValue == object3) {
|
||||
return SystemHash.hash2(object1.hashCode, object2.hashCode, _hashSeed);
|
||||
}
|
||||
if (sentinelValue == object4) {
|
||||
return SystemHash.hash3(
|
||||
object1.hashCode, object2.hashCode, object3.hashCode, _hashSeed);
|
||||
}
|
||||
if (sentinelValue == object5) {
|
||||
return SystemHash.hash4(object1.hashCode, object2.hashCode,
|
||||
object3.hashCode, object4.hashCode, _hashSeed);
|
||||
}
|
||||
if (sentinelValue == object6) {
|
||||
return SystemHash.hash5(object1.hashCode, object2.hashCode,
|
||||
object3.hashCode, object4.hashCode, object5.hashCode, _hashSeed);
|
||||
}
|
||||
if (sentinelValue == object7) {
|
||||
return SystemHash.hash6(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object8) {
|
||||
return SystemHash.hash7(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object9) {
|
||||
return SystemHash.hash8(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object10) {
|
||||
return SystemHash.hash9(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object11) {
|
||||
return SystemHash.hash10(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object12) {
|
||||
return SystemHash.hash11(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object13) {
|
||||
return SystemHash.hash12(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object14) {
|
||||
return SystemHash.hash13(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object15) {
|
||||
return SystemHash.hash14(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
object14.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object16) {
|
||||
return SystemHash.hash15(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
object14.hashCode,
|
||||
object15.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object17) {
|
||||
return SystemHash.hash16(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
object14.hashCode,
|
||||
object15.hashCode,
|
||||
object16.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object18) {
|
||||
return SystemHash.hash17(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
object14.hashCode,
|
||||
object15.hashCode,
|
||||
object16.hashCode,
|
||||
object17.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object19) {
|
||||
return SystemHash.hash18(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
object14.hashCode,
|
||||
object15.hashCode,
|
||||
object16.hashCode,
|
||||
object17.hashCode,
|
||||
object18.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
if (sentinelValue == object20) {
|
||||
return SystemHash.hash19(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
object14.hashCode,
|
||||
object15.hashCode,
|
||||
object16.hashCode,
|
||||
object17.hashCode,
|
||||
object18.hashCode,
|
||||
object19.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
return SystemHash.hash20(
|
||||
object1.hashCode,
|
||||
object2.hashCode,
|
||||
object3.hashCode,
|
||||
object4.hashCode,
|
||||
object5.hashCode,
|
||||
object6.hashCode,
|
||||
object7.hashCode,
|
||||
object8.hashCode,
|
||||
object9.hashCode,
|
||||
object10.hashCode,
|
||||
object11.hashCode,
|
||||
object12.hashCode,
|
||||
object13.hashCode,
|
||||
object14.hashCode,
|
||||
object15.hashCode,
|
||||
object16.hashCode,
|
||||
object17.hashCode,
|
||||
object18.hashCode,
|
||||
object19.hashCode,
|
||||
object20.hashCode,
|
||||
_hashSeed);
|
||||
}
|
||||
|
||||
/// Creates a combined hash code for a sequence of objects.
|
||||
///
|
||||
/// The hash code is computed for elements in [objects],
|
||||
/// even if they are `null`,
|
||||
/// by numerically combining the [Object.hashCode] of each element
|
||||
/// in iteration order.
|
||||
///
|
||||
/// The result of `hashAll([o])` is not `o.hashCode`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// class SomeObject {
|
||||
/// final List<String> path;
|
||||
/// SomeObject(this.path);
|
||||
/// bool operator=(Object other) {
|
||||
/// if (other is SomeObject) {
|
||||
/// if (path.length != other.path.length) return false;
|
||||
/// for (int i = 0; i < path.length; i++) {
|
||||
/// if (path[i] != other.path[i]) return false;
|
||||
/// }
|
||||
/// return true;
|
||||
/// }
|
||||
/// return false;
|
||||
/// }
|
||||
///
|
||||
/// int get hashCode => Object.hashAll(path);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The computed value will be be consistent when the function is called
|
||||
/// again with objects that have the same hash codes in the same order
|
||||
/// during an execution of a single program.
|
||||
///
|
||||
/// The hash value generated by this function is *not* guranteed to be stable
|
||||
/// over different runs of the same program,
|
||||
/// or between code run in different isolates of the same program.
|
||||
/// The exact algorithm used may differ between different platforms,
|
||||
/// or between different versions of the platform libraries,
|
||||
/// and it may depend on values that change on each program execution.
|
||||
@Since("2.14")
|
||||
static int hashAll(Iterable<Object?> objects) {
|
||||
int hash = _hashSeed;
|
||||
for (var object in objects) {
|
||||
hash = SystemHash.combine(hash, object.hashCode);
|
||||
}
|
||||
return SystemHash.finish(hash);
|
||||
}
|
||||
|
||||
/// Creates a combined hash code for a collection of objects.
|
||||
///
|
||||
/// The hash code is computed for elements in [objects],
|
||||
/// even if they are `null`,
|
||||
/// by numerically combining the [Object.hashCode] of each element
|
||||
/// in an order independent way.
|
||||
///
|
||||
/// The result of `unorderedHashAll({o})` is not `o.hashCode`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// bool setEquals<T>(Set<T> set1, Set<T> set2) {
|
||||
/// var hashCode1 = Object.unorderedHashAll(set1);
|
||||
/// var hashCode2 = Object.unorderedHashAll(set2);
|
||||
/// if (hashCode1 != hashCode2) return false;
|
||||
/// // Compare elements ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The computed value will be be consistent when the function is called
|
||||
/// again with objects that have the same hash codes
|
||||
/// during an execution of a single program,
|
||||
/// even if the objects are not necessarily in the same order,
|
||||
///
|
||||
/// The hash value generated by this function is *not* guranteed to be stable
|
||||
/// over different runs of the same program.
|
||||
/// The exact algorithm used may differ between different platforms,
|
||||
/// or between different versions of the platform libraries,
|
||||
/// and it may depend on values that change per program run
|
||||
@Since("2.14")
|
||||
static int hashAllUnordered(Iterable<Object?> objects) {
|
||||
int sum = 0;
|
||||
int count = 0;
|
||||
const int mask = 0x3FFFFFFF;
|
||||
for (var object in objects) {
|
||||
int objectHash = SystemHash.smear(object.hashCode);
|
||||
sum = (sum + objectHash) & mask;
|
||||
count += 1;
|
||||
}
|
||||
return SystemHash.hash2(sum, count);
|
||||
}
|
||||
}
|
||||
|
||||
// A per-isolate seed for hash code computations.
|
||||
final int _hashSeed = identityHashCode(Object);
|
||||
|
|
|
@ -148,7 +148,7 @@ final Future<Null> nullFuture = Zone.root.run(() => Future<Null>.value(null));
|
|||
///
|
||||
/// [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
|
||||
///
|
||||
/// Usage:
|
||||
/// Use:
|
||||
/// Hash each value with the hash of the previous value, then get the final
|
||||
/// hash by calling finish.
|
||||
/// ```
|
||||
|
@ -158,8 +158,9 @@ final Future<Null> nullFuture = Zone.root.run(() => Future<Null>.value(null));
|
|||
/// }
|
||||
/// hash = SystemHash.finish(hash);
|
||||
/// ```
|
||||
// TODO(lrn): Consider specializing this code per platform,
|
||||
// so the VM can use its 64-bit integers directly.
|
||||
///
|
||||
/// TODO(lrn): Consider specializing this code per platform,
|
||||
/// so the VM can use its 64-bit integers directly.
|
||||
@Since("2.11")
|
||||
class SystemHash {
|
||||
static int combine(int hash, int value) {
|
||||
|
@ -174,23 +175,24 @@ class SystemHash {
|
|||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
|
||||
static int hash2(int v1, int v2) {
|
||||
int hash = 0;
|
||||
static int hash2(int v1, int v2, [@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
static int hash3(int v1, int v2, int v3) {
|
||||
int hash = 0;
|
||||
static int hash3(int v1, int v2, int v3, [@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
static int hash4(int v1, int v2, int v3, int v4) {
|
||||
int hash = 0;
|
||||
static int hash4(int v1, int v2, int v3, int v4,
|
||||
[@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
|
@ -198,8 +200,9 @@ class SystemHash {
|
|||
return finish(hash);
|
||||
}
|
||||
|
||||
static int hash5(int v1, int v2, int v3, int v4, int v5) {
|
||||
int hash = 0;
|
||||
static int hash5(int v1, int v2, int v3, int v4, int v5,
|
||||
[@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
|
@ -208,8 +211,9 @@ class SystemHash {
|
|||
return finish(hash);
|
||||
}
|
||||
|
||||
static int hash6(int v1, int v2, int v3, int v4, int v5, int v6) {
|
||||
int hash = 0;
|
||||
static int hash6(int v1, int v2, int v3, int v4, int v5, int v6,
|
||||
[@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
|
@ -219,8 +223,9 @@ class SystemHash {
|
|||
return finish(hash);
|
||||
}
|
||||
|
||||
static int hash7(int v1, int v2, int v3, int v4, int v5, int v6, int v7) {
|
||||
int hash = 0;
|
||||
static int hash7(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
|
||||
[@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
|
@ -232,8 +237,9 @@ class SystemHash {
|
|||
}
|
||||
|
||||
static int hash8(
|
||||
int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) {
|
||||
int hash = 0;
|
||||
int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8,
|
||||
[@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
|
@ -246,8 +252,9 @@ class SystemHash {
|
|||
}
|
||||
|
||||
static int hash9(
|
||||
int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9) {
|
||||
int hash = 0;
|
||||
int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9,
|
||||
[@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
|
@ -261,8 +268,9 @@ class SystemHash {
|
|||
}
|
||||
|
||||
static int hash10(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
|
||||
int v8, int v9, int v10) {
|
||||
int hash = 0;
|
||||
int v8, int v9, int v10,
|
||||
[@Since("2.14") int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
|
@ -276,14 +284,334 @@ class SystemHash {
|
|||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash11(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
|
||||
int v8, int v9, int v10, int v11,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash12(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
|
||||
int v8, int v9, int v10, int v11, int v12,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash13(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
|
||||
int v8, int v9, int v10, int v11, int v12, int v13,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash14(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
|
||||
int v8, int v9, int v10, int v11, int v12, int v13, int v14,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
hash = combine(hash, v14);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash15(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
|
||||
int v8, int v9, int v10, int v11, int v12, int v13, int v14, int v15,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
hash = combine(hash, v14);
|
||||
hash = combine(hash, v15);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash16(
|
||||
int v1,
|
||||
int v2,
|
||||
int v3,
|
||||
int v4,
|
||||
int v5,
|
||||
int v6,
|
||||
int v7,
|
||||
int v8,
|
||||
int v9,
|
||||
int v10,
|
||||
int v11,
|
||||
int v12,
|
||||
int v13,
|
||||
int v14,
|
||||
int v15,
|
||||
int v16,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
hash = combine(hash, v14);
|
||||
hash = combine(hash, v15);
|
||||
hash = combine(hash, v16);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash17(
|
||||
int v1,
|
||||
int v2,
|
||||
int v3,
|
||||
int v4,
|
||||
int v5,
|
||||
int v6,
|
||||
int v7,
|
||||
int v8,
|
||||
int v9,
|
||||
int v10,
|
||||
int v11,
|
||||
int v12,
|
||||
int v13,
|
||||
int v14,
|
||||
int v15,
|
||||
int v16,
|
||||
int v17,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
hash = combine(hash, v14);
|
||||
hash = combine(hash, v15);
|
||||
hash = combine(hash, v16);
|
||||
hash = combine(hash, v17);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash18(
|
||||
int v1,
|
||||
int v2,
|
||||
int v3,
|
||||
int v4,
|
||||
int v5,
|
||||
int v6,
|
||||
int v7,
|
||||
int v8,
|
||||
int v9,
|
||||
int v10,
|
||||
int v11,
|
||||
int v12,
|
||||
int v13,
|
||||
int v14,
|
||||
int v15,
|
||||
int v16,
|
||||
int v17,
|
||||
int v18,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
hash = combine(hash, v14);
|
||||
hash = combine(hash, v15);
|
||||
hash = combine(hash, v16);
|
||||
hash = combine(hash, v17);
|
||||
hash = combine(hash, v18);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash19(
|
||||
int v1,
|
||||
int v2,
|
||||
int v3,
|
||||
int v4,
|
||||
int v5,
|
||||
int v6,
|
||||
int v7,
|
||||
int v8,
|
||||
int v9,
|
||||
int v10,
|
||||
int v11,
|
||||
int v12,
|
||||
int v13,
|
||||
int v14,
|
||||
int v15,
|
||||
int v16,
|
||||
int v17,
|
||||
int v18,
|
||||
int v19,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
hash = combine(hash, v14);
|
||||
hash = combine(hash, v15);
|
||||
hash = combine(hash, v16);
|
||||
hash = combine(hash, v17);
|
||||
hash = combine(hash, v18);
|
||||
hash = combine(hash, v19);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
@Since("2.14")
|
||||
static int hash20(
|
||||
int v1,
|
||||
int v2,
|
||||
int v3,
|
||||
int v4,
|
||||
int v5,
|
||||
int v6,
|
||||
int v7,
|
||||
int v8,
|
||||
int v9,
|
||||
int v10,
|
||||
int v11,
|
||||
int v12,
|
||||
int v13,
|
||||
int v14,
|
||||
int v15,
|
||||
int v16,
|
||||
int v17,
|
||||
int v18,
|
||||
int v19,
|
||||
int v20,
|
||||
[int seed = 0]) {
|
||||
int hash = seed;
|
||||
hash = combine(hash, v1);
|
||||
hash = combine(hash, v2);
|
||||
hash = combine(hash, v3);
|
||||
hash = combine(hash, v4);
|
||||
hash = combine(hash, v5);
|
||||
hash = combine(hash, v6);
|
||||
hash = combine(hash, v7);
|
||||
hash = combine(hash, v8);
|
||||
hash = combine(hash, v9);
|
||||
hash = combine(hash, v10);
|
||||
hash = combine(hash, v11);
|
||||
hash = combine(hash, v12);
|
||||
hash = combine(hash, v13);
|
||||
hash = combine(hash, v14);
|
||||
hash = combine(hash, v15);
|
||||
hash = combine(hash, v16);
|
||||
hash = combine(hash, v17);
|
||||
hash = combine(hash, v18);
|
||||
hash = combine(hash, v19);
|
||||
hash = combine(hash, v20);
|
||||
return finish(hash);
|
||||
}
|
||||
|
||||
/// Bit shuffling operation to improve hash codes.
|
||||
///
|
||||
/// Dart integers have very simple hash codes (their value),
|
||||
/// which is acceptable for the hash above because it smears the bits
|
||||
/// as part of the combination.
|
||||
/// However, for the unordered hash based on xor, we need to improve
|
||||
/// the hash code of, e.g., integers, so a set containing the integers
|
||||
/// from zero to 2^n won't always have a zero hashcode.
|
||||
/// However, for the unordered hash, we need to improve
|
||||
/// the hash code of, e.g., integers, to avoid collections of small integers
|
||||
/// too easily having colliding hash results.
|
||||
///
|
||||
/// Assumes the input hash code is an unsigned 32-bit integer.
|
||||
/// Found by Christopher Wellons [https://github.com/skeeto/hash-prospector].
|
||||
|
@ -298,6 +626,17 @@ class SystemHash {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sentinel values that should never be exposed outside of platform libraries.
|
||||
@Since("2.14")
|
||||
class SentinelValue {
|
||||
final int id;
|
||||
const SentinelValue(this.id);
|
||||
}
|
||||
|
||||
/// A default value to use when only one sentinel is needed.
|
||||
@Since("2.14")
|
||||
const Object sentinelValue = const SentinelValue(0);
|
||||
|
||||
/// Given an [instance] of some generic type [T], and [extract], a first-class
|
||||
/// generic function that takes the same number of type parameters as [T],
|
||||
/// invokes the function with the same type arguments that were passed to T
|
||||
|
|
134
tests/corelib/object_hash_test.dart
Normal file
134
tests/corelib/object_hash_test.dart
Normal file
|
@ -0,0 +1,134 @@
|
|||
// 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:math";
|
||||
import "dart:typed_data";
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
const nan = double.nan;
|
||||
const inf = double.infinity;
|
||||
|
||||
int hash1234 = Object.hash(1, 2, 3, 4);
|
||||
Expect.type<int>(hash1234);
|
||||
Expect.equals(hash1234, Object.hash(1, 2, 3, 4)); // Consistent.
|
||||
Expect.equals(hash1234, Object.hashAll([1, 2, 3, 4]));
|
||||
Expect.equals(hash1234, Object.hashAll(Uint8List.fromList([1, 2, 3, 4])));
|
||||
|
||||
Expect.notEquals(hash1234, Object.hash(1, 2, 3, 4, null));
|
||||
|
||||
Expect.equals(Object.hash(1, 2, 3, 4, 5, 6, 7, 8, 9),
|
||||
Object.hashAll([1, 2, 3, 4, 5, 6, 7, 8, 9]));
|
||||
|
||||
// Check that we can call `hash` with 2-20 arguments,
|
||||
// and they all agree with `hashAll`.
|
||||
var random = Random();
|
||||
for (var i = 2; i <= 20; i++) {
|
||||
var arguments = [for (var j = 0; j < i; j++) random.nextInt(256)];
|
||||
var hashAll = Object.hashAll(arguments);
|
||||
var hash = Function.apply(Object.hash, arguments);
|
||||
Expect.equals(
|
||||
hashAll,
|
||||
hash,
|
||||
"hashAll and hash disagrees for $i values:\n"
|
||||
"$arguments");
|
||||
}
|
||||
|
||||
// Works for all kinds of objects;
|
||||
int varHash = Object.hash(
|
||||
"string", 3, nan, true, null, Type, #Symbol, const Object(), function);
|
||||
Expect.equals(
|
||||
varHash,
|
||||
Object.hashAll([
|
||||
"string",
|
||||
3,
|
||||
nan,
|
||||
true,
|
||||
null,
|
||||
Type,
|
||||
#Symbol,
|
||||
const Object(),
|
||||
function
|
||||
]));
|
||||
|
||||
// Object doesn't matter, just its hash code.
|
||||
Expect.equals(hash1234,
|
||||
Object.hash(Hashable(1), Hashable(2), Hashable(3), Hashable(4)));
|
||||
|
||||
// It's potentially possible to get a conflict, but it doesn't happen here.
|
||||
Expect.notEquals("str".hashCode, Object.hashAll(["str"]));
|
||||
|
||||
var hash12345 = Object.hashAllUnordered([1, 2, 3, 4, 5]);
|
||||
for (var p in permutations([1, 2, 3, 4, 5])) {
|
||||
Expect.equals(hash12345, Object.hashAllUnordered(p));
|
||||
}
|
||||
Expect.notEquals(
|
||||
Object.hashAllUnordered(["a", "a"]), Object.hashAllUnordered(["a"]));
|
||||
|
||||
Expect.notEquals(Object.hashAllUnordered(["a", "a"]),
|
||||
Object.hashAllUnordered(["a", "a", "a", "a"]));
|
||||
|
||||
Expect.notEquals(Object.hashAllUnordered(["a", "b"]),
|
||||
Object.hashAllUnordered(["a", "a", "a", "b"]));
|
||||
|
||||
/// Unordered hashing works for all kinds of objects.
|
||||
var unorderHash = Object.hashAllUnordered([
|
||||
"string",
|
||||
3,
|
||||
nan,
|
||||
true,
|
||||
null,
|
||||
Type,
|
||||
#Symbol,
|
||||
const Object(),
|
||||
function,
|
||||
]);
|
||||
|
||||
var unorderHash2 = Object.hashAllUnordered([
|
||||
true,
|
||||
const Object(),
|
||||
3,
|
||||
function,
|
||||
Type,
|
||||
"string",
|
||||
null,
|
||||
nan,
|
||||
#Symbol,
|
||||
]);
|
||||
Expect.equals(unorderHash, unorderHash2);
|
||||
}
|
||||
|
||||
/// Lazily emits all permutations of [values].
|
||||
///
|
||||
/// Modifes [values] rather than create a new list.
|
||||
/// The [values] list is guaranteed to end up in its original state
|
||||
/// after all permutations have been read.
|
||||
Iterable<List<T>> permutations<T>(List<T> values) {
|
||||
Iterable<List<T>> recPermute(int end) sync* {
|
||||
if (end == 1) {
|
||||
yield values;
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < end; i++) {
|
||||
yield* recPermute(end - 1);
|
||||
// Rotate values[i:].
|
||||
var tmp = values.first;
|
||||
for (var k = 1; k < end; k++) values[k - 1] = values[k];
|
||||
values[end - 1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return recPermute(values.length);
|
||||
}
|
||||
|
||||
// static function, used as constant value.
|
||||
void function() {}
|
||||
|
||||
class Hashable {
|
||||
final Object o;
|
||||
Hashable(this.o);
|
||||
bool operator ==(Object other) => other is Hashable && o == other.o;
|
||||
int get hashCode => o.hashCode;
|
||||
}
|
134
tests/corelib_2/object_hash_test.dart
Normal file
134
tests/corelib_2/object_hash_test.dart
Normal file
|
@ -0,0 +1,134 @@
|
|||
// 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:math";
|
||||
import "dart:typed_data";
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
main() {
|
||||
const nan = double.nan;
|
||||
const inf = double.infinity;
|
||||
|
||||
int hash1234 = Object.hash(1, 2, 3, 4);
|
||||
Expect.type<int>(hash1234);
|
||||
Expect.equals(hash1234, Object.hash(1, 2, 3, 4)); // Consistent.
|
||||
Expect.equals(hash1234, Object.hashAll([1, 2, 3, 4]));
|
||||
Expect.equals(hash1234, Object.hashAll(Uint8List.fromList([1, 2, 3, 4])));
|
||||
|
||||
Expect.notEquals(hash1234, Object.hash(1, 2, 3, 4, null));
|
||||
|
||||
Expect.equals(Object.hash(1, 2, 3, 4, 5, 6, 7, 8, 9),
|
||||
Object.hashAll([1, 2, 3, 4, 5, 6, 7, 8, 9]));
|
||||
|
||||
// Check that we can call `hash` with 2-20 arguments,
|
||||
// and they all agree with `hashAll`.
|
||||
var random = Random();
|
||||
for (var i = 2; i <= 20; i++) {
|
||||
var arguments = [for (var j = 0; j < i; j++) random.nextInt(256)];
|
||||
var hashAll = Object.hashAll(arguments);
|
||||
var hash = Function.apply(Object.hash, arguments);
|
||||
Expect.equals(
|
||||
hashAll,
|
||||
hash,
|
||||
"hashAll and hash disagrees for $i values:\n"
|
||||
"$arguments");
|
||||
}
|
||||
|
||||
// Works for all kinds of objects;
|
||||
int varHash = Object.hash(
|
||||
"string", 3, nan, true, null, Type, #Symbol, const Object(), function);
|
||||
Expect.equals(
|
||||
varHash,
|
||||
Object.hashAll([
|
||||
"string",
|
||||
3,
|
||||
nan,
|
||||
true,
|
||||
null,
|
||||
Type,
|
||||
#Symbol,
|
||||
const Object(),
|
||||
function
|
||||
]));
|
||||
|
||||
// Object doesn't matter, just its hash code.
|
||||
Expect.equals(hash1234,
|
||||
Object.hash(Hashable(1), Hashable(2), Hashable(3), Hashable(4)));
|
||||
|
||||
// It's potentially possible to get a conflict, but it doesn't happen here.
|
||||
Expect.notEquals("str".hashCode, Object.hashAll(["str"]));
|
||||
|
||||
var hash12345 = Object.hashAllUnordered([1, 2, 3, 4, 5]);
|
||||
for (var p in permutations([1, 2, 3, 4, 5])) {
|
||||
Expect.equals(hash12345, Object.hashAllUnordered(p));
|
||||
}
|
||||
Expect.notEquals(
|
||||
Object.hashAllUnordered(["a", "a"]), Object.hashAllUnordered(["a"]));
|
||||
|
||||
Expect.notEquals(Object.hashAllUnordered(["a", "a"]),
|
||||
Object.hashAllUnordered(["a", "a", "a", "a"]));
|
||||
|
||||
Expect.notEquals(Object.hashAllUnordered(["a", "b"]),
|
||||
Object.hashAllUnordered(["a", "a", "a", "b"]));
|
||||
|
||||
/// Unordered hashing works for all kinds of objects.
|
||||
var unorderHash = Object.hashAllUnordered([
|
||||
"string",
|
||||
3,
|
||||
nan,
|
||||
true,
|
||||
null,
|
||||
Type,
|
||||
#Symbol,
|
||||
const Object(),
|
||||
function,
|
||||
]);
|
||||
|
||||
var unorderHash2 = Object.hashAllUnordered([
|
||||
true,
|
||||
const Object(),
|
||||
3,
|
||||
function,
|
||||
Type,
|
||||
"string",
|
||||
null,
|
||||
nan,
|
||||
#Symbol,
|
||||
]);
|
||||
Expect.equals(unorderHash, unorderHash2);
|
||||
}
|
||||
|
||||
/// Lazily emits all permutations of [values].
|
||||
///
|
||||
/// Modifes [values] rather than create a new list.
|
||||
/// The [values] list is guaranteed to end up in its original state
|
||||
/// after all permutations have been read.
|
||||
Iterable<List<T>> permutations<T>(List<T> values) {
|
||||
Iterable<List<T>> recPermute(int end) sync* {
|
||||
if (end == 1) {
|
||||
yield values;
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < end; i++) {
|
||||
yield* recPermute(end - 1);
|
||||
// Rotate values[i:].
|
||||
var tmp = values.first;
|
||||
for (var k = 1; k < end; k++) values[k - 1] = values[k];
|
||||
values[end - 1] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return recPermute(values.length);
|
||||
}
|
||||
|
||||
// static function, used as constant value.
|
||||
void function() {}
|
||||
|
||||
class Hashable {
|
||||
final Object o;
|
||||
Hashable(this.o);
|
||||
bool operator ==(Object other) => other is Hashable && o == other.o;
|
||||
int get hashCode => o.hashCode;
|
||||
}
|
|
@ -10,11 +10,18 @@ import 'package:expect/expect.dart';
|
|||
import 'stringify.dart';
|
||||
import 'declarations_model.dart' as declarations_model;
|
||||
|
||||
Set<DeclarationMirror> inheritedDeclarations(ClassMirror? cm) {
|
||||
/// Collects all declarations of [cm] and its super-classes except `Object`.
|
||||
///
|
||||
/// Includes static declarations of super-classes.
|
||||
///
|
||||
/// The `Object` class is omitted because this test should be stable against
|
||||
/// changes to the platform libraries, as long as the declaration model code
|
||||
/// doesn't change.
|
||||
Set<DeclarationMirror> transitiveDeclarations(ClassMirror cm) {
|
||||
var decls = new Set<DeclarationMirror>();
|
||||
while (cm != null) {
|
||||
while (cm != reflectClass(Object)) {
|
||||
decls.addAll(cm.declarations.values);
|
||||
cm = cm.superclass;
|
||||
cm = cm.superclass!;
|
||||
}
|
||||
return decls;
|
||||
}
|
||||
|
@ -163,14 +170,12 @@ main() {
|
|||
'Method(s(*) in s(Mixin))',
|
||||
'Method(s(+) in s(Class))',
|
||||
'Method(s(-) in s(Superclass))',
|
||||
'Method(s(==) in s(Object))',
|
||||
'TypeVariable(s(C) in s(Class),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Class.generativeConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.normalFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Object) in s(Object), constructor)',
|
||||
'TypeVariable(s(S) in s(Superclass),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Superclass.inheritedGenerativeConstructor)'
|
||||
|
@ -182,7 +187,6 @@ main() {
|
|||
'Method(s(Superclass.inheritedRedirectingFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(abstractMethod) in s(Class), abstract)',
|
||||
'Method(s(hashCode) in s(Object), getter)',
|
||||
'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
|
||||
'Method(s(inheritedInstanceMethod) in s(Superclass))',
|
||||
'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
|
||||
|
@ -199,8 +203,6 @@ main() {
|
|||
'Method(s(mixinInstanceMethod) in s(Mixin))',
|
||||
'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
|
||||
'Variable(s(mixinInstanceVariable) in s(Mixin))',
|
||||
'Method(s(noSuchMethod) in s(Object))',
|
||||
'Method(s(runtimeType) in s(Object), getter)',
|
||||
'Method(s(staticGetter) in s(Class), static, getter)',
|
||||
'Method(s(staticMethod) in s(Class), static)',
|
||||
'Method(s(staticSetter=) in s(Class), static, setter)',
|
||||
|
@ -213,12 +215,11 @@ main() {
|
|||
' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Method(s(toString) in s(Object))',
|
||||
'Variable(s(mixinStaticVariable) in s(Mixin), static)',
|
||||
'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
|
||||
'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
|
||||
'Method(s(mixinStaticMethod) in s(Mixin), static)'
|
||||
], inheritedDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
|
||||
], transitiveDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
|
||||
'transitive public');
|
||||
// The public members of Object should be the same in all implementations, so
|
||||
// we don't exclude Object here.
|
||||
|
@ -256,113 +257,106 @@ main() {
|
|||
'Variable(s(staticVariable) in s(Class), static)'
|
||||
], cm.declarations.values.map(stringify), 'declarations');
|
||||
|
||||
Expect.setEquals(
|
||||
[
|
||||
'Method(s(*) in s(Mixin))',
|
||||
'Method(s(+) in s(Class))',
|
||||
'Method(s(-) in s(Superclass))',
|
||||
'TypeVariable(s(C) in s(Class),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
|
||||
'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
|
||||
'Method(s(Class._redirectingConstructor)'
|
||||
' in s(Class), private, constructor)',
|
||||
'Method(s(Class._redirectingFactory)'
|
||||
' in s(Class), private, static, constructor)',
|
||||
'Method(s(Class.generativeConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.normalFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
|
||||
'TypeVariable(s(S) in s(Superclass),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Superclass._inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedNormalFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass.inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedNormalFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
|
||||
'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
|
||||
'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
|
||||
'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
|
||||
'Method(s(_inheritedStaticGetter)'
|
||||
' in s(Superclass), private, static, getter)',
|
||||
'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
|
||||
'Method(s(_inheritedStaticSetter=)'
|
||||
' in s(Superclass), private, static, setter)',
|
||||
'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
|
||||
'Method(s(_instanceGetter) in s(Class), private, getter)',
|
||||
'Method(s(_instanceMethod) in s(Class), private)',
|
||||
'Method(s(_instanceSetter=) in s(Class), private, setter)',
|
||||
'Variable(s(_instanceVariable) in s(Class), private)',
|
||||
'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
|
||||
'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
|
||||
'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
|
||||
'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
|
||||
'Method(s(_staticGetter) in s(Class), private, static, getter)',
|
||||
'Method(s(_staticMethod) in s(Class), private, static)',
|
||||
'Method(s(_staticSetter=) in s(Class), private, static, setter)',
|
||||
'Variable(s(_staticVariable) in s(Class), private, static)',
|
||||
'Method(s(abstractMethod) in s(Class), abstract)',
|
||||
'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
|
||||
'Method(s(inheritedInstanceMethod) in s(Superclass))',
|
||||
'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
|
||||
'Variable(s(inheritedInstanceVariable) in s(Superclass))',
|
||||
'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
|
||||
'Method(s(inheritedStaticMethod) in s(Superclass), static)',
|
||||
'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
|
||||
'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
|
||||
'Method(s(instanceGetter) in s(Class), getter)',
|
||||
'Method(s(instanceMethod) in s(Class))',
|
||||
'Method(s(instanceSetter=) in s(Class), setter)',
|
||||
'Variable(s(instanceVariable) in s(Class))',
|
||||
'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
|
||||
'Method(s(mixinInstanceMethod) in s(Mixin))',
|
||||
'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
|
||||
'Variable(s(mixinInstanceVariable) in s(Mixin))',
|
||||
'Method(s(staticGetter) in s(Class), static, getter)',
|
||||
'Method(s(staticMethod) in s(Class), static)',
|
||||
'Method(s(staticSetter=) in s(Class), static, setter)',
|
||||
'Variable(s(staticVariable) in s(Class), static)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Variable(s(mixinStaticVariable) in s(Mixin), static)',
|
||||
'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
|
||||
'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
|
||||
'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
|
||||
'Method(s(mixinStaticMethod) in s(Mixin), static)',
|
||||
'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
|
||||
'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
|
||||
'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
|
||||
],
|
||||
inheritedDeclarations(cm)
|
||||
.difference(reflectClass(Object).declarations.values.toSet())
|
||||
.map(stringify),
|
||||
'transitive less Object');
|
||||
// The private members of Object may vary across implementations, so we
|
||||
// exclude the declarations of Object in this test case.
|
||||
Expect.setEquals([
|
||||
'Method(s(*) in s(Mixin))',
|
||||
'Method(s(+) in s(Class))',
|
||||
'Method(s(-) in s(Superclass))',
|
||||
'TypeVariable(s(C) in s(Class),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
|
||||
'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
|
||||
'Method(s(Class._redirectingConstructor)'
|
||||
' in s(Class), private, constructor)',
|
||||
'Method(s(Class._redirectingFactory)'
|
||||
' in s(Class), private, static, constructor)',
|
||||
'Method(s(Class.generativeConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.normalFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
|
||||
'TypeVariable(s(S) in s(Superclass),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Superclass._inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedNormalFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass.inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedNormalFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
|
||||
'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
|
||||
'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
|
||||
'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
|
||||
'Method(s(_inheritedStaticGetter)'
|
||||
' in s(Superclass), private, static, getter)',
|
||||
'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
|
||||
'Method(s(_inheritedStaticSetter=)'
|
||||
' in s(Superclass), private, static, setter)',
|
||||
'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
|
||||
'Method(s(_instanceGetter) in s(Class), private, getter)',
|
||||
'Method(s(_instanceMethod) in s(Class), private)',
|
||||
'Method(s(_instanceSetter=) in s(Class), private, setter)',
|
||||
'Variable(s(_instanceVariable) in s(Class), private)',
|
||||
'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
|
||||
'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
|
||||
'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
|
||||
'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
|
||||
'Method(s(_staticGetter) in s(Class), private, static, getter)',
|
||||
'Method(s(_staticMethod) in s(Class), private, static)',
|
||||
'Method(s(_staticSetter=) in s(Class), private, static, setter)',
|
||||
'Variable(s(_staticVariable) in s(Class), private, static)',
|
||||
'Method(s(abstractMethod) in s(Class), abstract)',
|
||||
'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
|
||||
'Method(s(inheritedInstanceMethod) in s(Superclass))',
|
||||
'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
|
||||
'Variable(s(inheritedInstanceVariable) in s(Superclass))',
|
||||
'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
|
||||
'Method(s(inheritedStaticMethod) in s(Superclass), static)',
|
||||
'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
|
||||
'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
|
||||
'Method(s(instanceGetter) in s(Class), getter)',
|
||||
'Method(s(instanceMethod) in s(Class))',
|
||||
'Method(s(instanceSetter=) in s(Class), setter)',
|
||||
'Variable(s(instanceVariable) in s(Class))',
|
||||
'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
|
||||
'Method(s(mixinInstanceMethod) in s(Mixin))',
|
||||
'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
|
||||
'Variable(s(mixinInstanceVariable) in s(Mixin))',
|
||||
'Method(s(staticGetter) in s(Class), static, getter)',
|
||||
'Method(s(staticMethod) in s(Class), static)',
|
||||
'Method(s(staticSetter=) in s(Class), static, setter)',
|
||||
'Variable(s(staticVariable) in s(Class), static)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Variable(s(mixinStaticVariable) in s(Mixin), static)',
|
||||
'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
|
||||
'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
|
||||
'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
|
||||
'Method(s(mixinStaticMethod) in s(Mixin), static)',
|
||||
'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
|
||||
'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
|
||||
'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
|
||||
], transitiveDeclarations(cm).map(stringify), 'transitive all');
|
||||
}
|
||||
|
|
|
@ -12,9 +12,16 @@ import 'package:expect/expect.dart';
|
|||
import 'stringify.dart';
|
||||
import 'declarations_model.dart' as declarations_model;
|
||||
|
||||
Set<DeclarationMirror> inheritedDeclarations(ClassMirror cm) {
|
||||
/// Collects all declarations of [cm] and its super-classes except `Object`.
|
||||
///
|
||||
/// Includes static declarations of super-classes.
|
||||
///
|
||||
/// The `Object` class is omitted because this test should be stable against
|
||||
/// changes to the platform libraries, as long as the declaration model code
|
||||
/// doesn't change.
|
||||
Set<DeclarationMirror> transitiveDeclarations(ClassMirror cm) {
|
||||
var decls = new Set<DeclarationMirror>();
|
||||
while (cm != null) {
|
||||
while (cm != reflectClass(Object)) {
|
||||
decls.addAll(cm.declarations.values);
|
||||
cm = cm.superclass;
|
||||
}
|
||||
|
@ -165,14 +172,12 @@ main() {
|
|||
'Method(s(*) in s(Mixin))',
|
||||
'Method(s(+) in s(Class))',
|
||||
'Method(s(-) in s(Superclass))',
|
||||
'Method(s(==) in s(Object))',
|
||||
'TypeVariable(s(C) in s(Class),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Class.generativeConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.normalFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Object) in s(Object), constructor)',
|
||||
'TypeVariable(s(S) in s(Superclass),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Superclass.inheritedGenerativeConstructor)'
|
||||
|
@ -184,7 +189,6 @@ main() {
|
|||
'Method(s(Superclass.inheritedRedirectingFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(abstractMethod) in s(Class), abstract)',
|
||||
'Method(s(hashCode) in s(Object), getter)',
|
||||
'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
|
||||
'Method(s(inheritedInstanceMethod) in s(Superclass))',
|
||||
'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
|
||||
|
@ -201,8 +205,6 @@ main() {
|
|||
'Method(s(mixinInstanceMethod) in s(Mixin))',
|
||||
'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
|
||||
'Variable(s(mixinInstanceVariable) in s(Mixin))',
|
||||
'Method(s(noSuchMethod) in s(Object))',
|
||||
'Method(s(runtimeType) in s(Object), getter)',
|
||||
'Method(s(staticGetter) in s(Class), static, getter)',
|
||||
'Method(s(staticMethod) in s(Class), static)',
|
||||
'Method(s(staticSetter=) in s(Class), static, setter)',
|
||||
|
@ -215,12 +217,11 @@ main() {
|
|||
' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Method(s(toString) in s(Object))',
|
||||
'Variable(s(mixinStaticVariable) in s(Mixin), static)',
|
||||
'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
|
||||
'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
|
||||
'Method(s(mixinStaticMethod) in s(Mixin), static)'
|
||||
], inheritedDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
|
||||
], transitiveDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
|
||||
'transitive public');
|
||||
// The public members of Object should be the same in all implementations, so
|
||||
// we don't exclude Object here.
|
||||
|
@ -258,113 +259,106 @@ main() {
|
|||
'Variable(s(staticVariable) in s(Class), static)'
|
||||
], cm.declarations.values.map(stringify), 'declarations');
|
||||
|
||||
Expect.setEquals(
|
||||
[
|
||||
'Method(s(*) in s(Mixin))',
|
||||
'Method(s(+) in s(Class))',
|
||||
'Method(s(-) in s(Superclass))',
|
||||
'TypeVariable(s(C) in s(Class),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
|
||||
'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
|
||||
'Method(s(Class._redirectingConstructor)'
|
||||
' in s(Class), private, constructor)',
|
||||
'Method(s(Class._redirectingFactory)'
|
||||
' in s(Class), private, static, constructor)',
|
||||
'Method(s(Class.generativeConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.normalFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
|
||||
'TypeVariable(s(S) in s(Superclass),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Superclass._inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedNormalFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass.inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedNormalFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
|
||||
'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
|
||||
'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
|
||||
'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
|
||||
'Method(s(_inheritedStaticGetter)'
|
||||
' in s(Superclass), private, static, getter)',
|
||||
'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
|
||||
'Method(s(_inheritedStaticSetter=)'
|
||||
' in s(Superclass), private, static, setter)',
|
||||
'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
|
||||
'Method(s(_instanceGetter) in s(Class), private, getter)',
|
||||
'Method(s(_instanceMethod) in s(Class), private)',
|
||||
'Method(s(_instanceSetter=) in s(Class), private, setter)',
|
||||
'Variable(s(_instanceVariable) in s(Class), private)',
|
||||
'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
|
||||
'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
|
||||
'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
|
||||
'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
|
||||
'Method(s(_staticGetter) in s(Class), private, static, getter)',
|
||||
'Method(s(_staticMethod) in s(Class), private, static)',
|
||||
'Method(s(_staticSetter=) in s(Class), private, static, setter)',
|
||||
'Variable(s(_staticVariable) in s(Class), private, static)',
|
||||
'Method(s(abstractMethod) in s(Class), abstract)',
|
||||
'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
|
||||
'Method(s(inheritedInstanceMethod) in s(Superclass))',
|
||||
'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
|
||||
'Variable(s(inheritedInstanceVariable) in s(Superclass))',
|
||||
'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
|
||||
'Method(s(inheritedStaticMethod) in s(Superclass), static)',
|
||||
'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
|
||||
'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
|
||||
'Method(s(instanceGetter) in s(Class), getter)',
|
||||
'Method(s(instanceMethod) in s(Class))',
|
||||
'Method(s(instanceSetter=) in s(Class), setter)',
|
||||
'Variable(s(instanceVariable) in s(Class))',
|
||||
'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
|
||||
'Method(s(mixinInstanceMethod) in s(Mixin))',
|
||||
'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
|
||||
'Variable(s(mixinInstanceVariable) in s(Mixin))',
|
||||
'Method(s(staticGetter) in s(Class), static, getter)',
|
||||
'Method(s(staticMethod) in s(Class), static)',
|
||||
'Method(s(staticSetter=) in s(Class), static, setter)',
|
||||
'Variable(s(staticVariable) in s(Class), static)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Variable(s(mixinStaticVariable) in s(Mixin), static)',
|
||||
'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
|
||||
'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
|
||||
'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
|
||||
'Method(s(mixinStaticMethod) in s(Mixin), static)',
|
||||
'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
|
||||
'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
|
||||
'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
|
||||
],
|
||||
inheritedDeclarations(cm)
|
||||
.difference(reflectClass(Object).declarations.values.toSet())
|
||||
.map(stringify),
|
||||
'transitive less Object');
|
||||
// The private members of Object may vary across implementations, so we
|
||||
// exclude the declarations of Object in this test case.
|
||||
Expect.setEquals([
|
||||
'Method(s(*) in s(Mixin))',
|
||||
'Method(s(+) in s(Class))',
|
||||
'Method(s(-) in s(Superclass))',
|
||||
'TypeVariable(s(C) in s(Class),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
|
||||
'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
|
||||
'Method(s(Class._redirectingConstructor)'
|
||||
' in s(Class), private, constructor)',
|
||||
'Method(s(Class._redirectingFactory)'
|
||||
' in s(Class), private, static, constructor)',
|
||||
'Method(s(Class.generativeConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.normalFactory) in s(Class), static, constructor)',
|
||||
'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
|
||||
'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
|
||||
'TypeVariable(s(S) in s(Superclass),'
|
||||
' upperBound = Class(s(Object) in s(dart.core), top-level))',
|
||||
'Method(s(Superclass._inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedNormalFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), private, constructor)',
|
||||
'Method(s(Superclass._inheritedRedirectingFactory)'
|
||||
' in s(Superclass), private, static, constructor)',
|
||||
'Method(s(Superclass.inheritedGenerativeConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedNormalFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingConstructor)'
|
||||
' in s(Superclass), constructor)',
|
||||
'Method(s(Superclass.inheritedRedirectingFactory)'
|
||||
' in s(Superclass), static, constructor)',
|
||||
'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
|
||||
'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
|
||||
'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
|
||||
'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
|
||||
'Method(s(_inheritedStaticGetter)'
|
||||
' in s(Superclass), private, static, getter)',
|
||||
'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
|
||||
'Method(s(_inheritedStaticSetter=)'
|
||||
' in s(Superclass), private, static, setter)',
|
||||
'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
|
||||
'Method(s(_instanceGetter) in s(Class), private, getter)',
|
||||
'Method(s(_instanceMethod) in s(Class), private)',
|
||||
'Method(s(_instanceSetter=) in s(Class), private, setter)',
|
||||
'Variable(s(_instanceVariable) in s(Class), private)',
|
||||
'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
|
||||
'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
|
||||
'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
|
||||
'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
|
||||
'Method(s(_staticGetter) in s(Class), private, static, getter)',
|
||||
'Method(s(_staticMethod) in s(Class), private, static)',
|
||||
'Method(s(_staticSetter=) in s(Class), private, static, setter)',
|
||||
'Variable(s(_staticVariable) in s(Class), private, static)',
|
||||
'Method(s(abstractMethod) in s(Class), abstract)',
|
||||
'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
|
||||
'Method(s(inheritedInstanceMethod) in s(Superclass))',
|
||||
'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
|
||||
'Variable(s(inheritedInstanceVariable) in s(Superclass))',
|
||||
'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
|
||||
'Method(s(inheritedStaticMethod) in s(Superclass), static)',
|
||||
'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
|
||||
'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
|
||||
'Method(s(instanceGetter) in s(Class), getter)',
|
||||
'Method(s(instanceMethod) in s(Class))',
|
||||
'Method(s(instanceSetter=) in s(Class), setter)',
|
||||
'Variable(s(instanceVariable) in s(Class))',
|
||||
'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
|
||||
'Method(s(mixinInstanceMethod) in s(Mixin))',
|
||||
'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
|
||||
'Variable(s(mixinInstanceVariable) in s(Mixin))',
|
||||
'Method(s(staticGetter) in s(Class), static, getter)',
|
||||
'Method(s(staticMethod) in s(Class), static)',
|
||||
'Method(s(staticSetter=) in s(Class), static, setter)',
|
||||
'Variable(s(staticVariable) in s(Class), static)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), private, constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Method(s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
|
||||
' in s(test.declarations_model.Superclass'
|
||||
' with test.declarations_model.Mixin), constructor)',
|
||||
'Variable(s(mixinStaticVariable) in s(Mixin), static)',
|
||||
'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
|
||||
'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
|
||||
'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
|
||||
'Method(s(mixinStaticMethod) in s(Mixin), static)',
|
||||
'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
|
||||
'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
|
||||
'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
|
||||
], transitiveDeclarations(cm).map(stringify), 'transitive all');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue