Index: lib/ast.dart |
diff --git a/lib/ast.dart b/lib/ast.dart |
index b8f08976ecb666e2f0f822969922e2133ff45f14..69eb1be823d984682982f037126d09ea127ec130 100644 |
--- a/lib/ast.dart |
+++ b/lib/ast.dart |
@@ -944,7 +944,13 @@ class Procedure extends Member { |
_MemberAccessor get _setterInterface => _reference; |
} |
-enum ProcedureKind { Method, Getter, Setter, Operator, Factory, } |
+enum ProcedureKind { |
+ Method, |
+ Getter, |
+ Setter, |
+ Operator, |
+ Factory, |
+} |
// ------------------------------------------------------------------------ |
// CONSTRUCTOR INITIALIZERS |
@@ -1100,7 +1106,7 @@ class FunctionNode extends TreeNode { |
List<TypeParameter> typeParameters; |
int requiredParameterCount; |
List<VariableDeclaration> positionalParameters; |
- List<VariableDeclaration> namedParameters; |
+ List<VariableDeclaration> namedParameters; // Must be sorted. |
InferredValue inferredReturnValue; // May be null. |
DartType returnType; // Not null. |
Statement body; |
@@ -1128,6 +1134,10 @@ class FunctionNode extends TreeNode { |
static DartType _getTypeOfVariable(VariableDeclaration node) => node.type; |
+ static NamedType _getNamedTypeOfVariable(VariableDeclaration node) { |
+ return new NamedType(node.name, node.type); |
+ } |
+ |
FunctionType get functionType { |
Map<String, DartType> named = const <String, DartType>{}; |
if (namedParameters.isNotEmpty) { |
@@ -1139,7 +1149,7 @@ class FunctionNode extends TreeNode { |
TreeNode parent = this.parent; |
return new FunctionType( |
positionalParameters.map(_getTypeOfVariable).toList(), returnType, |
- namedParameters: named, |
+ namedParameters: namedParameters.map(_getNamedTypeOfVariable).toList(), |
typeParameters: parent is Constructor |
? parent.enclosingClass.typeParameters |
: typeParameters, |
@@ -1981,8 +1991,8 @@ class ConditionalExpression extends Expression { |
/// The static type of the expression. Should not be `null`. |
DartType staticType; |
- ConditionalExpression(this.condition, this.then, this.otherwise, |
- this.staticType) { |
+ ConditionalExpression( |
+ this.condition, this.then, this.otherwise, this.staticType) { |
condition?.parent = this; |
then?.parent = this; |
otherwise?.parent = this; |
@@ -2963,7 +2973,8 @@ class YieldStatement extends Statement { |
/// When this occurs as a statement, it must be a direct child of a [Block]. |
// |
// DESIGN TODO: Should we remove the 'final' modifier from variables? |
-class VariableDeclaration extends Statement { |
+class VariableDeclaration extends Statement |
+ implements Comparable<VariableDeclaration> { |
/// For named parameters, this is the name of the parameter. No two named |
/// parameters (in the same parameter list) can have the same name. |
/// |
@@ -3036,6 +3047,10 @@ class VariableDeclaration extends Statement { |
/// Returns a possibly synthesized name for this variable, consistent with |
/// the names used across all [toString] calls. |
String toString() => debugVariableDeclarationName(this); |
+ |
+ int compareTo(VariableDeclaration other) { |
+ return name.compareTo(other.name); |
+ } |
} |
/// Declaration a local function. |
@@ -3262,12 +3277,12 @@ class FunctionType extends DartType { |
final List<TypeParameter> typeParameters; |
final int requiredParameterCount; |
final List<DartType> positionalParameters; |
- final Map<String, DartType> namedParameters; |
+ final List<NamedType> namedParameters; // Must be sorted. |
final DartType returnType; |
int _hashCode; |
FunctionType(List<DartType> positionalParameters, this.returnType, |
- {this.namedParameters: const <String, DartType>{}, |
+ {this.namedParameters: const <NamedType>[], |
this.typeParameters: const <TypeParameter>[], |
int requiredParameterCount}) |
: this.positionalParameters = positionalParameters, |
@@ -3279,7 +3294,7 @@ class FunctionType extends DartType { |
visitChildren(Visitor v) { |
visitList(typeParameters, v); |
visitList(positionalParameters, v); |
- visitIterable(namedParameters.values, v); |
+ visitList(namedParameters, v); |
returnType.accept(v); |
} |
@@ -3298,10 +3313,8 @@ class FunctionType extends DartType { |
return false; |
} |
} |
- for (var name in namedParameters.keys) { |
- // If the other function type declared differently named parameters, |
- // one side of this equality will be null and we're good. |
- if (namedParameters[name] != other.namedParameters[name]) { |
+ for (int i = 0; i < namedParameters.length; ++i) { |
+ if (namedParameters[i] != other.namedParameters[i]) { |
return false; |
} |
} |
@@ -3342,13 +3355,9 @@ class FunctionType extends DartType { |
for (int i = 0; i < positionalParameters.length; ++i) { |
hash = 0x3fffffff & (hash * 31 + positionalParameters[i].hashCode); |
} |
- // TODO: Using a sorted list of names would be better than a map here. |
- namedParameters.forEach((String name, DartType type) { |
- // Note that we use only addition and truncation here, so that we do not |
- // rely on the iteration of the of the map. |
- hash = 0x3fffffff & (hash + name.hashCode); |
- hash = 0x3fffffff & (hash + type.hashCode); |
- }); |
+ for (int i = 0; i < namedParameters.length; ++i) { |
+ hash = 0x3fffffff & (hash * 31 + namedParameters[i].hashCode); |
+ } |
hash = 0x3fffffff & (hash * 31 + returnType.hashCode); |
for (int i = 0; i < typeParameters.length; ++i) { |
// Remove the type parameters from the scope again. |
@@ -3358,6 +3367,30 @@ class FunctionType extends DartType { |
} |
} |
+/// A named parameter in [FunctionType]. |
+class NamedType extends Node implements Comparable<NamedType> { |
+ final String name; |
+ final DartType type; |
+ |
+ NamedType(this.name, this.type); |
+ |
+ bool operator ==(Object other) { |
+ return other is NamedType && name == other.name && type == other.type; |
+ } |
+ |
+ int get hashCode { |
+ return name.hashCode * 31 + type.hashCode * 37; |
+ } |
+ |
+ int compareTo(NamedType other) => name.compareTo(other.name); |
+ |
+ accept(Visitor v) => v.visitNamedType(this); |
+ |
+ void visitChildren(Visitor v) { |
+ type.accept(v); |
+ } |
+} |
+ |
/// Stores the hash code of function type parameters while computing the hash |
/// code of a [FunctionType] object. |
/// |