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

Unified Diff: lib/compiler/implementation/resolver.dart

Issue 10947024: Made dart2js constructor lookup logic "private"-aware, fixed 4740 bug. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixed co19-dart2js.status merge error. Created 8 years, 2 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: lib/compiler/implementation/resolver.dart
diff --git a/lib/compiler/implementation/resolver.dart b/lib/compiler/implementation/resolver.dart
index 7d3eae2b4d500f482a329245e9f842c19d815ab9..aadf9a73fe7a3af1fdeae3aae12f2b501c091979 100644
--- a/lib/compiler/implementation/resolver.dart
+++ b/lib/compiler/implementation/resolver.dart
@@ -87,15 +87,21 @@ class ResolverTask extends CompilerTask {
});
}
- SourceString getConstructorName(Send node) {
- if (node.receiver !== null) {
- return node.selector.asIdentifier().source;
- } else {
- return const SourceString('');
- }
- }
-
- FunctionElement resolveConstructorRedirection(FunctionElement constructor) {
+ bool isNamedConstructor(Send node) => node.receiver !== null;
ahe 2012/10/11 04:55:40 Add newline between methods.
aam-me 2012/10/11 06:14:00 Done.
+ SourceString getConstructorName(Send node) =>
ahe 2012/10/11 04:55:40 When the function shorthand doesn't fit on one lin
aam-me 2012/10/11 06:14:00 Done.
+ node.selector.asIdentifier().source;
+
+ String createConstructorFullName(SourceString className,
ahe 2012/10/11 04:55:40 As far as I can tell, this is only used for diagno
aam-me 2012/10/11 06:14:00 Done.
+ SourceString constructorName) {
+ String classNameString = className.slowToString();
+ String constructorNameString = constructorName.slowToString();
+ return (constructorName === const SourceString(''))
+ ? classNameString
+ : "$classNameString.$constructorNameString";
+ }
+
+ FunctionElement resolveConstructorRedirection(InitializerResolver resolver,
+ FunctionElement constructor) {
if (constructor.isPatched) {
checkMatchingPatchSignatures(constructor, constructor.patch);
constructor = constructor.patch;
@@ -109,10 +115,17 @@ class ResolverTask extends CompilerTask {
if (!initializers.isEmpty() &&
Initializers.isConstructorRedirect(initializers.head)) {
final ClassElement classElement = constructor.getEnclosingClass();
- final SourceString constructorName =
- getConstructorName(initializers.head);
- final SourceString className = classElement.name;
- return classElement.lookupConstructor(className, constructorName);
+ Selector selector;
+ if (isNamedConstructor(initializers.head)) {
+ SourceString constructorName = getConstructorName(initializers.head);
+ selector = new Selector.callConstructor(
+ constructorName,
+ resolver.visitor.enclosingElement.getLibrary());
+ } else {
+ selector = new Selector.callDefaultConstructor(
+ resolver.visitor.enclosingElement.getLibrary());
+ }
+ return classElement.lookupConstructor(selector);
}
return null;
}
@@ -129,7 +142,7 @@ class ResolverTask extends CompilerTask {
return;
}
seen.add(redirection);
- redirection = resolveConstructorRedirection(redirection);
+ redirection = resolveConstructorRedirection(resolver, redirection);
}
}
@@ -290,26 +303,39 @@ class ResolverTask extends CompilerTask {
// [intrface] is an interface, let's say "MyInterface".
// [defaultClass] is a class, let's say "MyClass".
+ Selector selector;
// If the default class implements the interface then we must use the
// default class' name. Otherwise we look for a factory with the name
// of the interface.
- SourceString name;
if (defaultClass.implementsInterface(intrface)) {
- // TODO(ahe): Don't use string replacement here.
ahe 2012/10/11 04:55:40 Please keep this todo. I still think it is problem
aam-me 2012/10/11 06:14:00 Done.
- name = new SourceString(constructor.name.slowToString().replaceFirst(
- intrface.name.slowToString(),
- defaultClass.name.slowToString()));
+ var constructorNameString = constructor.name.slowToString();
+ // Create selector based on constructor.name but where interface
+ // is replaced with default class name.
+ int classNameSeparatorIndex = constructorNameString.indexOf('\$');
+ if (classNameSeparatorIndex < 0) {
+ selector = new Selector.callDefaultConstructor(
+ defaultClass.getLibrary());
+ } else {
+ selector = new Selector.callConstructor(
+ new SourceString(
+ constructorNameString.substring(classNameSeparatorIndex + 1)),
+ defaultClass.getLibrary());
+ }
+ constructor.defaultImplementation =
+ defaultClass.lookupConstructor(selector);
} else {
- name = constructor.name;
+ selector =
+ new Selector.callConstructor(constructor.name,
+ defaultClass.getLibrary());
+ constructor.defaultImplementation =
+ defaultClass.lookupFactoryConstructor(selector);
}
- constructor.defaultImplementation = defaultClass.lookupConstructor(name);
-
if (constructor.defaultImplementation === null) {
// We failed to find a constructor named either
// "MyInterface.name" or "MyClass.name".
error(node,
MessageKind.CANNOT_FIND_CONSTRUCTOR2,
- [name, defaultClass.name]);
+ [selector.name, defaultClass.name]);
ahe 2012/10/11 04:55:40 I think we're using MyClass$foo here. Could you ad
aam-me 2012/10/11 06:14:00 Done.
}
}
@@ -679,6 +705,21 @@ class InitializerResolver {
visitor.visitInStaticContext(init.arguments.head);
}
+ ClassElement getSuperOrThisLookupTarget(FunctionElement constructor,
+ bool isSuperCall,
+ Node diagnosticNode) {
+ ClassElement lookupTarget = constructor.getEnclosingClass();
+ if (isSuperCall) {
+ // Calculate correct lookup target and constructor name.
+ if (lookupTarget === visitor.compiler.objectClass) {
+ error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
+ } else {
+ lookupTarget = lookupTarget.supertype.element;
ahe 2012/10/11 04:55:40 Just return?
aam-me 2012/10/11 06:14:00 Done.
+ }
+ }
+ return lookupTarget;
+ }
+
Element resolveSuperOrThisForSend(FunctionElement constructor,
FunctionExpression functionNode,
Send call) {
@@ -690,12 +731,39 @@ class InitializerResolver {
});
Selector selector = visitor.mapping.getSelector(call);
bool isSuperCall = Initializers.isSuperConstructorCall(call);
- SourceString constructorName = resolver.getConstructorName(call);
- Element result = resolveSuperOrThis(
- constructor, isSuperCall, false, constructorName, selector, call);
- visitor.useElement(call, result);
- visitor.world.registerStaticUse(result);
- return result;
+
+ ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
+ isSuperCall,
+ call);
+ final SourceString className = lookupTarget.name;
+
+ SourceString constructorName;
+ Selector lookupSelector;
+ if (resolver.isNamedConstructor(call)) {
+ constructorName = resolver.getConstructorName(call);
+ lookupSelector = new Selector.callConstructor(
+ constructorName,
+ visitor.enclosingElement.getLibrary());
+ } else {
+ constructorName = const SourceString('');
+ lookupSelector = new Selector.callDefaultConstructor(
+ visitor.enclosingElement.getLibrary());
+ }
+
+ FunctionElement lookedupConstructor =
+ lookupTarget.lookupConstructor(lookupSelector);
+
+ final bool isImplicitSuperCall = false;
+ verifyThatConstructorMatchesCall(lookedupConstructor,
+ selector,
+ isImplicitSuperCall,
+ call,
+ constructorName,
+ className);
+
+ visitor.useElement(call, lookedupConstructor);
+ visitor.world.registerStaticUse(lookedupConstructor);
+ return lookedupConstructor;
}
void resolveImplicitSuperConstructorSend(FunctionElement constructor,
@@ -706,55 +774,57 @@ class InitializerResolver {
if (classElement != visitor.compiler.objectClass) {
assert(superClass !== null);
assert(superClass.resolutionState == STATE_DONE);
- SourceString name = const SourceString('');
- Selector call = new Selector.call(name, classElement.getLibrary(), 0);
- var element = resolveSuperOrThis(constructor, true, true,
- name, call, functionNode);
- visitor.world.registerStaticUse(element);
- }
- }
-
- Element resolveSuperOrThis(FunctionElement constructor,
- bool isSuperCall,
- bool isImplicitSuperCall,
- SourceString constructorName,
- Selector selector,
- Node diagnosticNode) {
- ClassElement lookupTarget = constructor.getEnclosingClass();
- bool validTarget = true;
- FunctionElement result;
- if (isSuperCall) {
- // Calculate correct lookup target and constructor name.
- if (lookupTarget === visitor.compiler.objectClass) {
- error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
- } else {
- lookupTarget = lookupTarget.supertype.element;
- }
- }
-
- // Lookup constructor and try to match it to the selector.
- ResolverTask resolver = visitor.compiler.resolver;
- final SourceString className = lookupTarget.name;
- result = lookupTarget.lookupConstructor(className, constructorName);
- if (result === null || !result.isGenerativeConstructor()) {
- String classNameString = className.slowToString();
- String constructorNameString = constructorName.slowToString();
- String name = (constructorName === const SourceString(''))
- ? classNameString
- : "$classNameString.$constructorNameString";
+ SourceString constructorName = const SourceString('');
+ Selector callToMatch = new Selector.call(
+ constructorName,
+ classElement.getLibrary(),
+ 0);
+
+ final bool isSuperCall = true;
+ ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
+ isSuperCall,
+ functionNode);
+ final SourceString className = lookupTarget.name;
+ Element calledConstructor = lookupTarget.lookupConstructor(
+ new Selector.callDefaultConstructor(
+ visitor.enclosingElement.getLibrary()));
+
+ final bool isImplicitSuperCall = true;
+ verifyThatConstructorMatchesCall(calledConstructor,
+ callToMatch,
+ isImplicitSuperCall,
+ functionNode,
+ className,
+ const SourceString(''));
+
+ visitor.world.registerStaticUse(calledConstructor);
+ }
+ }
+
+ void verifyThatConstructorMatchesCall(
+ FunctionElement lookedupConstructor,
+ Selector call,
+ bool isImplicitSuperCall,
+ Node diagnosticNode,
+ SourceString className,
+ SourceString constructorName) {
+ if (lookedupConstructor === null
+ || !lookedupConstructor.isGenerativeConstructor()) {
+ var fullConstructorName =
+ visitor.compiler.resolver.createConstructorFullName(className,
+ constructorName);
MessageKind kind = isImplicitSuperCall
- ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
- : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
- error(diagnosticNode, kind, [name]);
+ ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
+ : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
+ error(diagnosticNode, kind, [fullConstructorName]);
} else {
- if (!selector.applies(result, visitor.compiler)) {
+ if (!call.applies(lookedupConstructor, visitor.compiler)) {
MessageKind kind = isImplicitSuperCall
? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
: MessageKind.NO_MATCHING_CONSTRUCTOR;
error(diagnosticNode, kind);
}
}
- return result;
}
FunctionElement resolveRedirection(FunctionElement constructor,
@@ -2798,17 +2868,25 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
Node diagnosticNode,
SourceString constructorName) {
cls.ensureResolved(compiler);
- Element result = cls.lookupConstructor(cls.name, constructorName);
+ Selector selector =
+ constructorName === const SourceString('')
ahe 2012/10/11 04:55:40 Only use == on SourceString.
aam-me 2012/10/11 06:14:00 Done.
+ ? new Selector.callDefaultConstructor(
+ resolver.enclosingElement.getLibrary())
+ : new Selector.callConstructor(
+ constructorName,
+ resolver.enclosingElement.getLibrary());
ahe 2012/10/11 04:55:40 I think I'm seeing this pattern a few times. Would
aam-me 2012/10/11 06:14:00 I don't think this code is used anywhere besides t
+ Element result = cls.lookupConstructor(selector);
if (result === null) {
- String fullConstructorName = cls.name.slowToString();
- if (constructorName !== const SourceString('')) {
- fullConstructorName = '$fullConstructorName'
- '.${constructorName.slowToString()}';
- }
- return failOrReturnErroneousElement(cls, diagnosticNode,
- new SourceString(fullConstructorName),
- MessageKind.CANNOT_FIND_CONSTRUCTOR,
- [fullConstructorName]);
+ String fullConstructorName =
+ resolver.compiler.resolver.createConstructorFullName(
+ cls.name,
+ constructorName);
+ return failOrReturnErroneousElement(
+ cls,
+ diagnosticNode,
+ new SourceString(fullConstructorName),
+ MessageKind.CANNOT_FIND_CONSTRUCTOR,
+ [fullConstructorName]);
} else if (inConstContext && !result.modifiers.isConst()) {
error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
}

Powered by Google App Engine
This is Rietveld 408576698