Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Unified Diff: pkg/kernel/lib/ast.dart

Issue 2665723002: Implement canonical name scheme in kernel. (Closed)
Patch Set: Address comments Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/kernel/lib/ast.dart
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index f35e754d4d1c5238c2e6257267b16a26fcf38ddb..99d51d0a2444abbadd1b2299e16750541434c36a 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -56,6 +56,9 @@ export 'visitor.dart';
import 'type_propagation/type_propagation.dart';
export 'type_propagation/type_propagation.dart';
+import 'canonical_name.dart' show CanonicalName;
+export 'canonical_name.dart' show CanonicalName;
+
import 'transformations/flags.dart';
import 'text/ast_to_text.dart';
import 'type_algebra.dart';
@@ -152,11 +155,23 @@ abstract class TreeNode extends Node {
}
}
+/// An AST node that has an associated [CanonicalName], allowing it to be
+/// referenced by name. Libraries, classes, and members are linked nodes.
+///
+/// When created, a linked node has no associated canonical name, and must be
+/// linked to such a name before it can be referenced. A canonical name is
+/// typically assigned by either:
+/// - Adding it to the a class or library using `addMember` or `addClass`.
+/// - Explicitly assigning a name using [CanonicalName.bindTo].
+abstract class LinkedNode extends TreeNode {
+ CanonicalName canonicalName;
+}
+
// ------------------------------------------------------------------------
// LIBRARIES and CLASSES
// ------------------------------------------------------------------------
-class Library extends TreeNode implements Comparable<Library> {
+class Library extends LinkedNode implements Comparable<Library> {
/// An import path to this library.
///
/// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme.
@@ -205,6 +220,10 @@ class Library extends TreeNode implements Comparable<Library> {
<Iterable<Member>>[fields, procedures].expand((x) => x);
void addMember(Member member) {
+ if (member.canonicalName == null || !member.canonicalName.isDummy) {
+ // This should not run from the dart2js/rasta adaptor.
ahe 2017/02/02 16:24:01 Add TODO?
asgerf 2017/02/03 10:31:16 I don't think it actually helps to spray non-actio
+ getCanonicalNameOfLibrary(this).getChildFromMember(member).bindTo(member);
+ }
member.parent = this;
if (member is Procedure) {
procedures.add(member);
@@ -216,6 +235,10 @@ class Library extends TreeNode implements Comparable<Library> {
}
void addClass(Class class_) {
+ if (class_.canonicalName == null || !class_.canonicalName.isDummy) {
+ // This should not run from the dart2js/rasta adaptor.
+ getCanonicalNameOfLibrary(this).getChild(class_.name).bindTo(class_);
+ }
class_.parent = this;
classes.add(class_);
}
@@ -289,7 +312,7 @@ enum ClassLevel {
/// use those from its mixed-in type. However, the IR does not enforce this
/// rule directly, as doing so can obstruct transformations. It is possible to
/// transform a mixin application to become a regular class, and vice versa.
-class Class extends TreeNode {
+class Class extends LinkedNode {
/// The degree to which the contents of the class have been loaded.
ClassLevel level = ClassLevel.Body;
@@ -397,6 +420,10 @@ class Class extends TreeNode {
/// Throws an error if attempting to add a field or procedure to a mixin
/// application.
void addMember(Member member) {
+ if (member.canonicalName == null || !member.canonicalName.isDummy) {
+ // This should not run from the dart2js/rasta adaptor.
+ getCanonicalNameOfClass(this).getChildFromMember(member).bindTo(member);
+ }
member.parent = this;
if (member is Constructor) {
constructors.add(member);
@@ -490,14 +517,7 @@ class Class extends TreeNode {
// MEMBERS
// ------------------------------------------------------------------------
-/// A indirect reference to a member, which can be updated to point at another
-/// member at a later time.
-class _MemberAccessor {
- Member target;
- _MemberAccessor(this.target);
-}
-
-abstract class Member extends TreeNode {
+abstract class Member extends LinkedNode {
/// End offset in the source file it comes from. Valid values are from 0 and
/// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available
/// (this is the default if none is specifically set).
@@ -585,9 +605,6 @@ abstract class Member extends TreeNode {
bool get containsSuperCalls {
return transformerFlags & TransformerFlag.superCalls != 0;
}
-
- _MemberAccessor get _getterInterface;
- _MemberAccessor get _setterInterface;
}
/// A field declaration.
@@ -595,8 +612,6 @@ abstract class Member extends TreeNode {
/// The implied getter and setter for the field are not represented explicitly,
/// but can be made explicit if needed.
class Field extends Member {
- _MemberAccessor _getterInterface, _setterInterface;
-
DartType type; // Not null. Defaults to DynamicType.
InferredValue inferredValue; // May be null.
int flags = 0;
@@ -617,8 +632,6 @@ class Field extends Member {
int transformerFlags: 0,
this.fileUri})
: super(name) {
- _getterInterface = new _MemberAccessor(this);
- _setterInterface = new _MemberAccessor(this);
assert(type != null);
initializer?.parent = this;
this.isFinal = isFinal;
@@ -718,46 +731,6 @@ class Field extends Member {
DartType get getterType => type;
DartType get setterType => isMutable ? type : const BottomType();
- /// Makes all [PropertyGet]s that have this field as its interface target
- /// use [getter] as its interface target instead.
- ///
- /// That can be used to introduce an explicit getter for a field instead of
- /// its implicit getter.
- ///
- /// This method only updates the stored interface target -- the caller must
- /// ensure that [getter] actually becomes the target for dispatches that
- /// would previously hit the implicit field getter.
- ///
- /// [DirectPropertyGet]s are not affected, and will continue to access the
- /// field directly. [PropertyGet] nodes created after the call will not be
- /// affected until the method is called again.
- ///
- /// Existing [ClassHierarchy] instances are not affected by this call.
- void replaceGetterInterfaceWith(Procedure getter) {
- _getterInterface.target = getter;
- _getterInterface = new _MemberAccessor(this);
- }
-
- /// Makes all [PropertySet]s that have this field as its interface target
- /// use [setter] as its interface target instead.
- ///
- /// That can be used to introduce an explicit setter for a field instead of
- /// its implicit setter.
- ///
- /// This method only updates the stored interface target -- the caller must
- /// ensure that [setter] actually becomes the target for dispatches that
- /// would previously hit the implicit field setter.
- ///
- /// [DirectPropertySet] and [FieldInitializer]s are not affected, and will
- /// continue to access the field directly. [PropertySet] nodes created after
- /// the call will not be affected until the method is called again.
- ///
- /// Existing [ClassHierarchy] instances are not affected by this call.
- void replaceSetterInterfaceWith(Procedure setter) {
- _setterInterface.target = setter;
- _setterInterface = new _MemberAccessor(this);
- }
-
Location _getLocationInEnclosingFile(int offset) {
return enclosingProgram.getLocation(fileUri, offset);
}
@@ -832,14 +805,6 @@ class Constructor extends Member {
DartType get getterType => const BottomType();
DartType get setterType => const BottomType();
-
- _MemberAccessor get _getterInterface {
- throw 'Constructors cannot be used as getters';
- }
-
- _MemberAccessor get _setterInterface {
- throw 'Constructors cannot be used as setters';
- }
}
/// A method, getter, setter, index-getter, index-setter, operator overloader,
@@ -858,7 +823,6 @@ class Constructor extends Member {
/// For operators, this is the token for the operator, e.g. `+` or `==`,
/// except for the unary minus operator, whose name is `unary-`.
class Procedure extends Member {
- _MemberAccessor _reference;
ProcedureKind kind;
int flags = 0;
FunctionNode function; // Body is null if and only if abstract or external.
@@ -874,7 +838,6 @@ class Procedure extends Member {
int transformerFlags: 0,
this.fileUri})
: super(name) {
- _reference = new _MemberAccessor(this);
function?.parent = this;
this.isAbstract = isAbstract;
this.isStatic = isStatic;
@@ -947,9 +910,6 @@ class Procedure extends Member {
: const BottomType();
}
- _MemberAccessor get _getterInterface => _reference;
- _MemberAccessor get _setterInterface => _reference;
-
Location _getLocationInEnclosingFile(int offset) {
return enclosingProgram.getLocation(fileUri, offset);
}
@@ -995,13 +955,22 @@ class InvalidInitializer extends Initializer {
// exactly once, and that no fields are assigned twice in the initializer list.
class FieldInitializer extends Initializer {
/// Reference to the field being initialized. Not null.
- Field field;
+ CanonicalName fieldName;
Expression value;
- FieldInitializer(this.field, this.value) {
+ FieldInitializer(Field field, Expression value)
+ : this.byName(getCanonicalNameOfMember(field), value);
+
+ FieldInitializer.byName(this.fieldName, this.value) {
value?.parent = this;
}
+ Field get field => fieldName?.asField;
+
+ void set field(Field field) {
+ fieldName = getCanonicalNameOfMember(field);
+ }
+
accept(InitializerVisitor v) => v.visitFieldInitializer(this);
visitChildren(Visitor v) {
@@ -1028,13 +997,22 @@ class FieldInitializer extends Initializer {
// from the extends clause.
class SuperInitializer extends Initializer {
/// Reference to the constructor being invoked in the super class. Not null.
- Constructor target;
+ CanonicalName targetName;
Arguments arguments;
- SuperInitializer(this.target, this.arguments) {
+ SuperInitializer(Constructor target, Arguments arguments)
+ : this.byName(getCanonicalNameOfMember(target), arguments);
+
+ SuperInitializer.byName(this.targetName, this.arguments) {
arguments?.parent = this;
}
+ Constructor get target => targetName?.asConstructor;
+
+ void set target(Constructor target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
accept(InitializerVisitor v) => v.visitSuperInitializer(this);
visitChildren(Visitor v) {
@@ -1057,13 +1035,22 @@ class SuperInitializer extends Initializer {
// constructor has a body or if there is a cycle in the initializer calls.
class RedirectingInitializer extends Initializer {
/// Reference to the constructor being invoked in the same class. Not null.
- Constructor target;
+ CanonicalName targetName;
Arguments arguments;
- RedirectingInitializer(this.target, this.arguments) {
+ RedirectingInitializer(Constructor target, Arguments arguments)
+ : this.byName(getCanonicalNameOfMember(target), arguments);
+
+ RedirectingInitializer.byName(this.targetName, this.arguments) {
arguments?.parent = this;
}
+ Constructor get target => targetName?.asConstructor;
+
+ void set target(Constructor target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
accept(InitializerVisitor v) => v.visitRedirectingInitializer(this);
visitChildren(Visitor v) {
@@ -1356,17 +1343,19 @@ class PropertyGet extends Expression {
Expression receiver;
Name name;
- _MemberAccessor _interfaceTargetReference;
+ CanonicalName interfaceTargetName;
+
+ PropertyGet(Expression receiver, Name name, [Member interfaceTarget])
+ : this.byName(receiver, name, getCanonicalNameOfMember(interfaceTarget));
- PropertyGet(this.receiver, this.name, [Member interfaceTarget]) {
+ PropertyGet.byName(this.receiver, this.name, this.interfaceTargetName) {
receiver?.parent = this;
- this.interfaceTarget = interfaceTarget;
}
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ Member get interfaceTarget => interfaceTargetName?.asMember;
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._getterInterface;
+ void set interfaceTarget(Member member) {
+ interfaceTargetName = getCanonicalNameOfMember(member);
}
DartType getStaticType(TypeEnvironment types) {
@@ -1413,18 +1402,23 @@ class PropertySet extends Expression {
Name name;
Expression value;
- _MemberAccessor _interfaceTargetReference;
+ CanonicalName interfaceTargetName;
+
+ PropertySet(Expression receiver, Name name, Expression value,
+ [Member interfaceTarget])
+ : this.byName(
+ receiver, name, value, getCanonicalNameOfMember(interfaceTarget));
- PropertySet(this.receiver, this.name, this.value, [Member interfaceTarget]) {
+ PropertySet.byName(
+ this.receiver, this.name, this.value, this.interfaceTargetName) {
receiver?.parent = this;
value?.parent = this;
- this.interfaceTarget = interfaceTarget;
}
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ Member get interfaceTarget => interfaceTargetName?.asMember;
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._setterInterface;
+ void set interfaceTarget(Member member) {
+ interfaceTargetName = getCanonicalNameOfMember(member);
}
DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
@@ -1452,12 +1446,21 @@ class PropertySet extends Expression {
/// Directly read a field, call a getter, or tear off a method.
class DirectPropertyGet extends Expression {
Expression receiver;
- Member target;
+ CanonicalName targetName;
- DirectPropertyGet(this.receiver, this.target) {
+ DirectPropertyGet(Expression receiver, Member target)
+ : this.byName(receiver, getCanonicalNameOfMember(target));
+
+ DirectPropertyGet.byName(this.receiver, this.targetName) {
receiver?.parent = this;
}
+ Member get target => targetName?.asMember;
+
+ void set target(Member target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
visitChildren(Visitor v) {
receiver?.accept(v);
target?.acceptReference(v);
@@ -1486,14 +1489,23 @@ class DirectPropertyGet extends Expression {
/// Evaluates to the value of [value].
class DirectPropertySet extends Expression {
Expression receiver;
- Member target;
+ CanonicalName targetName;
Expression value;
- DirectPropertySet(this.receiver, this.target, this.value) {
+ DirectPropertySet(Expression receiver, Member target, Expression value)
+ : this.byName(receiver, getCanonicalNameOfMember(target), value);
+
+ DirectPropertySet.byName(this.receiver, this.targetName, this.value) {
receiver?.parent = this;
value?.parent = this;
}
+ Member get target => targetName?.asMember;
+
+ void set target(Member target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
visitChildren(Visitor v) {
receiver?.accept(v);
target?.acceptReference(v);
@@ -1519,14 +1531,25 @@ class DirectPropertySet extends Expression {
/// Directly call an instance method, bypassing ordinary dispatch.
class DirectMethodInvocation extends Expression {
Expression receiver;
- Procedure target;
+ CanonicalName targetName;
Arguments arguments;
- DirectMethodInvocation(this.receiver, this.target, this.arguments) {
+ DirectMethodInvocation(
+ Expression receiver, Procedure target, Arguments arguments)
+ : this.byName(receiver, getCanonicalNameOfMember(target), arguments);
+
+ DirectMethodInvocation.byName(
+ this.receiver, this.targetName, this.arguments) {
receiver?.parent = this;
arguments?.parent = this;
}
+ Procedure get target => targetName?.asProcedure;
+
+ void set target(Procedure target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
visitChildren(Visitor v) {
receiver?.accept(v);
target?.acceptReference(v);
@@ -1567,16 +1590,17 @@ class DirectMethodInvocation extends Expression {
/// This may invoke a getter, read a field, or tear off a method.
class SuperPropertyGet extends Expression {
Name name;
- _MemberAccessor _interfaceTargetReference;
+ CanonicalName interfaceTargetName;
- SuperPropertyGet(this.name, [Member interfaceTarget]) {
- _interfaceTargetReference = interfaceTarget?._getterInterface;
- }
+ SuperPropertyGet(Name name, [Member interfaceTarget])
+ : this.byName(name, getCanonicalNameOfMember(interfaceTarget));
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ SuperPropertyGet.byName(this.name, this.interfaceTargetName);
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._getterInterface;
+ Member get interfaceTarget => interfaceTargetName?.asMember;
+
+ void set interfaceTarget(Member member) {
+ interfaceTargetName = getCanonicalNameOfMember(member);
}
DartType getStaticType(TypeEnvironment types) {
@@ -1608,17 +1632,19 @@ class SuperPropertyGet extends Expression {
class SuperPropertySet extends Expression {
Name name;
Expression value;
- _MemberAccessor _interfaceTargetReference;
+ CanonicalName interfaceTargetName;
+
+ SuperPropertySet(Name name, Expression value, Member interfaceTarget)
+ : this.byName(name, value, getCanonicalNameOfMember(interfaceTarget));
- SuperPropertySet(this.name, this.value, [Member interfaceTarget]) {
+ SuperPropertySet.byName(this.name, this.value, this.interfaceTargetName) {
value?.parent = this;
- _interfaceTargetReference = interfaceTarget?._setterInterface;
}
- Member get interfaceTarget => _interfaceTargetReference?.target;
+ Member get interfaceTarget => interfaceTargetName?.asMember;
- void set interfaceTarget(Member newTarget) {
- _interfaceTargetReference = newTarget?._setterInterface;
+ void set interfaceTarget(Member member) {
+ interfaceTargetName = getCanonicalNameOfMember(member);
}
DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
@@ -1641,9 +1667,17 @@ class SuperPropertySet extends Expression {
/// Read a static field, call a static getter, or tear off a static method.
class StaticGet extends Expression {
/// A static field, getter, or method (for tear-off).
- Member target;
+ CanonicalName targetName;
+
+ StaticGet(Member target) : this.byName(getCanonicalNameOfMember(target));
+
+ StaticGet.byName(this.targetName);
- StaticGet(this.target);
+ Member get target => targetName?.asMember;
+
+ void set target(Member target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
DartType getStaticType(TypeEnvironment types) => target.getterType;
@@ -1661,13 +1695,22 @@ class StaticGet extends Expression {
/// Evaluates to the value of [value].
class StaticSet extends Expression {
/// A mutable static field or a static setter.
- Member target;
+ CanonicalName targetName;
Expression value;
- StaticSet(this.target, this.value) {
+ StaticSet(Member target, Expression value)
+ : this.byName(getCanonicalNameOfMember(target), value);
+
+ StaticSet.byName(this.targetName, this.value) {
value?.parent = this;
}
+ Member get target => targetName?.asMember;
+
+ void set target(Member target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
accept(ExpressionVisitor v) => v.visitStaticSet(this);
@@ -1761,14 +1804,25 @@ class MethodInvocation extends InvocationExpression {
Name name;
Arguments arguments;
- Procedure interfaceTarget;
+ CanonicalName interfaceTargetName;
+
+ MethodInvocation(Expression receiver, Name name, Arguments arguments,
+ [Procedure interfaceTarget])
+ : this.byName(receiver, name, arguments,
+ getCanonicalNameOfMember(interfaceTarget));
- MethodInvocation(this.receiver, this.name, this.arguments,
- [this.interfaceTarget]) {
+ MethodInvocation.byName(
+ this.receiver, this.name, this.arguments, this.interfaceTargetName) {
receiver?.parent = this;
arguments?.parent = this;
}
+ Procedure get interfaceTarget => interfaceTargetName?.asProcedure;
+
+ void set interfaceTarget(Member target) {
+ interfaceTargetName = getCanonicalNameOfMember(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
if (interfaceTarget != null) {
if (types.isOverloadedArithmeticOperator(interfaceTarget)) {
@@ -1830,12 +1884,23 @@ class SuperMethodInvocation extends InvocationExpression {
Name name;
Arguments arguments;
- Member interfaceTarget;
+ CanonicalName interfaceTargetName;
- SuperMethodInvocation(this.name, this.arguments, this.interfaceTarget) {
+ SuperMethodInvocation(Name name, Arguments arguments,
+ [Procedure interfaceTarget])
+ : this.byName(name, arguments, getCanonicalNameOfMember(interfaceTarget));
+
+ SuperMethodInvocation.byName(
+ this.name, this.arguments, this.interfaceTargetName) {
arguments?.parent = this;
}
+ Procedure get interfaceTarget => interfaceTargetName?.asProcedure;
+
+ void set interfaceTarget(Procedure target) {
+ interfaceTargetName = getCanonicalNameOfMember(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
if (interfaceTarget == null) return const DynamicType();
Class superclass = interfaceTarget.enclosingClass;
@@ -1869,7 +1934,7 @@ class SuperMethodInvocation extends InvocationExpression {
///
/// The provided arguments might not match the parameters of the target.
class StaticInvocation extends InvocationExpression {
- Procedure target;
+ CanonicalName targetName;
Arguments arguments;
/// True if this is a constant call to an external constant factory.
@@ -1877,10 +1942,21 @@ class StaticInvocation extends InvocationExpression {
Name get name => target?.name;
- StaticInvocation(this.target, this.arguments, {this.isConst: false}) {
+ StaticInvocation(Procedure target, Arguments arguments, {bool isConst: false})
+ : this.byName(getCanonicalNameOfMember(target), arguments,
+ isConst: isConst);
+
+ StaticInvocation.byName(this.targetName, this.arguments,
+ {this.isConst: false}) {
arguments?.parent = this;
}
+ Procedure get target => targetName?.asProcedure;
+
+ void set target(Procedure target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
return Substitution
.fromPairs(target.function.typeParameters, arguments.types)
@@ -1910,16 +1986,28 @@ class StaticInvocation extends InvocationExpression {
// `classTypeArguments`? They are quite different from type arguments to
// generic functions.
class ConstructorInvocation extends InvocationExpression {
- Constructor target;
+ CanonicalName targetName;
Arguments arguments;
bool isConst;
Name get name => target?.name;
- ConstructorInvocation(this.target, this.arguments, {this.isConst: false}) {
+ ConstructorInvocation(Constructor target, Arguments arguments,
+ {bool isConst: false})
+ : this.byName(getCanonicalNameOfMember(target), arguments,
+ isConst: isConst);
+
+ ConstructorInvocation.byName(this.targetName, this.arguments,
+ {this.isConst: false}) {
arguments?.parent = this;
}
+ Constructor get target => targetName?.asConstructor;
+
+ void set target(Constructor target) {
+ targetName = getCanonicalNameOfMember(target);
+ }
+
DartType getStaticType(TypeEnvironment types) {
return arguments.types.isEmpty
? target.enclosingClass.rawType
@@ -3121,17 +3209,21 @@ class FunctionDeclaration extends Statement {
abstract class Name implements Node {
final int hashCode;
final String name;
+ CanonicalName get libraryName;
Library get library;
bool get isPrivate;
Name._internal(this.hashCode, this.name);
- factory Name(String name, [Library library]) {
+ factory Name(String name, [Library library]) =>
+ new Name.byReference(name, library?.canonicalName);
+
+ factory Name.byReference(String name, CanonicalName libraryName) {
/// Use separate subclasses for the public and private case to save memory
/// for public names.
if (name.startsWith('_')) {
- assert(library != null);
- return new _PrivateName(name, library);
+ assert(libraryName != null);
+ return new _PrivateName(name, libraryName);
} else {
return new _PublicName(name);
}
@@ -3149,21 +3241,24 @@ abstract class Name implements Node {
}
class _PrivateName extends Name {
- final Library library;
+ final CanonicalName libraryName;
bool get isPrivate => true;
- _PrivateName(String name, Library library)
- : this.library = library,
- super._internal(_computeHashCode(name, library), name);
+ _PrivateName(String name, CanonicalName libraryName)
+ : this.libraryName = libraryName,
+ super._internal(_computeHashCode(name, libraryName), name);
String toString() => library != null ? '$library::$name' : name;
- static int _computeHashCode(String name, Library library) {
- return 131 * name.hashCode + 17 * library.hashCode;
+ Library get library => libraryName.asLibrary;
+
+ static int _computeHashCode(String name, CanonicalName libraryName) {
+ return 131 * name.hashCode + 17 * libraryName.hashCode;
}
}
class _PublicName extends Name {
+ CanonicalName get libraryName => null;
Library get library => null;
bool get isPrivate => false;
@@ -3243,14 +3338,18 @@ class BottomType extends DartType {
}
class InterfaceType extends DartType {
- final Class classNode;
+ final CanonicalName className;
final List<DartType> typeArguments;
/// The [typeArguments] list must not be modified after this call. If the
/// list is omitted, 'dynamic' type arguments are filled in.
InterfaceType(Class classNode, [List<DartType> typeArguments])
- : this.classNode = classNode,
- this.typeArguments = typeArguments ?? _defaultTypeArguments(classNode);
+ : this.byName(getCanonicalNameOfClass(classNode),
+ typeArguments ?? _defaultTypeArguments(classNode));
+
+ InterfaceType.byName(this.className, this.typeArguments);
+
+ Class get classNode => className.asClass;
static List<DartType> _defaultTypeArguments(Class classNode) {
if (classNode.typeParameters.length == 0) {
@@ -3272,7 +3371,7 @@ class InterfaceType extends DartType {
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is InterfaceType) {
- if (classNode != other.classNode) return false;
+ if (className != other.className) return false;
if (typeArguments.length != other.typeArguments.length) return false;
for (int i = 0; i < typeArguments.length; ++i) {
if (typeArguments[i] != other.typeArguments[i]) return false;
@@ -3284,7 +3383,7 @@ class InterfaceType extends DartType {
}
int get hashCode {
- int hash = 0x3fffffff & classNode.hashCode;
+ int hash = 0x3fffffff & className.hashCode;
for (int i = 0; i < typeArguments.length; ++i) {
hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
}
@@ -3472,10 +3571,15 @@ class TypeParameter extends TreeNode {
}
class Supertype extends Node {
- final Class classNode;
+ final CanonicalName className;
final List<DartType> typeArguments;
- Supertype(this.classNode, this.typeArguments);
+ Supertype(Class classNode, List<DartType> typeArguments)
+ : this.byName(getCanonicalNameOfClass(classNode), typeArguments);
+
+ Supertype.byName(this.className, this.typeArguments);
+
+ Class get classNode => className.asClass;
accept(Visitor v) => v.visitSupertype(this);
@@ -3491,7 +3595,7 @@ class Supertype extends Node {
bool operator ==(Object other) {
if (identical(this, other)) return true;
if (other is Supertype) {
- if (classNode != other.classNode) return false;
+ if (className != other.className) return false;
if (typeArguments.length != other.typeArguments.length) return false;
for (int i = 0; i < typeArguments.length; ++i) {
if (typeArguments[i] != other.typeArguments[i]) return false;
@@ -3503,7 +3607,7 @@ class Supertype extends Node {
}
int get hashCode {
- int hash = 0x3fffffff & classNode.hashCode;
+ int hash = 0x3fffffff & className.hashCode;
for (int i = 0; i < typeArguments.length; ++i) {
hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
}
@@ -3517,6 +3621,8 @@ class Supertype extends Node {
/// A way to bundle up all the libraries in a program.
class Program extends TreeNode {
+ final CanonicalName root = new CanonicalName.root();
+
final List<Library> libraries;
/// Map from a source file uri to a line-starts table and source code.
@@ -3525,12 +3631,18 @@ class Program extends TreeNode {
final Map<String, Source> uriToSource;
/// Reference to the main method in one of the libraries.
- Procedure mainMethod;
+ CanonicalName mainMethodName;
Program([List<Library> libraries, Map<String, Source> uriToSource])
: libraries = libraries ?? <Library>[],
uriToSource = uriToSource ?? <String, Source>{} {
- setParents(libraries, this);
+ setParents(this.libraries, this);
+ }
+
+ Procedure get mainMethod => mainMethodName?.asProcedure;
+
+ void set mainMethod(Procedure main) {
+ mainMethodName = getCanonicalNameOfMember(main);
}
accept(TreeVisitor v) => v.visitProgram(this);
@@ -3565,6 +3677,20 @@ class Program extends TreeNode {
int columnNumber = 1 + offset - lineStart;
return new Location(file, lineNumber, columnNumber);
}
+
+ Library getLibraryReference(Uri uri) {
+ assert(uri.hasScheme);
+ var canonicalName = root.getChildFromUri(uri);
+ Library library;
+ if (canonicalName.definition == null) {
+ library = new Library(uri, isExternal: true);
+ canonicalName.bindTo(library);
+ libraries.add(library..parent = this);
+ } else {
+ library = canonicalName.definition;
+ }
+ return library;
+ }
}
/// A tuple with file, line, and column number, for displaying human-readable
@@ -3673,3 +3799,51 @@ class Source {
Source(this.lineStarts, this.source);
}
+
+/// Returns the canonical name of [member], or throws an exception if the
+/// member has not been assigned a canonical name yet.
+///
+/// Returns `null` if the member is `null`.
+CanonicalName getCanonicalNameOfMember(Member member) {
+ if (member == null) {
+ return null;
+ }
+ var name = member.canonicalName;
+ if (name == null) {
+ throw '$member has no canonical name. '
+ 'It must be added to a class or library before it can be referenced.';
+ }
+ return name;
+}
+
+/// Returns the canonical name of [class_], or throws an exception if the
+/// class has not been assigned a canonical name yet.
+///
+/// Returns `null` if the class is `null`.
+CanonicalName getCanonicalNameOfClass(Class class_) {
+ if (class_ == null) {
+ return null;
+ }
+ var name = class_.canonicalName;
+ if (name == null) {
+ throw '$class_ has no canonical name. '
+ 'It must be added to a library before it can be referenced.';
+ }
+ return name;
+}
+
+/// Returns the canonical name of [library], or throws an exception if the
+/// library has not been assigned a canonical name yet.
+///
+/// Returns `null` if the library is `null`.
+CanonicalName getCanonicalNameOfLibrary(Library library) {
+ if (library == null) {
+ return null;
+ }
+ var name = library.canonicalName;
+ if (name == null) {
+ throw '$library has no canonical name. '
+ 'It must be added to a program before it can be referenced.';
+ }
+ return name;
+}

Powered by Google App Engine
This is Rietveld 408576698