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

Side by Side Diff: dart/lib/compiler/implementation/resolver.dart

Issue 11184046: Clean up leg.dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 abstract class TreeElements {
6 Element operator[](Node node);
7 Selector getSelector(Send send);
8 DartType getType(TypeAnnotation annotation);
9 bool isParameterChecked(Element element);
10 }
11
12 class TreeElementMapping implements TreeElements {
13 final Element currentElement;
14 final Map<Node, Element> map;
15 final Map<Node, Selector> selectors;
16 final Map<TypeAnnotation, DartType> types;
17 final Set<Element> checkedParameters;
18
19 TreeElementMapping([Element this.currentElement])
20 : map = new LinkedHashMap<Node, Element>(),
21 selectors = new LinkedHashMap<Node, Selector>(),
22 types = new LinkedHashMap<TypeAnnotation, DartType>(),
23 checkedParameters = new Set<Element>();
24
25 operator []=(Node node, Element element) {
26 assert(invariant(node, () {
27 if (node is FunctionExpression) {
28 return !node.modifiers.isExternal();
29 }
30 return true;
31 }));
32 // TODO(johnniwinther): Simplify this invariant to use only declarations in
33 // [TreeElements].
34 assert(invariant(node, () {
35 if (!element.isErroneous() && currentElement != null && element.isPatch) {
36 return currentElement.getImplementationLibrary().isPatch;
37 }
38 return true;
39 }));
40
41 map[node] = element;
42 }
43 operator [](Node node) => map[node];
44 void remove(Node node) { map.remove(node); }
45
46 void setType(TypeAnnotation annotation, DartType type) {
47 types[annotation] = type;
48 }
49
50 DartType getType(TypeAnnotation annotation) => types[annotation];
51
52 void setSelector(Node node, Selector selector) {
53 selectors[node] = selector;
54 }
55
56 Selector getSelector(Node node) => selectors[node];
57
58 bool isParameterChecked(Element element) {
59 return checkedParameters.contains(element);
60 }
61 }
62
63 class ResolverTask extends CompilerTask {
64 ResolverTask(Compiler compiler) : super(compiler);
65
66 String get name => 'Resolver';
67
68 TreeElements resolve(Element element) {
69 return measure(() {
70 ElementKind kind = element.kind;
71 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) ||
72 identical(kind, ElementKind.FUNCTION) ||
73 identical(kind, ElementKind.GETTER) ||
74 identical(kind, ElementKind.SETTER)) {
75 return resolveMethodElement(element);
76 }
77
78 if (identical(kind, ElementKind.FIELD)) return resolveField(element);
79
80 if (identical(kind, ElementKind.PARAMETER) ||
81 identical(kind, ElementKind.FIELD_PARAMETER)) {
82 return resolveParameter(element);
83 }
84
85 compiler.unimplemented("resolve($element)",
86 node: element.parseNode(compiler));
87 });
88 }
89
90 bool isNamedConstructor(Send node) => node.receiver != null;
91
92 SourceString getConstructorName(Send node) {
93 return node.selector.asIdentifier().source;
94 }
95
96 String constructorNameForDiagnostics(SourceString className,
97 SourceString constructorName) {
98 String classNameString = className.slowToString();
99 String constructorNameString = constructorName.slowToString();
100 return (identical(constructorName, const SourceString('')))
101 ? classNameString
102 : "$classNameString.$constructorNameString";
103 }
104
105 FunctionElement resolveConstructorRedirection(InitializerResolver resolver,
106 FunctionElement constructor) {
107 if (constructor.isPatched) {
108 checkMatchingPatchSignatures(constructor, constructor.patch);
109 constructor = constructor.patch;
110 }
111 FunctionExpression node = constructor.parseNode(compiler);
112
113 // A synthetic constructor does not have a node.
114 if (node == null) return null;
115 if (node.initializers == null) return null;
116 Link<Node> initializers = node.initializers.nodes;
117 if (!initializers.isEmpty() &&
118 Initializers.isConstructorRedirect(initializers.head)) {
119 final ClassElement classElement = constructor.getEnclosingClass();
120 Selector selector;
121 if (isNamedConstructor(initializers.head)) {
122 SourceString constructorName = getConstructorName(initializers.head);
123 selector = new Selector.callConstructor(
124 constructorName,
125 resolver.visitor.enclosingElement.getLibrary());
126 } else {
127 selector = new Selector.callDefaultConstructor(
128 resolver.visitor.enclosingElement.getLibrary());
129 }
130 return classElement.lookupConstructor(selector);
131 }
132 return null;
133 }
134
135 void resolveRedirectingConstructor(InitializerResolver resolver,
136 Node node,
137 FunctionElement constructor,
138 FunctionElement redirection) {
139 Set<FunctionElement> seen = new Set<FunctionElement>();
140 seen.add(constructor);
141 while (redirection != null) {
142 if (seen.contains(redirection)) {
143 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
144 return;
145 }
146 seen.add(redirection);
147 redirection = resolveConstructorRedirection(resolver, redirection);
148 }
149 }
150
151 void checkMatchingPatchParameters(FunctionElement origin,
152 Link<Element> originParameters,
153 Link<Element> patchParameters) {
154 while (!originParameters.isEmpty()) {
155 Element originParameter = originParameters.head;
156 Element patchParameter = patchParameters.head;
157 // Hack: Use unparser to test parameter equality. This only works because
158 // we are restricting patch uses and the approach cannot be used
159 // elsewhere.
160 String originParameterText =
161 originParameter.parseNode(compiler).toString();
162 String patchParameterText =
163 patchParameter.parseNode(compiler).toString();
164 if (originParameterText != patchParameterText) {
165 error(originParameter.parseNode(compiler),
166 MessageKind.PATCH_PARAMETER_MISMATCH,
167 [origin.name, originParameterText, patchParameterText]);
168 }
169
170 originParameters = originParameters.tail;
171 patchParameters = patchParameters.tail;
172 }
173 }
174
175 void checkMatchingPatchSignatures(FunctionElement origin,
176 FunctionElement patch) {
177 // TODO(johnniwinther): Show both origin and patch locations on errors.
178 FunctionExpression originTree = compiler.withCurrentElement(origin, () {
179 return origin.parseNode(compiler);
180 });
181 FunctionSignature originSignature = compiler.withCurrentElement(origin, () {
182 return origin.computeSignature(compiler);
183 });
184 FunctionExpression patchTree = compiler.withCurrentElement(patch, () {
185 return patch.parseNode(compiler);
186 });
187 FunctionSignature patchSignature = compiler.withCurrentElement(patch, () {
188 return patch.computeSignature(compiler);
189 });
190
191 if (originSignature.returnType != patchSignature.returnType) {
192 compiler.withCurrentElement(patch, () {
193 Node errorNode =
194 patchTree.returnType != null ? patchTree.returnType : patchTree;
195 error(errorNode, MessageKind.PATCH_RETURN_TYPE_MISMATCH, [origin.name,
196 originSignature.returnType, patchSignature.returnType]);
197 });
198 }
199 if (originSignature.requiredParameterCount !=
200 patchSignature.requiredParameterCount) {
201 compiler.withCurrentElement(patch, () {
202 error(patchTree,
203 MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH,
204 [origin.name, originSignature.requiredParameterCount,
205 patchSignature.requiredParameterCount]);
206 });
207 } else {
208 checkMatchingPatchParameters(origin,
209 originSignature.requiredParameters,
210 patchSignature.requiredParameters);
211 }
212 if (originSignature.optionalParameterCount != 0 &&
213 patchSignature.optionalParameterCount != 0) {
214 if (originSignature.optionalParametersAreNamed !=
215 patchSignature.optionalParametersAreNamed) {
216 compiler.withCurrentElement(patch, () {
217 error(patchTree,
218 MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH,
219 [origin.name]);
220 });
221 }
222 }
223 if (originSignature.optionalParameterCount !=
224 patchSignature.optionalParameterCount) {
225 compiler.withCurrentElement(patch, () {
226 error(patchTree,
227 MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH,
228 [origin.name, originSignature.optionalParameterCount,
229 patchSignature.optionalParameterCount]);
230 });
231 } else {
232 checkMatchingPatchParameters(origin,
233 originSignature.optionalParameters,
234 patchSignature.optionalParameters);
235 }
236 }
237
238 TreeElements resolveMethodElement(FunctionElement element) {
239 assert(invariant(element, element.isDeclaration));
240 return compiler.withCurrentElement(element, () {
241 bool isConstructor =
242 identical(element.kind, ElementKind.GENERATIVE_CONSTRUCTOR);
243 TreeElements elements =
244 compiler.enqueuer.resolution.getCachedElements(element);
245 if (elements != null) {
246 assert(isConstructor);
247 return elements;
248 }
249 if (element.isPatched) {
250 checkMatchingPatchSignatures(element, element.patch);
251 element = element.patch;
252 }
253 return compiler.withCurrentElement(element, () {
254 FunctionExpression tree = element.parseNode(compiler);
255 if (isConstructor) {
256 if (tree.returnType != null) {
257 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE);
258 }
259 resolveConstructorImplementation(element, tree);
260 }
261 ResolverVisitor visitor = new ResolverVisitor(compiler, element);
262 visitor.useElement(tree, element);
263 visitor.setupFunction(tree, element);
264
265 if (isConstructor) {
266 // Even if there is no initializer list we still have to do the
267 // resolution in case there is an implicit super constructor call.
268 InitializerResolver resolver = new InitializerResolver(visitor);
269 FunctionElement redirection =
270 resolver.resolveInitializers(element, tree);
271 if (redirection != null) {
272 resolveRedirectingConstructor(resolver, tree, element, redirection);
273 }
274 } else if (tree.initializers != null) {
275 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER);
276 }
277 visitBody(visitor, tree.body);
278
279 return visitor.mapping;
280 });
281 });
282 }
283
284 void visitBody(ResolverVisitor visitor, Statement body) {
285 visitor.visit(body);
286 }
287
288 void resolveConstructorImplementation(FunctionElement constructor,
289 FunctionExpression node) {
290 if (!identical(constructor.defaultImplementation, constructor)) return;
291 ClassElement intrface = constructor.getEnclosingClass();
292 if (!intrface.isInterface()) return;
293 DartType defaultType = intrface.defaultClass;
294 if (defaultType == null) {
295 error(node, MessageKind.NO_DEFAULT_CLASS, [intrface.name]);
296 }
297 ClassElement defaultClass = defaultType.element;
298 defaultClass.ensureResolved(compiler);
299 assert(defaultClass.resolutionState == STATE_DONE);
300 assert(defaultClass.supertypeLoadState == STATE_DONE);
301 if (defaultClass.isInterface()) {
302 error(node, MessageKind.CANNOT_INSTANTIATE_INTERFACE,
303 [defaultClass.name]);
304 }
305 // We have now established the following:
306 // [intrface] is an interface, let's say "MyInterface".
307 // [defaultClass] is a class, let's say "MyClass".
308
309 Selector selector;
310 // If the default class implements the interface then we must use the
311 // default class' name. Otherwise we look for a factory with the name
312 // of the interface.
313 if (defaultClass.implementsInterface(intrface)) {
314 var constructorNameString = constructor.name.slowToString();
315 // Create selector based on constructor.name but where interface
316 // is replaced with default class name.
317 // TODO(ahe): Don't use string manipulations here.
318 int classNameSeparatorIndex = constructorNameString.indexOf('\$');
319 if (classNameSeparatorIndex < 0) {
320 selector = new Selector.callDefaultConstructor(
321 defaultClass.getLibrary());
322 } else {
323 selector = new Selector.callConstructor(
324 new SourceString(
325 constructorNameString.substring(classNameSeparatorIndex + 1)),
326 defaultClass.getLibrary());
327 }
328 constructor.defaultImplementation =
329 defaultClass.lookupConstructor(selector);
330 } else {
331 selector =
332 new Selector.callConstructor(constructor.name,
333 defaultClass.getLibrary());
334 constructor.defaultImplementation =
335 defaultClass.lookupFactoryConstructor(selector);
336 }
337 if (constructor.defaultImplementation == null) {
338 // We failed to find a constructor named either
339 // "MyInterface.name" or "MyClass.name".
340 // TODO(aprelev@gmail.com): Use constructorNameForDiagnostics in
341 // the error message below.
342 error(node,
343 MessageKind.CANNOT_FIND_CONSTRUCTOR2,
344 [selector.name, defaultClass.name]);
345 }
346 }
347
348 TreeElements resolveField(VariableElement element) {
349 Node tree = element.parseNode(compiler);
350 if(element.modifiers.isStatic() && element.variables.isTopLevel()) {
351 error(element.modifiers.getStatic(), MessageKind.TOP_LEVEL_VARIABLE_DECLAR ED_STATIC);
352 }
353 ResolverVisitor visitor = new ResolverVisitor(compiler, element);
354 initializerDo(tree, visitor.visit);
355 return visitor.mapping;
356 }
357
358 TreeElements resolveParameter(Element element) {
359 Node tree = element.parseNode(compiler);
360 ResolverVisitor visitor =
361 new ResolverVisitor(compiler, element.enclosingElement);
362 initializerDo(tree, visitor.visit);
363 return visitor.mapping;
364 }
365
366 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) {
367 DartType type = resolveReturnType(element, annotation);
368 if (type == compiler.types.voidType) {
369 error(annotation, MessageKind.VOID_NOT_ALLOWED);
370 }
371 return type;
372 }
373
374 DartType resolveReturnType(Element element, TypeAnnotation annotation) {
375 if (annotation == null) return compiler.types.dynamicType;
376 ResolverVisitor visitor = new ResolverVisitor(compiler, element);
377 DartType result = visitor.resolveTypeAnnotation(annotation);
378 if (result == null) {
379 // TODO(karklose): warning.
380 return compiler.types.dynamicType;
381 }
382 return result;
383 }
384
385 /**
386 * Load and resolve the supertypes of [cls].
387 *
388 * Warning: do not call this method directly. It should only be
389 * called by [resolveClass] and [ClassSupertypeResolver].
390 */
391 void loadSupertypes(ClassElement cls, Node from) {
392 compiler.withCurrentElement(cls, () => measure(() {
393 if (cls.supertypeLoadState == STATE_DONE) return;
394 if (cls.supertypeLoadState == STATE_STARTED) {
395 compiler.reportMessage(
396 compiler.spanFromNode(from),
397 MessageKind.CYCLIC_CLASS_HIERARCHY.error([cls.name]),
398 api.Diagnostic.ERROR);
399 cls.supertypeLoadState = STATE_DONE;
400 cls.allSupertypes = const Link<DartType>().prepend(
401 compiler.objectClass.computeType(compiler));
402 // TODO(ahe): We should also set cls.supertype here to avoid
403 // creating a malformed class hierarchy.
404 return;
405 }
406 cls.supertypeLoadState = STATE_STARTED;
407 compiler.withCurrentElement(cls, () {
408 // TODO(ahe): Cache the node in cls.
409 cls.parseNode(compiler).accept(new ClassSupertypeResolver(compiler,
410 cls));
411 if (cls.supertypeLoadState != STATE_DONE) {
412 cls.supertypeLoadState = STATE_DONE;
413 }
414 });
415 }));
416 }
417
418 /**
419 * Resolve the class [element].
420 *
421 * Before calling this method, [element] was constructed by the
422 * scanner and most fields are null or empty. This method fills in
423 * these fields and also ensure that the supertypes of [element] are
424 * resolved.
425 *
426 * Warning: Do not call this method directly. Instead use
427 * [:element.ensureResolved(compiler):].
428 */
429 void resolveClass(ClassElement element) {
430 if (!element.isPatch) {
431 compiler.withCurrentElement(element, () => measure(() {
432 assert(element.resolutionState == STATE_NOT_STARTED);
433 element.resolutionState = STATE_STARTED;
434 ClassNode tree = element.parseNode(compiler);
435 loadSupertypes(element, tree);
436
437 ClassResolverVisitor visitor =
438 new ClassResolverVisitor(compiler, element);
439 visitor.visit(tree);
440 element.resolutionState = STATE_DONE;
441 }));
442 if (element.isPatched) {
443 // Ensure handling patch after origin.
444 element.patch.ensureResolved(compiler);
445 }
446 } else { // Handle patch classes:
447 element.resolutionState = STATE_STARTED;
448 // Ensure handling origin before patch.
449 element.origin.ensureResolved(compiler);
450 // Ensure that the type is computed.
451 element.computeType(compiler);
452 // Copy class hiearchy from origin.
453 element.supertype = element.origin.supertype;
454 element.defaultClass = element.origin.defaultClass;
455 element.interfaces = element.origin.interfaces;
456 element.allSupertypes = element.origin.allSupertypes;
457 // Stepwise assignment to ensure invariant.
458 element.supertypeLoadState = STATE_STARTED;
459 element.supertypeLoadState = STATE_DONE;
460 element.resolutionState = STATE_DONE;
461 // TODO(johnniwinther): Check matching type variables and
462 // empty extends/implements clauses.
463 }
464 }
465
466 void checkMembers(ClassElement cls) {
467 assert(invariant(cls, cls.isDeclaration));
468 if (cls.isObject(compiler)) return;
469 // TODO(johnniwinther): Should this be done on the implementation element as
470 // well?
471 cls.forEachMember((holder, member) {
472 // Perform various checks as side effect of "computing" the type.
473 member.computeType(compiler);
474
475 // Check modifiers.
476 if (member.isFunction() && member.modifiers.isFinal()) {
477 compiler.reportMessage(
478 compiler.spanFromElement(member),
479 MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER.error(),
480 api.Diagnostic.ERROR);
481 }
482 if (member.isConstructor()) {
483 final mismatchedFlagsBits =
484 member.modifiers.flags &
485 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT);
486 if (mismatchedFlagsBits != 0) {
487 final mismatchedFlags =
488 new Modifiers.withFlags(null, mismatchedFlagsBits);
489 compiler.reportMessage(
490 compiler.spanFromElement(member),
491 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS.error([mismatchedFlags]),
492 api.Diagnostic.ERROR);
493 }
494 }
495 checkAbstractField(member);
496 checkValidOverride(member, cls.lookupSuperMember(member.name));
497 });
498 }
499
500 void checkAbstractField(Element member) {
501 // Only check for getters. The test can only fail if there is both a setter
502 // and a getter with the same name, and we only need to check each abstract
503 // field once, so we just ignore setters.
504 if (!member.isGetter()) return;
505
506 // Find the associated abstract field.
507 ClassElement classElement = member.getEnclosingClass();
508 Element lookupElement = classElement.lookupLocalMember(member.name);
509 if (lookupElement == null) {
510 compiler.internalErrorOnElement(member,
511 "No abstract field for accessor");
512 } else if (!identical(lookupElement.kind, ElementKind.ABSTRACT_FIELD)) {
513 compiler.internalErrorOnElement(
514 member, "Inaccessible abstract field for accessor");
515 }
516 AbstractFieldElement field = lookupElement;
517
518 if (field.getter == null) return;
519 if (field.setter == null) return;
520 int getterFlags = field.getter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
521 int setterFlags = field.setter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
522 if (!identical(getterFlags, setterFlags)) {
523 final mismatchedFlags =
524 new Modifiers.withFlags(null, getterFlags ^ setterFlags);
525 compiler.reportMessage(
526 compiler.spanFromElement(field.getter),
527 MessageKind.GETTER_MISMATCH.error([mismatchedFlags]),
528 api.Diagnostic.ERROR);
529 compiler.reportMessage(
530 compiler.spanFromElement(field.setter),
531 MessageKind.SETTER_MISMATCH.error([mismatchedFlags]),
532 api.Diagnostic.ERROR);
533 }
534 }
535
536 reportErrorWithContext(Element errorneousElement,
537 MessageKind errorMessage,
538 Element contextElement,
539 MessageKind contextMessage) {
540 compiler.reportMessage(
541 compiler.spanFromElement(errorneousElement),
542 errorMessage.error([contextElement.name,
543 contextElement.getEnclosingClass().name]),
544 api.Diagnostic.ERROR);
545 compiler.reportMessage(
546 compiler.spanFromElement(contextElement),
547 contextMessage.error(),
548 api.Diagnostic.INFO);
549 }
550
551 void checkValidOverride(Element member, Element superMember) {
552 if (superMember == null) return;
553 if (member.modifiers.isStatic()) {
554 reportErrorWithContext(
555 member, MessageKind.NO_STATIC_OVERRIDE,
556 superMember, MessageKind.NO_STATIC_OVERRIDE_CONT);
557 } else {
558 FunctionElement superFunction = superMember.asFunctionElement();
559 FunctionElement function = member.asFunctionElement();
560 if (superFunction == null || superFunction.isAccessor()) {
561 // Field or accessor in super.
562 if (function != null && !function.isAccessor()) {
563 // But a plain method in this class.
564 reportErrorWithContext(
565 member, MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD,
566 superMember, MessageKind.CANNOT_OVERRIDE_FIELD_WITH_METHOD_CONT);
567 }
568 } else {
569 // Instance method in super.
570 if (function == null || function.isAccessor()) {
571 // But a field (or accessor) in this class.
572 reportErrorWithContext(
573 member, MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD,
574 superMember, MessageKind.CANNOT_OVERRIDE_METHOD_WITH_FIELD_CONT);
575 } else {
576 // Both are plain instance methods.
577 if (superFunction.requiredParameterCount(compiler) !=
578 function.requiredParameterCount(compiler)) {
579 reportErrorWithContext(
580 member,
581 MessageKind.BAD_ARITY_OVERRIDE,
582 superMember,
583 MessageKind.BAD_ARITY_OVERRIDE_CONT);
584 }
585 // TODO(ahe): Check optional parameters.
586 }
587 }
588 }
589 }
590
591 FunctionSignature resolveSignature(FunctionElement element) {
592 return compiler.withCurrentElement(element, () {
593 FunctionExpression node =
594 compiler.parser.measure(() => element.parseNode(compiler));
595 return measure(() => SignatureResolver.analyze(
596 compiler, node.parameters, node.returnType, element));
597 });
598 }
599
600 FunctionSignature resolveFunctionExpression(Element element,
601 FunctionExpression node) {
602 return measure(() => SignatureResolver.analyze(
603 compiler, node.parameters, node.returnType, element));
604 }
605
606 void resolveTypedef(TypedefElement element) {
607 if (element.isResolved || element.isBeingResolved) return;
608 element.isBeingResolved = true;
609 return compiler.withCurrentElement(element, () {
610 measure(() {
611 Typedef node =
612 compiler.parser.measure(() => element.parseNode(compiler));
613 TypedefResolverVisitor visitor =
614 new TypedefResolverVisitor(compiler, element);
615 visitor.visit(node);
616
617 element.isBeingResolved = false;
618 element.isResolved = true;
619 });
620 });
621 }
622
623 FunctionType computeFunctionType(Element element,
624 FunctionSignature signature) {
625 LinkBuilder<DartType> parameterTypes = new LinkBuilder<DartType>();
626 for (Link<Element> link = signature.requiredParameters;
627 !link.isEmpty();
628 link = link.tail) {
629 parameterTypes.addLast(link.head.computeType(compiler));
630 // TODO(karlklose): optional parameters.
631 }
632 return new FunctionType(signature.returnType,
633 parameterTypes.toLink(),
634 element);
635 }
636
637 void resolveMetadataAnnotation(PartialMetadataAnnotation annotation) {
638 compiler.withCurrentElement(annotation.annotatedElement, () => measure(() {
639 assert(annotation.resolutionState == STATE_NOT_STARTED);
640 annotation.resolutionState = STATE_STARTED;
641
642 Node node = annotation.parseNode(compiler);
643 ResolverVisitor visitor = new ResolverVisitor(
644 compiler, annotation.annotatedElement.enclosingElement);
645 node.accept(visitor);
646 annotation.value = compiler.constantHandler.compileNodeWithDefinitions(
647 node, visitor.mapping);
648
649 annotation.resolutionState = STATE_DONE;
650 }));
651 }
652
653 error(Node node, MessageKind kind, [arguments = const []]) {
654 ResolutionError message = new ResolutionError(kind, arguments);
655 compiler.reportError(node, message);
656 }
657 }
658
659 class InitializerResolver {
660 final ResolverVisitor visitor;
661 final Map<SourceString, Node> initialized;
662 Link<Node> initializers;
663 bool hasSuper;
664
665 InitializerResolver(this.visitor)
666 : initialized = new Map<SourceString, Node>(), hasSuper = false;
667
668 error(Node node, MessageKind kind, [arguments = const []]) {
669 visitor.error(node, kind, arguments);
670 }
671
672 warning(Node node, MessageKind kind, [arguments = const []]) {
673 visitor.warning(node, kind, arguments);
674 }
675
676 bool isFieldInitializer(SendSet node) {
677 if (node.selector.asIdentifier() == null) return false;
678 if (node.receiver == null) return true;
679 if (node.receiver.asIdentifier() == null) return false;
680 return node.receiver.asIdentifier().isThis();
681 }
682
683 void checkForDuplicateInitializers(SourceString name, Node init) {
684 if (initialized.containsKey(name)) {
685 error(init, MessageKind.DUPLICATE_INITIALIZER, [name]);
686 warning(initialized[name], MessageKind.ALREADY_INITIALIZED, [name]);
687 }
688 initialized[name] = init;
689 }
690
691 void resolveFieldInitializer(FunctionElement constructor, SendSet init) {
692 // init is of the form [this.]field = value.
693 final Node selector = init.selector;
694 final SourceString name = selector.asIdentifier().source;
695 // Lookup target field.
696 Element target;
697 if (isFieldInitializer(init)) {
698 Scope localScope = constructor.getEnclosingClass().buildLocalScope();
699 target = localScope.lookup(name);
700 if (target == null) {
701 error(selector, MessageKind.CANNOT_RESOLVE, [name]);
702 } else if (target.kind != ElementKind.FIELD) {
703 error(selector, MessageKind.NOT_A_FIELD, [name]);
704 } else if (!target.isInstanceMember()) {
705 error(selector, MessageKind.INIT_STATIC_FIELD, [name]);
706 }
707 } else {
708 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
709 }
710 visitor.useElement(init, target);
711 visitor.world.registerStaticUse(target);
712 checkForDuplicateInitializers(name, init);
713 // Resolve initializing value.
714 visitor.visitInStaticContext(init.arguments.head);
715 }
716
717 ClassElement getSuperOrThisLookupTarget(FunctionElement constructor,
718 bool isSuperCall,
719 Node diagnosticNode) {
720 ClassElement lookupTarget = constructor.getEnclosingClass();
721 if (isSuperCall) {
722 // Calculate correct lookup target and constructor name.
723 if (identical(lookupTarget, visitor.compiler.objectClass)) {
724 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
725 } else {
726 return lookupTarget.supertype.element;
727 }
728 }
729 return lookupTarget;
730 }
731
732 Element resolveSuperOrThisForSend(FunctionElement constructor,
733 FunctionExpression functionNode,
734 Send call) {
735 // Resolve the selector and the arguments.
736 ResolverTask resolver = visitor.compiler.resolver;
737 visitor.inStaticContext(() {
738 visitor.resolveSelector(call);
739 visitor.resolveArguments(call.argumentsNode);
740 });
741 Selector selector = visitor.mapping.getSelector(call);
742 bool isSuperCall = Initializers.isSuperConstructorCall(call);
743
744 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
745 isSuperCall,
746 call);
747 final SourceString className = lookupTarget.name;
748
749 SourceString constructorName;
750 Selector lookupSelector;
751 if (resolver.isNamedConstructor(call)) {
752 constructorName = resolver.getConstructorName(call);
753 lookupSelector = new Selector.callConstructor(
754 constructorName,
755 visitor.enclosingElement.getLibrary());
756 } else {
757 constructorName = const SourceString('');
758 lookupSelector = new Selector.callDefaultConstructor(
759 visitor.enclosingElement.getLibrary());
760 }
761
762 FunctionElement lookedupConstructor =
763 lookupTarget.lookupConstructor(lookupSelector);
764
765 final bool isImplicitSuperCall = false;
766 verifyThatConstructorMatchesCall(lookedupConstructor,
767 selector,
768 isImplicitSuperCall,
769 call,
770 constructorName,
771 className);
772
773 visitor.useElement(call, lookedupConstructor);
774 visitor.world.registerStaticUse(lookedupConstructor);
775 return lookedupConstructor;
776 }
777
778 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
779 FunctionExpression functionNode) {
780 // If the class has a super resolve the implicit super call.
781 ClassElement classElement = constructor.getEnclosingClass();
782 ClassElement superClass = classElement.superclass;
783 if (classElement != visitor.compiler.objectClass) {
784 assert(superClass != null);
785 assert(superClass.resolutionState == STATE_DONE);
786 SourceString constructorName = const SourceString('');
787 Selector callToMatch = new Selector.call(
788 constructorName,
789 classElement.getLibrary(),
790 0);
791
792 final bool isSuperCall = true;
793 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
794 isSuperCall,
795 functionNode);
796 final SourceString className = lookupTarget.name;
797 Element calledConstructor = lookupTarget.lookupConstructor(
798 new Selector.callDefaultConstructor(
799 visitor.enclosingElement.getLibrary()));
800
801 final bool isImplicitSuperCall = true;
802 verifyThatConstructorMatchesCall(calledConstructor,
803 callToMatch,
804 isImplicitSuperCall,
805 functionNode,
806 className,
807 const SourceString(''));
808
809 visitor.world.registerStaticUse(calledConstructor);
810 }
811 }
812
813 void verifyThatConstructorMatchesCall(
814 FunctionElement lookedupConstructor,
815 Selector call,
816 bool isImplicitSuperCall,
817 Node diagnosticNode,
818 SourceString className,
819 SourceString constructorName) {
820 if (lookedupConstructor == null
821 || !lookedupConstructor.isGenerativeConstructor()) {
822 var fullConstructorName =
823 visitor.compiler.resolver.constructorNameForDiagnostics(className,
824 constructorName);
825 MessageKind kind = isImplicitSuperCall
826 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
827 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
828 error(diagnosticNode, kind, [fullConstructorName]);
829 } else {
830 if (!call.applies(lookedupConstructor, visitor.compiler)) {
831 MessageKind kind = isImplicitSuperCall
832 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
833 : MessageKind.NO_MATCHING_CONSTRUCTOR;
834 error(diagnosticNode, kind);
835 }
836 }
837 }
838
839 FunctionElement resolveRedirection(FunctionElement constructor,
840 FunctionExpression functionNode) {
841 if (functionNode.initializers == null) return null;
842 Link<Node> link = functionNode.initializers.nodes;
843 if (!link.isEmpty() && Initializers.isConstructorRedirect(link.head)) {
844 return resolveSuperOrThisForSend(constructor, functionNode, link.head);
845 }
846 return null;
847 }
848
849 /**
850 * Resolve all initializers of this constructor. In the case of a redirecting
851 * constructor, the resolved constructor's function element is returned.
852 */
853 FunctionElement resolveInitializers(FunctionElement constructor,
854 FunctionExpression functionNode) {
855 // Keep track of all "this.param" parameters specified for constructor so
856 // that we can ensure that fields are initialized only once.
857 FunctionSignature functionParameters =
858 constructor.computeSignature(visitor.compiler);
859 functionParameters.forEachParameter((Element element) {
860 if (identical(element.kind, ElementKind.FIELD_PARAMETER)) {
861 checkForDuplicateInitializers(element.name,
862 element.parseNode(visitor.compiler));
863 }
864 });
865
866 if (functionNode.initializers == null) {
867 initializers = const Link<Node>();
868 } else {
869 initializers = functionNode.initializers.nodes;
870 }
871 FunctionElement result;
872 bool resolvedSuper = false;
873 for (Link<Node> link = initializers;
874 !link.isEmpty();
875 link = link.tail) {
876 if (link.head.asSendSet() != null) {
877 final SendSet init = link.head.asSendSet();
878 resolveFieldInitializer(constructor, init);
879 } else if (link.head.asSend() != null) {
880 final Send call = link.head.asSend();
881 if (Initializers.isSuperConstructorCall(call)) {
882 if (resolvedSuper) {
883 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER);
884 }
885 resolveSuperOrThisForSend(constructor, functionNode, call);
886 resolvedSuper = true;
887 } else if (Initializers.isConstructorRedirect(call)) {
888 // Check that there is no body (Language specification 7.5.1).
889 if (functionNode.hasBody()) {
890 error(functionNode, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY);
891 }
892 // Check that there are no other initializers.
893 if (!initializers.tail.isEmpty()) {
894 error(call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER);
895 }
896 return resolveSuperOrThisForSend(constructor, functionNode, call);
897 } else {
898 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED);
899 return null;
900 }
901 } else {
902 error(link.head, MessageKind.INVALID_INITIALIZER);
903 }
904 }
905 if (!resolvedSuper) {
906 resolveImplicitSuperConstructorSend(constructor, functionNode);
907 }
908 return null; // If there was no redirection always return null.
909 }
910 }
911
912 class CommonResolverVisitor<R> extends Visitor<R> {
913 final Compiler compiler;
914
915 CommonResolverVisitor(Compiler this.compiler);
916
917 R visitNode(Node node) {
918 cancel(node,
919 'internal error: Unhandled node: ${node.getObjectDescription()}');
920 }
921
922 R visitEmptyStatement(Node node) => null;
923
924 /** Convenience method for visiting nodes that may be null. */
925 R visit(Node node) => (node == null) ? null : node.accept(this);
926
927 void error(Node node, MessageKind kind, [arguments = const []]) {
928 ResolutionError message = new ResolutionError(kind, arguments);
929 compiler.reportError(node, message);
930 }
931
932 void warning(Node node, MessageKind kind, [arguments = const []]) {
933 ResolutionWarning message = new ResolutionWarning(kind, arguments);
934 compiler.reportWarning(node, message);
935 }
936
937 void cancel(Node node, String message) {
938 compiler.cancel(message, node: node);
939 }
940
941 void internalError(Node node, String message) {
942 compiler.internalError(message, node: node);
943 }
944
945 void unimplemented(Node node, String message) {
946 compiler.unimplemented(message, node: node);
947 }
948 }
949
950 abstract class LabelScope {
951 LabelScope get outer;
952 LabelElement lookup(String label);
953 }
954
955 class LabeledStatementLabelScope implements LabelScope {
956 final LabelScope outer;
957 final Map<String, LabelElement> labels;
958 LabeledStatementLabelScope(this.outer, this.labels);
959 LabelElement lookup(String labelName) {
960 LabelElement label = labels[labelName];
961 if (label != null) return label;
962 return outer.lookup(labelName);
963 }
964 }
965
966 class SwitchLabelScope implements LabelScope {
967 final LabelScope outer;
968 final Map<String, LabelElement> caseLabels;
969
970 SwitchLabelScope(this.outer, this.caseLabels);
971
972 LabelElement lookup(String labelName) {
973 LabelElement result = caseLabels[labelName];
974 if (result != null) return result;
975 return outer.lookup(labelName);
976 }
977 }
978
979 class EmptyLabelScope implements LabelScope {
980 const EmptyLabelScope();
981 LabelElement lookup(String label) => null;
982 LabelScope get outer {
983 throw 'internal error: empty label scope has no outer';
984 }
985 }
986
987 class StatementScope {
988 LabelScope labels;
989 Link<TargetElement> breakTargetStack;
990 Link<TargetElement> continueTargetStack;
991 // Used to provide different numbers to statements if one is inside the other.
992 // Can be used to make otherwise duplicate labels unique.
993 int nestingLevel = 0;
994
995 StatementScope()
996 : labels = const EmptyLabelScope(),
997 breakTargetStack = const Link<TargetElement>(),
998 continueTargetStack = const Link<TargetElement>();
999
1000 LabelElement lookupLabel(String label) {
1001 return labels.lookup(label);
1002 }
1003
1004 TargetElement currentBreakTarget() =>
1005 breakTargetStack.isEmpty() ? null : breakTargetStack.head;
1006
1007 TargetElement currentContinueTarget() =>
1008 continueTargetStack.isEmpty() ? null : continueTargetStack.head;
1009
1010 void enterLabelScope(Map<String, LabelElement> elements) {
1011 labels = new LabeledStatementLabelScope(labels, elements);
1012 nestingLevel++;
1013 }
1014
1015 void exitLabelScope() {
1016 nestingLevel--;
1017 labels = labels.outer;
1018 }
1019
1020 void enterLoop(TargetElement element) {
1021 breakTargetStack = breakTargetStack.prepend(element);
1022 continueTargetStack = continueTargetStack.prepend(element);
1023 nestingLevel++;
1024 }
1025
1026 void exitLoop() {
1027 nestingLevel--;
1028 breakTargetStack = breakTargetStack.tail;
1029 continueTargetStack = continueTargetStack.tail;
1030 }
1031
1032 void enterSwitch(TargetElement breakElement,
1033 Map<String, LabelElement> continueElements) {
1034 breakTargetStack = breakTargetStack.prepend(breakElement);
1035 labels = new SwitchLabelScope(labels, continueElements);
1036 nestingLevel++;
1037 }
1038
1039 void exitSwitch() {
1040 nestingLevel--;
1041 breakTargetStack = breakTargetStack.tail;
1042 labels = labels.outer;
1043 }
1044 }
1045
1046 class TypeResolver {
1047 final Compiler compiler;
1048
1049 TypeResolver(this.compiler);
1050
1051 Element resolveTypeName(Scope scope, TypeAnnotation node) {
1052 Identifier typeName = node.typeName.asIdentifier();
1053 Send send = node.typeName.asSend();
1054 return resolveTypeNameInternal(scope, typeName, send);
1055 }
1056
1057 Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) {
1058 if (send != null) {
1059 typeName = send.selector;
1060 }
1061 if (identical(typeName.source.stringValue, 'void')) {
1062 return compiler.types.voidType.element;
1063 } else if (
1064 // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support.
1065 identical(typeName.source.stringValue, 'Dynamic')
1066 || identical(typeName.source.stringValue, 'dynamic')) {
1067 return compiler.dynamicClass;
1068 } else if (send != null) {
1069 Element e = scope.lookup(send.receiver.asIdentifier().source);
1070 if (e != null && identical(e.kind, ElementKind.PREFIX)) {
1071 // The receiver is a prefix. Lookup in the imported members.
1072 PrefixElement prefix = e;
1073 return prefix.lookupLocalMember(typeName.source);
1074 } else if (e != null && identical(e.kind, ElementKind.CLASS)) {
1075 // The receiver is the class part of a named constructor.
1076 return e;
1077 } else {
1078 return null;
1079 }
1080 } else {
1081 return scope.lookup(typeName.source);
1082 }
1083 }
1084
1085 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean
1086 // flags instead of closures.
1087 // TODO(johnniwinther): Should never return [null] but instead an erroneous
1088 // type.
1089 DartType resolveTypeAnnotation(TypeAnnotation node,
1090 {Scope inScope, ClassElement inClass,
1091 onFailure(Node, MessageKind, [List arguments]),
1092 whenResolved(Node, Type)}) {
1093 if (onFailure == null) {
1094 onFailure = (n, k, [arguments]) {};
1095 }
1096 if (whenResolved == null) {
1097 whenResolved = (n, t) {};
1098 }
1099 if (inClass != null) {
1100 inScope = inClass.buildScope();
1101 }
1102 if (inScope == null) {
1103 compiler.internalError('resolveTypeAnnotation: no scope specified');
1104 }
1105 return resolveTypeAnnotationInContext(inScope, node, onFailure,
1106 whenResolved);
1107 }
1108
1109 DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node,
1110 onFailure, whenResolved) {
1111 Element element = resolveTypeName(scope, node);
1112 DartType type;
1113 if (element == null) {
1114 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
1115 } else if (element.isErroneous()) {
1116 ErroneousElement error = element;
1117 onFailure(node, error.messageKind, error.messageArguments);
1118 } else if (!element.impliesType()) {
1119 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]);
1120 } else {
1121 if (identical(element, compiler.types.voidType.element) ||
1122 identical(element, compiler.types.dynamicType.element)) {
1123 type = element.computeType(compiler);
1124 } else if (element.isClass()) {
1125 ClassElement cls = element;
1126 cls.ensureResolved(compiler);
1127 Link<DartType> arguments =
1128 resolveTypeArguments(node, cls.typeVariables, scope,
1129 onFailure, whenResolved);
1130 if (cls.typeVariables.isEmpty() && arguments.isEmpty()) {
1131 // Use the canonical type if it has no type parameters.
1132 type = cls.computeType(compiler);
1133 } else {
1134 type = new InterfaceType(cls, arguments);
1135 }
1136 } else if (element.isTypedef()) {
1137 TypedefElement typdef = element;
1138 // TODO(ahe): Should be [ensureResolved].
1139 compiler.resolveTypedef(typdef);
1140 typdef.computeType(compiler);
1141 Link<DartType> arguments = resolveTypeArguments(
1142 node, typdef.typeVariables,
1143 scope, onFailure, whenResolved);
1144 if (typdef.typeVariables.isEmpty() && arguments.isEmpty()) {
1145 // Return the canonical type if it has no type parameters.
1146 type = typdef.computeType(compiler);
1147 } else {
1148 type = new TypedefType(typdef, arguments);
1149 }
1150 } else if (element.isTypeVariable()) {
1151 type = element.computeType(compiler);
1152 } else {
1153 compiler.cancel("unexpected element kind ${element.kind}",
1154 node: node);
1155 }
1156 }
1157 whenResolved(node, type);
1158 return type;
1159 }
1160
1161 Link<DartType> resolveTypeArguments(TypeAnnotation node,
1162 Link<DartType> typeVariables,
1163 Scope scope, onFailure, whenResolved) {
1164 if (node.typeArguments == null) {
1165 return const Link<DartType>();
1166 }
1167 var arguments = new LinkBuilder<DartType>();
1168 for (Link<Node> typeArguments = node.typeArguments.nodes;
1169 !typeArguments.isEmpty();
1170 typeArguments = typeArguments.tail) {
1171 if (typeVariables.isEmpty()) {
1172 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
1173 }
1174 DartType argType = resolveTypeAnnotationInContext(scope,
1175 typeArguments.head,
1176 onFailure,
1177 whenResolved);
1178 arguments.addLast(argType);
1179 if (!typeVariables.isEmpty()) {
1180 typeVariables = typeVariables.tail;
1181 }
1182 }
1183 if (!typeVariables.isEmpty()) {
1184 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
1185 }
1186 return arguments.toLink();
1187 }
1188 }
1189
1190 class ResolverVisitor extends CommonResolverVisitor<Element> {
1191 final TreeElementMapping mapping;
1192 Element enclosingElement;
1193 final TypeResolver typeResolver;
1194 bool inInstanceContext;
1195 bool inCheckContext;
1196 bool inCatchBlock;
1197 Scope scope;
1198 ClassElement currentClass;
1199 ExpressionStatement currentExpressionStatement;
1200 bool typeRequired = false;
1201 StatementScope statementScope;
1202 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION;
1203
1204 ResolverVisitor(Compiler compiler, Element element)
1205 : this.mapping = new TreeElementMapping(element),
1206 this.enclosingElement = element,
1207 // When the element is a field, we are actually resolving its
1208 // initial value, which should not have access to instance
1209 // fields.
1210 inInstanceContext = (element.isInstanceMember() && !element.isField())
1211 || element.isGenerativeConstructor(),
1212 this.currentClass = element.isMember() ? element.getEnclosingClass()
1213 : null,
1214 this.statementScope = new StatementScope(),
1215 typeResolver = new TypeResolver(compiler),
1216 scope = element.buildScope(),
1217 inCheckContext = compiler.enableTypeAssertions,
1218 inCatchBlock = false,
1219 super(compiler);
1220
1221 Enqueuer get world => compiler.enqueuer.resolution;
1222
1223 Element lookup(Node node, SourceString name) {
1224 Element result = scope.lookup(name);
1225 if (!inInstanceContext && result != null && result.isInstanceMember()) {
1226 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
1227 }
1228 return result;
1229 }
1230
1231 // Create, or reuse an already created, statement element for a statement.
1232 TargetElement getOrCreateTargetElement(Node statement) {
1233 TargetElement element = mapping[statement];
1234 if (element == null) {
1235 element = new TargetElement(statement,
1236 statementScope.nestingLevel,
1237 enclosingElement);
1238 mapping[statement] = element;
1239 }
1240 return element;
1241 }
1242
1243 doInCheckContext(action()) {
1244 bool wasInCheckContext = inCheckContext;
1245 inCheckContext = true;
1246 var result = action();
1247 inCheckContext = wasInCheckContext;
1248 return result;
1249 }
1250
1251 inStaticContext(action()) {
1252 bool wasInstanceContext = inInstanceContext;
1253 inInstanceContext = false;
1254 var result = action();
1255 inInstanceContext = wasInstanceContext;
1256 return result;
1257 }
1258
1259 visitInStaticContext(Node node) {
1260 inStaticContext(() => visit(node));
1261 }
1262
1263 ErroneousElement warnAndCreateErroneousElement(Node node,
1264 SourceString name,
1265 MessageKind kind,
1266 List<Node> arguments) {
1267 return warnOnErroneousElement(node,
1268 new ErroneousElement(kind, arguments, name, enclosingElement));
1269 }
1270
1271 ErroneousElement warnOnErroneousElement(Node node,
1272 ErroneousElement erroneousElement) {
1273 ResolutionWarning warning =
1274 new ResolutionWarning(erroneousElement.messageKind,
1275 erroneousElement.messageArguments);
1276 compiler.reportWarning(node, warning);
1277 return erroneousElement;
1278 }
1279
1280 Element visitIdentifier(Identifier node) {
1281 if (node.isThis()) {
1282 if (!inInstanceContext) {
1283 error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
1284 }
1285 return null;
1286 } else if (node.isSuper()) {
1287 if (!inInstanceContext) error(node, MessageKind.NO_SUPER_IN_STATIC);
1288 if ((ElementCategory.SUPER & allowedCategory) == 0) {
1289 error(node, MessageKind.INVALID_USE_OF_SUPER);
1290 }
1291 return null;
1292 } else {
1293 Element element = lookup(node, node.source);
1294 if (element == null) {
1295 if (!inInstanceContext) {
1296 element = warnAndCreateErroneousElement(node, node.source,
1297 MessageKind.CANNOT_RESOLVE,
1298 [node]);
1299 }
1300 } else if (element.isErroneous()) {
1301 element = warnOnErroneousElement(node, element);
1302 } else {
1303 if ((element.kind.category & allowedCategory) == 0) {
1304 // TODO(ahe): Improve error message. Need UX input.
1305 error(node, MessageKind.GENERIC, ["is not an expression $element"]);
1306 }
1307 }
1308 return useElement(node, element);
1309 }
1310 }
1311
1312 Element visitTypeAnnotation(TypeAnnotation node) {
1313 DartType type = resolveTypeAnnotation(node);
1314 if (type != null) {
1315 if (inCheckContext) {
1316 compiler.enqueuer.resolution.registerIsCheck(type);
1317 }
1318 return type.element;
1319 }
1320 return null;
1321 }
1322
1323 Element defineElement(Node node, Element element,
1324 {bool doAddToScope: true}) {
1325 compiler.ensure(element != null);
1326 mapping[node] = element;
1327 if (doAddToScope) {
1328 Element existing = scope.add(element);
1329 if (existing != element) {
1330 error(node, MessageKind.DUPLICATE_DEFINITION, [node]);
1331 }
1332 }
1333 return element;
1334 }
1335
1336 Element useElement(Node node, Element element) {
1337 if (element == null) return null;
1338 return mapping[node] = element;
1339 }
1340
1341 DartType useType(TypeAnnotation annotation, DartType type) {
1342 if (type != null) {
1343 mapping.setType(annotation, type);
1344 useElement(annotation, type.element);
1345 }
1346 return type;
1347 }
1348
1349 void setupFunction(FunctionExpression node, FunctionElement function) {
1350 // If [function] is the [enclosingElement], the [scope] has
1351 // already been set in the constructor of [ResolverVisitor].
1352 if (function != enclosingElement) scope = new MethodScope(scope, function);
1353
1354 // Put the parameters in scope.
1355 FunctionSignature functionParameters =
1356 function.computeSignature(compiler);
1357 Link<Node> parameterNodes = (node.parameters == null)
1358 ? const Link<Node>() : node.parameters.nodes;
1359 functionParameters.forEachParameter((Element element) {
1360 if (element == functionParameters.optionalParameters.head) {
1361 NodeList nodes = parameterNodes.head;
1362 parameterNodes = nodes.nodes;
1363 }
1364 VariableDefinitions variableDefinitions = parameterNodes.head;
1365 Node parameterNode = variableDefinitions.definitions.nodes.head;
1366 initializerDo(parameterNode, (n) => n.accept(this));
1367 // Field parameters (this.x) are not visible inside the constructor. The
1368 // fields they reference are visible, but must be resolved independently.
1369 if (element.kind == ElementKind.FIELD_PARAMETER) {
1370 useElement(parameterNode, element);
1371 } else {
1372 defineElement(variableDefinitions.definitions.nodes.head, element);
1373 }
1374 parameterNodes = parameterNodes.tail;
1375 });
1376 }
1377
1378 visitCascade(Cascade node) {
1379 visit(node.expression);
1380 }
1381
1382 visitCascadeReceiver(CascadeReceiver node) {
1383 visit(node.expression);
1384 }
1385
1386 Element visitClassNode(ClassNode node) {
1387 cancel(node, "shouldn't be called");
1388 }
1389
1390 visitIn(Node node, Scope nestedScope) {
1391 scope = nestedScope;
1392 Element element = visit(node);
1393 scope = scope.parent;
1394 return element;
1395 }
1396
1397 /**
1398 * Introduces new default targets for break and continue
1399 * before visiting the body of the loop
1400 */
1401 visitLoopBodyIn(Node loop, Node body, Scope bodyScope) {
1402 TargetElement element = getOrCreateTargetElement(loop);
1403 statementScope.enterLoop(element);
1404 visitIn(body, bodyScope);
1405 statementScope.exitLoop();
1406 if (!element.isTarget) {
1407 mapping.remove(loop);
1408 }
1409 }
1410
1411 visitBlock(Block node) {
1412 visitIn(node.statements, new BlockScope(scope));
1413 }
1414
1415 visitDoWhile(DoWhile node) {
1416 visitLoopBodyIn(node, node.body, new BlockScope(scope));
1417 visit(node.condition);
1418 }
1419
1420 visitEmptyStatement(EmptyStatement node) { }
1421
1422 visitExpressionStatement(ExpressionStatement node) {
1423 ExpressionStatement oldExpressionStatement = currentExpressionStatement;
1424 currentExpressionStatement = node;
1425 visit(node.expression);
1426 currentExpressionStatement = oldExpressionStatement;
1427 }
1428
1429 visitFor(For node) {
1430 Scope blockScope = new BlockScope(scope);
1431 visitIn(node.initializer, blockScope);
1432 visitIn(node.condition, blockScope);
1433 visitIn(node.update, blockScope);
1434 visitLoopBodyIn(node, node.body, blockScope);
1435 }
1436
1437 visitFunctionDeclaration(FunctionDeclaration node) {
1438 assert(node.function.name != null);
1439 visit(node.function);
1440 FunctionElement functionElement = mapping[node.function];
1441 // TODO(floitsch): this might lead to two errors complaining about
1442 // shadowing.
1443 defineElement(node, functionElement);
1444 }
1445
1446 visitFunctionExpression(FunctionExpression node) {
1447 visit(node.returnType);
1448 SourceString name;
1449 if (node.name == null) {
1450 name = const SourceString("");
1451 } else {
1452 name = node.name.asIdentifier().source;
1453 }
1454
1455 FunctionElement function = new FunctionElement.node(
1456 name, node, ElementKind.FUNCTION, Modifiers.EMPTY,
1457 enclosingElement);
1458 setupFunction(node, function);
1459 defineElement(node, function, doAddToScope: node.name !== null);
1460
1461 Element previousEnclosingElement = enclosingElement;
1462 enclosingElement = function;
1463 // Run the body in a fresh statement scope.
1464 StatementScope oldScope = statementScope;
1465 statementScope = new StatementScope();
1466 visit(node.body);
1467 statementScope = oldScope;
1468
1469 scope = scope.parent;
1470 enclosingElement = previousEnclosingElement;
1471 }
1472
1473 visitIf(If node) {
1474 visit(node.condition);
1475 visit(node.thenPart);
1476 visit(node.elsePart);
1477 }
1478
1479 static bool isLogicalOperator(Identifier op) {
1480 String str = op.source.stringValue;
1481 return (identical(str, '&&') || str == '||' || str == '!');
1482 }
1483
1484 Element resolveSend(Send node) {
1485 Selector selector = resolveSelector(node);
1486
1487 if (node.receiver == null) {
1488 // If this send is of the form "assert(expr);", then
1489 // this is an assertion.
1490 if (selector.isAssert()) {
1491 if (selector.argumentCount != 1) {
1492 error(node.selector,
1493 MessageKind.WRONG_NUMBER_OF_ARGUMENTS_FOR_ASSERT,
1494 [selector.argumentCount]);
1495 } else if (selector.namedArgumentCount != 0) {
1496 error(node.selector,
1497 MessageKind.ASSERT_IS_GIVEN_NAMED_ARGUMENTS,
1498 [selector.namedArgumentCount]);
1499 }
1500 return compiler.assertMethod;
1501 }
1502 return node.selector.accept(this);
1503 }
1504
1505 var oldCategory = allowedCategory;
1506 allowedCategory |=
1507 ElementCategory.CLASS | ElementCategory.PREFIX | ElementCategory.SUPER;
1508 Element resolvedReceiver = visit(node.receiver);
1509 allowedCategory = oldCategory;
1510
1511 Element target;
1512 SourceString name = node.selector.asIdentifier().source;
1513 if (identical(name.stringValue, 'this')) {
1514 error(node.selector, MessageKind.GENERIC, ["expected an identifier"]);
1515 } else if (node.isSuperCall) {
1516 if (node.isOperator) {
1517 if (isUserDefinableOperator(name.stringValue)) {
1518 name = selector.name;
1519 } else {
1520 error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, [name]);
1521 }
1522 }
1523 if (!inInstanceContext) {
1524 error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, [name]);
1525 return null;
1526 }
1527 if (currentClass.supertype == null) {
1528 // This is just to guard against internal errors, so no need
1529 // for a real error message.
1530 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]);
1531 }
1532 // TODO(johnniwinther): Ensure correct behavior if currentClass is a
1533 // patch.
1534 target = currentClass.lookupSuperMember(name);
1535 // [target] may be null which means invoking noSuchMethod on
1536 // super.
1537 } else if (Elements.isUnresolved(resolvedReceiver)) {
1538 return null;
1539 } else if (identical(resolvedReceiver.kind, ElementKind.CLASS)) {
1540 ClassElement receiverClass = resolvedReceiver;
1541 receiverClass.ensureResolved(compiler);
1542 target = receiverClass.buildLocalScope().lookup(name);
1543 if (target == null) {
1544 // TODO(johnniwinther): With the simplified [TreeElements] invariant,
1545 // try to resolve injected elements if [currentClass] is in the patch
1546 // library of [receiverClass].
1547
1548 // TODO(karlklose): this should be reported by the caller of
1549 // [resolveSend] to select better warning messages for getters and
1550 // setters.
1551 return warnAndCreateErroneousElement(node, name,
1552 MessageKind.METHOD_NOT_FOUND,
1553 [receiverClass.name, name]);
1554 } else if (target.isInstanceMember()) {
1555 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]);
1556 }
1557 } else if (identical(resolvedReceiver.kind, ElementKind.PREFIX)) {
1558 PrefixElement prefix = resolvedReceiver;
1559 target = prefix.lookupLocalMember(name);
1560 if (target == null) {
1561 error(node, MessageKind.NO_SUCH_LIBRARY_MEMBER, [prefix.name, name]);
1562 }
1563 }
1564 return target;
1565 }
1566
1567 DartType resolveTypeTest(Node argument) {
1568 TypeAnnotation node = argument.asTypeAnnotation();
1569 if (node == null) {
1570 // node is of the form !Type.
1571 node = argument.asSend().receiver.asTypeAnnotation();
1572 if (node == null) compiler.cancel("malformed send");
1573 }
1574 return resolveTypeRequired(node);
1575 }
1576
1577 static Selector computeSendSelector(Send node, LibraryElement library) {
1578 // First determine if this is part of an assignment.
1579 bool isSet = node.asSendSet() != null;
1580
1581 if (node.isIndex) {
1582 return isSet ? new Selector.indexSet() : new Selector.index();
1583 }
1584
1585 if (node.isOperator) {
1586 SourceString source = node.selector.asOperator().source;
1587 String string = source.stringValue;
1588 if (identical(string, '!') || identical(string, '&&') || string == '||' ||
1589 identical(string, 'is') || identical(string, 'as') ||
1590 identical(string, '===') || identical(string, '!==') ||
1591 identical(string, '>>>')) {
1592 return null;
1593 }
1594 return node.arguments.isEmpty()
1595 ? new Selector.unaryOperator(source)
1596 : new Selector.binaryOperator(source);
1597 }
1598
1599 Identifier identifier = node.selector.asIdentifier();
1600 if (node.isPropertyAccess) {
1601 assert(!isSet);
1602 return new Selector.getter(identifier.source, library);
1603 } else if (isSet) {
1604 return new Selector.setter(identifier.source, library);
1605 }
1606
1607 // Compute the arity and the list of named arguments.
1608 int arity = 0;
1609 List<SourceString> named = <SourceString>[];
1610 for (Link<Node> link = node.argumentsNode.nodes;
1611 !link.isEmpty();
1612 link = link.tail) {
1613 Expression argument = link.head;
1614 NamedArgument namedArgument = argument.asNamedArgument();
1615 if (namedArgument != null) {
1616 named.add(namedArgument.name.source);
1617 }
1618 arity++;
1619 }
1620
1621 // If we're invoking a closure, we do not have an identifier.
1622 return (identifier == null)
1623 ? new Selector.callClosure(arity, named)
1624 : new Selector.call(identifier.source, library, arity, named);
1625 }
1626
1627 Selector resolveSelector(Send node) {
1628 LibraryElement library = enclosingElement.getLibrary();
1629 Selector selector = computeSendSelector(node, library);
1630 if (selector != null) mapping.setSelector(node, selector);
1631 return selector;
1632 }
1633
1634 void resolveArguments(NodeList list) {
1635 if (list == null) return;
1636 bool seenNamedArgument = false;
1637 for (Link<Node> link = list.nodes; !link.isEmpty(); link = link.tail) {
1638 Expression argument = link.head;
1639 visit(argument);
1640 if (argument.asNamedArgument() != null) {
1641 seenNamedArgument = true;
1642 } else if (seenNamedArgument) {
1643 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED);
1644 }
1645 }
1646 }
1647
1648 visitSend(Send node) {
1649 Element target = resolveSend(node);
1650 if (!Elements.isUnresolved(target)
1651 && target.kind == ElementKind.ABSTRACT_FIELD) {
1652 AbstractFieldElement field = target;
1653 target = field.getter;
1654 if (target == null && !inInstanceContext) {
1655 target =
1656 warnAndCreateErroneousElement(node.selector, field.name,
1657 MessageKind.CANNOT_RESOLVE_GETTER,
1658 [node.selector]);
1659 }
1660 }
1661
1662 bool resolvedArguments = false;
1663 if (node.isOperator) {
1664 String operatorString = node.selector.asOperator().source.stringValue;
1665 if (identical(operatorString, 'is') || identical(operatorString, 'as')) {
1666 assert(node.arguments.tail.isEmpty());
1667 DartType type = resolveTypeTest(node.arguments.head);
1668 if (type != null) {
1669 compiler.enqueuer.resolution.registerIsCheck(type);
1670 }
1671 resolvedArguments = true;
1672 } else if (identical(operatorString, '?')) {
1673 Element parameter = mapping[node.receiver];
1674 if (parameter == null
1675 || !identical(parameter.kind, ElementKind.PARAMETER)) {
1676 error(node.receiver, MessageKind.PARAMETER_NAME_EXPECTED);
1677 } else {
1678 mapping.checkedParameters.add(parameter);
1679 }
1680 }
1681 }
1682
1683 if (!resolvedArguments) {
1684 resolveArguments(node.argumentsNode);
1685 }
1686
1687 // If the selector is null, it means that we will not be generating
1688 // code for this as a send.
1689 Selector selector = mapping.getSelector(node);
1690 if (selector == null) return;
1691
1692 // If we don't know what we're calling or if we are calling a getter,
1693 // we need to register that fact that we may be calling a closure
1694 // with the same arguments.
1695 if (node.isCall &&
1696 (Elements.isUnresolved(target) ||
1697 target.isGetter() ||
1698 Elements.isClosureSend(node, target))) {
1699 Selector call = new Selector.callClosureFrom(selector);
1700 world.registerDynamicInvocation(call.name, call);
1701 }
1702
1703 // TODO(ngeoffray): Warn if target is null and the send is
1704 // unqualified.
1705 useElement(node, target);
1706 registerSend(selector, target);
1707 return node.isPropertyAccess ? target : null;
1708 }
1709
1710 visitSendSet(SendSet node) {
1711 Element target = resolveSend(node);
1712 Element setter = target;
1713 Element getter = target;
1714 SourceString operatorName = node.assignmentOperator.source;
1715 String source = operatorName.stringValue;
1716 bool isComplex = !identical(source, '=');
1717 if (!Elements.isUnresolved(target)
1718 && target.kind == ElementKind.ABSTRACT_FIELD) {
1719 AbstractFieldElement field = target;
1720 setter = field.setter;
1721 getter = field.getter;
1722 if (setter == null && !inInstanceContext) {
1723 setter =
1724 warnAndCreateErroneousElement(node.selector, field.name,
1725 MessageKind.CANNOT_RESOLVE_SETTER,
1726 [node.selector]);
1727 }
1728 if (isComplex && getter == null && !inInstanceContext) {
1729 getter =
1730 warnAndCreateErroneousElement(node.selector, field.name,
1731 MessageKind.CANNOT_RESOLVE_GETTER,
1732 [node.selector]);
1733 }
1734 }
1735
1736 visit(node.argumentsNode);
1737
1738 // TODO(ngeoffray): Check if the target can be assigned.
1739 // TODO(ngeoffray): Warn if target is null and the send is
1740 // unqualified.
1741
1742 Selector selector = mapping.getSelector(node);
1743 if (isComplex) {
1744 if (selector.isSetter()) {
1745 // TODO(kasperl): We're registering the getter selector for
1746 // compound assignments on the AST selector node. In the code
1747 // generator, we then fetch it from there when generating the
1748 // getter for a SendSet node.
1749 Selector getterSelector = new Selector.getterFrom(selector);
1750 registerSend(getterSelector, getter);
1751 mapping.setSelector(node.selector, getterSelector);
1752 useElement(node.selector, getter);
1753 } else {
1754 // TODO(kasperl): If [getter] is resolved, it will actually
1755 // refer to the []= operator which isn't the one we want to
1756 // register here. We should consider using some notion of
1757 // abstract indexable element that we can resolve to so we can
1758 // distinguish the two.
1759 assert(selector.isIndexSet());
1760 registerSend(new Selector.index(), null);
1761 }
1762
1763 // Make sure we include the + and - operators if we are using
1764 // the ++ and -- ones. Also, if op= form is used, include op itself.
1765 void registerBinaryOperator(SourceString name) {
1766 Selector binop = new Selector.binaryOperator(name);
1767 world.registerDynamicInvocation(binop.name, binop);
1768 }
1769 if (identical(source, '++')) registerBinaryOperator(const SourceString('+' ));
1770 if (identical(source, '--')) registerBinaryOperator(const SourceString('-' ));
1771 if (source.endsWith('=')) {
1772 registerBinaryOperator(Elements.mapToUserOperator(operatorName));
1773 }
1774 }
1775
1776 registerSend(selector, setter);
1777 return useElement(node, setter);
1778 }
1779
1780 void registerSend(Selector selector, Element target) {
1781 if (target == null || target.isInstanceMember()) {
1782 if (selector.isGetter()) {
1783 world.registerDynamicGetter(selector.name, selector);
1784 } else if (selector.isSetter()) {
1785 world.registerDynamicSetter(selector.name, selector);
1786 } else {
1787 world.registerDynamicInvocation(selector.name, selector);
1788 }
1789 } else if (Elements.isStaticOrTopLevel(target)) {
1790 // TODO(kasperl): It seems like we're not supposed to register
1791 // the use of classes. Wouldn't it be simpler if we just did?
1792 if (!target.isClass()) {
1793 // [target] might be the implementation element and only declaration
1794 // elements may be registered.
1795 world.registerStaticUse(target.declaration);
1796 }
1797 }
1798 if (target == null) {
1799 // If we haven't found an element for this send, it might be a
1800 // dynamic send on a primitive value. Register the selector with
1801 // the world to add an interceptor, if necessary.
1802 world.registerUsedSelector(selector);
1803 }
1804 }
1805
1806 visitLiteralInt(LiteralInt node) {
1807 }
1808
1809 visitLiteralDouble(LiteralDouble node) {
1810 }
1811
1812 visitLiteralBool(LiteralBool node) {
1813 }
1814
1815 visitLiteralString(LiteralString node) {
1816 }
1817
1818 visitLiteralNull(LiteralNull node) {
1819 }
1820
1821 visitStringJuxtaposition(StringJuxtaposition node) {
1822 node.visitChildren(this);
1823 }
1824
1825 visitNodeList(NodeList node) {
1826 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
1827 visit(link.head);
1828 }
1829 }
1830
1831 visitOperator(Operator node) {
1832 unimplemented(node, 'operator');
1833 }
1834
1835 visitReturn(Return node) {
1836 if (node.isRedirectingConstructorBody) {
1837 unimplemented(node, 'redirecting constructors');
1838 }
1839 visit(node.expression);
1840 }
1841
1842 visitThrow(Throw node) {
1843 if (!inCatchBlock && node.expression == null) {
1844 error(node, MessageKind.THROW_WITHOUT_EXPRESSION);
1845 }
1846 visit(node.expression);
1847 }
1848
1849 visitVariableDefinitions(VariableDefinitions node) {
1850 visit(node.type);
1851 VariableDefinitionsVisitor visitor =
1852 new VariableDefinitionsVisitor(compiler, node, this,
1853 ElementKind.VARIABLE);
1854 visitor.visit(node.definitions);
1855 }
1856
1857 visitWhile(While node) {
1858 visit(node.condition);
1859 visitLoopBodyIn(node, node.body, new BlockScope(scope));
1860 }
1861
1862 visitParenthesizedExpression(ParenthesizedExpression node) {
1863 visit(node.expression);
1864 }
1865
1866 visitNewExpression(NewExpression node) {
1867 Node selector = node.send.selector;
1868 FunctionElement constructor = resolveConstructor(node);
1869 resolveSelector(node.send);
1870 resolveArguments(node.send.argumentsNode);
1871 useElement(node.send, constructor);
1872 if (Elements.isUnresolved(constructor)) return constructor;
1873 // TODO(karlklose): handle optional arguments.
1874 if (node.send.argumentCount() != constructor.parameterCount(compiler)) {
1875 // TODO(ngeoffray): resolution error with wrong number of
1876 // parameters. We cannot do this rigth now because of the
1877 // List constructor.
1878 }
1879 // [constructor] might be the implementation element and only declaration
1880 // elements may be registered.
1881 world.registerStaticUse(constructor.declaration);
1882 compiler.withCurrentElement(constructor, () {
1883 FunctionExpression tree = constructor.parseNode(compiler);
1884 compiler.resolver.resolveConstructorImplementation(constructor, tree);
1885 });
1886 // [constructor.defaultImplementation] might be the implementation element
1887 // and only declaration elements may be registered.
1888 world.registerStaticUse(constructor.defaultImplementation.declaration);
1889 ClassElement cls = constructor.defaultImplementation.getEnclosingClass();
1890 // [cls] might be the implementation element and only declaration elements
1891 // may be registered.
1892 world.registerInstantiatedClass(cls.declaration);
1893 // [cls] might be the declaration element and we want to include injected
1894 // members.
1895 cls.implementation.forEachInstanceField(
1896 (ClassElement enclosingClass, Element member) {
1897 world.addToWorkList(member);
1898 },
1899 includeBackendMembers: false,
1900 includeSuperMembers: true);
1901 return null;
1902 }
1903
1904 /**
1905 * Try to resolve the constructor that is referred to by [node].
1906 * Note: this function may return an ErroneousFunctionElement instead of
1907 * [null], if there is no corresponding constructor, class or library.
1908 */
1909 FunctionElement resolveConstructor(NewExpression node) {
1910 // Resolve the constructor that [node] refers to.
1911 ConstructorResolver visitor =
1912 new ConstructorResolver(compiler, this, node.isConst());
1913 FunctionElement constructor = node.accept(visitor);
1914 // Try to resolve the type that the new-expression constructs.
1915 TypeAnnotation annotation = node.send.getTypeAnnotation();
1916 if (Elements.isUnresolved(constructor)) {
1917 // Resolve the type arguments. We cannot create a type and check the
1918 // number of type arguments for this annotation, because we do not know
1919 // the element.
1920 Link arguments = const Link<Node>();
1921 if (annotation.typeArguments != null) {
1922 arguments = annotation.typeArguments.nodes;
1923 }
1924 for (Node argument in arguments) {
1925 resolveTypeRequired(argument);
1926 }
1927 } else {
1928 // Resolve and store the type this annotation resolves to. The type
1929 // is used in the backend, e.g., for creating runtime type information.
1930 // TODO(karlklose): This will resolve the class element again. Refactor
1931 // so we can use the TypeResolver.
1932 resolveTypeRequired(annotation);
1933 }
1934 return constructor;
1935 }
1936
1937 DartType resolveTypeRequired(TypeAnnotation node) {
1938 bool old = typeRequired;
1939 typeRequired = true;
1940 DartType result = resolveTypeAnnotation(node);
1941 typeRequired = old;
1942 return result;
1943 }
1944
1945 void analyzeTypeArgument(DartType annotation, DartType argument) {
1946 if (argument == null) return;
1947 if (argument.element.isTypeVariable()) {
1948 // Register a dependency between the class where the type
1949 // variable is, and the annotation. If the annotation requires
1950 // runtime type information, then the class of the type variable
1951 // does too.
1952 compiler.world.registerRtiDependency(
1953 annotation.element,
1954 argument.element.enclosingElement);
1955 } else if (argument is InterfaceType) {
1956 InterfaceType type = argument;
1957 type.arguments.forEach((DartType argument) {
1958 analyzeTypeArgument(type, argument);
1959 });
1960 }
1961 }
1962
1963 DartType resolveTypeAnnotation(TypeAnnotation node) {
1964 Function report = typeRequired ? error : warning;
1965 DartType type = typeResolver.resolveTypeAnnotation(node, inScope: scope,
1966 onFailure: report,
1967 whenResolved: useType);
1968 if (type == null) return null;
1969 if (inCheckContext) {
1970 compiler.enqueuer.resolution.registerIsCheck(type);
1971 }
1972 if (typeRequired || inCheckContext) {
1973 if (type is InterfaceType) {
1974 InterfaceType itf = type;
1975 itf.arguments.forEach((DartType argument) {
1976 analyzeTypeArgument(type, argument);
1977 });
1978 }
1979 // TODO(ngeoffray): Also handle cases like:
1980 // 1) a is T
1981 // 2) T a (in checked mode).
1982 }
1983 return type;
1984 }
1985
1986 visitModifiers(Modifiers node) {
1987 // TODO(ngeoffray): Implement this.
1988 unimplemented(node, 'modifiers');
1989 }
1990
1991 visitLiteralList(LiteralList node) {
1992 NodeList arguments = node.typeArguments;
1993 if (arguments != null) {
1994 Link<Node> nodes = arguments.nodes;
1995 if (nodes.isEmpty()) {
1996 error(arguments, MessageKind.MISSING_TYPE_ARGUMENT, []);
1997 } else {
1998 resolveTypeRequired(nodes.head);
1999 for (nodes = nodes.tail; !nodes.isEmpty(); nodes = nodes.tail) {
2000 error(nodes.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT, []);
2001 resolveTypeRequired(nodes.head);
2002 }
2003 }
2004 }
2005 visit(node.elements);
2006 }
2007
2008 visitConditional(Conditional node) {
2009 node.visitChildren(this);
2010 }
2011
2012 visitStringInterpolation(StringInterpolation node) {
2013 node.visitChildren(this);
2014 }
2015
2016 visitStringInterpolationPart(StringInterpolationPart node) {
2017 registerImplicitInvocation(const SourceString('toString'), 0);
2018 node.visitChildren(this);
2019 }
2020
2021 visitBreakStatement(BreakStatement node) {
2022 TargetElement target;
2023 if (node.target == null) {
2024 target = statementScope.currentBreakTarget();
2025 if (target == null) {
2026 error(node, MessageKind.NO_BREAK_TARGET);
2027 return;
2028 }
2029 target.isBreakTarget = true;
2030 } else {
2031 String labelName = node.target.source.slowToString();
2032 LabelElement label = statementScope.lookupLabel(labelName);
2033 if (label == null) {
2034 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]);
2035 return;
2036 }
2037 target = label.target;
2038 if (!target.statement.isValidBreakTarget()) {
2039 error(node.target, MessageKind.INVALID_BREAK, [labelName]);
2040 return;
2041 }
2042 label.setBreakTarget();
2043 mapping[node.target] = label;
2044 }
2045 mapping[node] = target;
2046 }
2047
2048 visitContinueStatement(ContinueStatement node) {
2049 TargetElement target;
2050 if (node.target == null) {
2051 target = statementScope.currentContinueTarget();
2052 if (target == null) {
2053 error(node, MessageKind.NO_CONTINUE_TARGET);
2054 return;
2055 }
2056 target.isContinueTarget = true;
2057 } else {
2058 String labelName = node.target.source.slowToString();
2059 LabelElement label = statementScope.lookupLabel(labelName);
2060 if (label == null) {
2061 error(node.target, MessageKind.UNBOUND_LABEL, [labelName]);
2062 return;
2063 }
2064 target = label.target;
2065 if (!target.statement.isValidContinueTarget()) {
2066 error(node.target, MessageKind.INVALID_CONTINUE, [labelName]);
2067 }
2068 // TODO(lrn): Handle continues to switch cases.
2069 if (target.statement is SwitchCase) {
2070 unimplemented(node, "continue to switch case");
2071 }
2072 label.setContinueTarget();
2073 mapping[node.target] = label;
2074 }
2075 mapping[node] = target;
2076 }
2077
2078 registerImplicitInvocation(SourceString name, int arity) {
2079 Selector selector = new Selector.call(name, null, arity);
2080 world.registerDynamicInvocation(name, selector);
2081 }
2082
2083 visitForIn(ForIn node) {
2084 for (final name in const [
2085 const SourceString('iterator'),
2086 const SourceString('next'),
2087 const SourceString('hasNext')]) {
2088 registerImplicitInvocation(name, 0);
2089 }
2090 visit(node.expression);
2091 Scope blockScope = new BlockScope(scope);
2092 Node declaration = node.declaredIdentifier;
2093 visitIn(declaration, blockScope);
2094 visitLoopBodyIn(node, node.body, blockScope);
2095
2096 // TODO(lrn): Also allow a single identifier.
2097 if ((declaration is !Send || declaration.asSend().selector is !Identifier
2098 || declaration.asSend().receiver != null)
2099 && (declaration is !VariableDefinitions ||
2100 !declaration.asVariableDefinitions().definitions.nodes.tail.isEmpty()))
2101 {
2102 // The variable declaration is either not an identifier, not a
2103 // declaration, or it's declaring more than one variable.
2104 error(node.declaredIdentifier, MessageKind.INVALID_FOR_IN, []);
2105 }
2106 }
2107
2108 visitLabel(Label node) {
2109 // Labels are handled by their containing statements/cases.
2110 }
2111
2112 visitLabeledStatement(LabeledStatement node) {
2113 Statement body = node.statement;
2114 TargetElement targetElement = getOrCreateTargetElement(body);
2115 Map<String, LabelElement> labelElements = <String, LabelElement>{};
2116 for (Label label in node.labels) {
2117 String labelName = label.slowToString();
2118 if (labelElements.containsKey(labelName)) continue;
2119 LabelElement element = targetElement.addLabel(label, labelName);
2120 labelElements[labelName] = element;
2121 }
2122 statementScope.enterLabelScope(labelElements);
2123 visit(node.statement);
2124 statementScope.exitLabelScope();
2125 labelElements.forEach((String labelName, LabelElement element) {
2126 if (element.isTarget) {
2127 mapping[element.label] = element;
2128 } else {
2129 warning(element.label, MessageKind.UNUSED_LABEL, [labelName]);
2130 }
2131 });
2132 if (!targetElement.isTarget && identical(mapping[body], targetElement)) {
2133 // If the body is itself a break or continue for another target, it
2134 // might have updated its mapping to the target it actually does target.
2135 mapping.remove(body);
2136 }
2137 }
2138
2139 visitLiteralMap(LiteralMap node) {
2140 node.visitChildren(this);
2141 }
2142
2143 visitLiteralMapEntry(LiteralMapEntry node) {
2144 node.visitChildren(this);
2145 }
2146
2147 visitNamedArgument(NamedArgument node) {
2148 visit(node.expression);
2149 }
2150
2151 visitSwitchStatement(SwitchStatement node) {
2152 node.expression.accept(this);
2153
2154 TargetElement breakElement = getOrCreateTargetElement(node);
2155 Map<String, LabelElement> continueLabels = <String, LabelElement>{};
2156 Link<Node> cases = node.cases.nodes;
2157 while (!cases.isEmpty()) {
2158 SwitchCase switchCase = cases.head;
2159 for (Node labelOrCase in switchCase.labelsAndCases) {
2160 if (labelOrCase is! Label) continue;
2161 Label label = labelOrCase;
2162 String labelName = label.slowToString();
2163
2164 LabelElement existingElement = continueLabels[labelName];
2165 if (existingElement != null) {
2166 // It's an error if the same label occurs twice in the same switch.
2167 warning(label, MessageKind.DUPLICATE_LABEL, [labelName]);
2168 error(existingElement.label, MessageKind.EXISTING_LABEL, [labelName]);
2169 } else {
2170 // It's only a warning if it shadows another label.
2171 existingElement = statementScope.lookupLabel(labelName);
2172 if (existingElement != null) {
2173 warning(label, MessageKind.DUPLICATE_LABEL, [labelName]);
2174 warning(existingElement.label,
2175 MessageKind.EXISTING_LABEL, [labelName]);
2176 }
2177 }
2178
2179 TargetElement targetElement =
2180 new TargetElement(switchCase,
2181 statementScope.nestingLevel,
2182 enclosingElement);
2183 mapping[switchCase] = targetElement;
2184
2185 LabelElement labelElement =
2186 new LabelElement(label, labelName,
2187 targetElement, enclosingElement);
2188 mapping[label] = labelElement;
2189 continueLabels[labelName] = labelElement;
2190 }
2191 cases = cases.tail;
2192 // Test that only the last case, if any, is a default case.
2193 if (switchCase.defaultKeyword != null && !cases.isEmpty()) {
2194 error(switchCase, MessageKind.INVALID_CASE_DEFAULT);
2195 }
2196 }
2197
2198 statementScope.enterSwitch(breakElement, continueLabels);
2199 node.cases.accept(this);
2200 statementScope.exitSwitch();
2201
2202 // Clean-up unused labels.
2203 continueLabels.forEach((String key, LabelElement label) {
2204 if (!label.isContinueTarget) {
2205 TargetElement targetElement = label.target;
2206 SwitchCase switchCase = targetElement.statement;
2207 mapping.remove(switchCase);
2208 mapping.remove(label.label);
2209 }
2210 });
2211 }
2212
2213 visitSwitchCase(SwitchCase node) {
2214 node.labelsAndCases.accept(this);
2215 visitIn(node.statements, new BlockScope(scope));
2216 }
2217
2218 visitCaseMatch(CaseMatch node) {
2219 visit(node.expression);
2220 }
2221
2222 visitTryStatement(TryStatement node) {
2223 visit(node.tryBlock);
2224 if (node.catchBlocks.isEmpty() && node.finallyBlock == null) {
2225 // TODO(ngeoffray): The precise location is
2226 // node.getEndtoken.next. Adjust when issue #1581 is fixed.
2227 error(node, MessageKind.NO_CATCH_NOR_FINALLY);
2228 }
2229 visit(node.catchBlocks);
2230 visit(node.finallyBlock);
2231 }
2232
2233 visitCatchBlock(CatchBlock node) {
2234 // Check that if catch part is present, then
2235 // it has one or two formal parameters.
2236 if (node.formals != null) {
2237 if (node.formals.isEmpty()) {
2238 error(node, MessageKind.EMPTY_CATCH_DECLARATION);
2239 }
2240 if (!node.formals.nodes.tail.isEmpty() &&
2241 !node.formals.nodes.tail.tail.isEmpty()) {
2242 for (Node extra in node.formals.nodes.tail.tail) {
2243 error(extra, MessageKind.EXTRA_CATCH_DECLARATION);
2244 }
2245 }
2246
2247 // Check that the formals aren't optional and that they have no
2248 // modifiers or type.
2249 for (Link<Node> link = node.formals.nodes;
2250 !link.isEmpty();
2251 link = link.tail) {
2252 // If the formal parameter is a node list, it means that it is a
2253 // sequence of optional parameters.
2254 NodeList nodeList = link.head.asNodeList();
2255 if (nodeList != null) {
2256 error(nodeList, MessageKind.OPTIONAL_PARAMETER_IN_CATCH);
2257 } else {
2258 VariableDefinitions declaration = link.head;
2259 for (Node modifier in declaration.modifiers.nodes) {
2260 error(modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH);
2261 }
2262 TypeAnnotation type = declaration.type;
2263 if (type != null) {
2264 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH);
2265 }
2266 }
2267 }
2268 }
2269
2270 Scope blockScope = new BlockScope(scope);
2271 var wasTypeRequired = typeRequired;
2272 typeRequired = true;
2273 doInCheckContext(() => visitIn(node.type, blockScope));
2274 typeRequired = wasTypeRequired;
2275 visitIn(node.formals, blockScope);
2276 var oldInCatchBlock = inCatchBlock;
2277 inCatchBlock = true;
2278 visitIn(node.block, blockScope);
2279 inCatchBlock = oldInCatchBlock;
2280 }
2281
2282 visitTypedef(Typedef node) {
2283 unimplemented(node, 'typedef');
2284 }
2285 }
2286
2287 class TypeDefinitionVisitor extends CommonResolverVisitor<DartType> {
2288 Scope scope;
2289 TypeDeclarationElement element;
2290 TypeResolver typeResolver;
2291
2292 TypeDefinitionVisitor(Compiler compiler, TypeDeclarationElement element)
2293 : this.element = element,
2294 scope = element.buildEnclosingScope(),
2295 typeResolver = new TypeResolver(compiler),
2296 super(compiler);
2297
2298 void resolveTypeVariableBounds(NodeList node) {
2299 if (node == null) return;
2300
2301 var nameSet = new Set<SourceString>();
2302 // Resolve the bounds of type variables.
2303 Link<DartType> typeLink = element.typeVariables;
2304 Link<Node> nodeLink = node.nodes;
2305 while (!nodeLink.isEmpty()) {
2306 TypeVariableType typeVariable = typeLink.head;
2307 SourceString typeName = typeVariable.name;
2308 TypeVariable typeNode = nodeLink.head;
2309 if (nameSet.contains(typeName)) {
2310 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]);
2311 }
2312 nameSet.add(typeName);
2313
2314 TypeVariableElement variableElement = typeVariable.element;
2315 if (typeNode.bound != null) {
2316 DartType boundType = typeResolver.resolveTypeAnnotation(
2317 typeNode.bound, inScope: scope, onFailure: warning);
2318 if (boundType != null && boundType.element == variableElement) {
2319 // TODO(johnniwinther): Check for more general cycles, like
2320 // [: <A extends B, B extends C, C extends B> :].
2321 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE,
2322 [variableElement.name]);
2323 } else if (boundType != null) {
2324 variableElement.bound = boundType;
2325 } else {
2326 // TODO(johnniwinther): Should be an erroneous type.
2327 variableElement.bound = compiler.objectClass.computeType(compiler);
2328 }
2329 } else {
2330 variableElement.bound = compiler.objectClass.computeType(compiler);
2331 }
2332 nodeLink = nodeLink.tail;
2333 typeLink = typeLink.tail;
2334 }
2335 assert(typeLink.isEmpty());
2336 }
2337 }
2338
2339 class TypedefResolverVisitor extends TypeDefinitionVisitor {
2340 TypedefElement get element => super.element;
2341
2342 TypedefResolverVisitor(Compiler compiler, TypedefElement typedefElement)
2343 : super(compiler, typedefElement);
2344
2345 visitTypedef(Typedef node) {
2346 TypedefType type = element.computeType(compiler);
2347 scope = new TypeDeclarationScope(scope, element);
2348 resolveTypeVariableBounds(node.typeParameters);
2349
2350 element.functionSignature = SignatureResolver.analyze(
2351 compiler, node.formals, node.returnType, element);
2352
2353 element.alias = compiler.computeFunctionType(
2354 element, element.functionSignature);
2355
2356 // TODO(johnniwinther): Check for cyclic references in the typedef alias.
2357 }
2358 }
2359
2360 /**
2361 * The implementation of [ResolverTask.resolveClass].
2362 *
2363 * This visitor has to be extra careful as it is building the basic
2364 * element information, and cannot safely look at other elements as
2365 * this may lead to cycles.
2366 *
2367 * This visitor can assume that the supertypes have already been
2368 * resolved, but it cannot call [ResolverTask.resolveClass] directly
2369 * or indirectly (through [ClassElement.ensureResolved]) for any other
2370 * types.
2371 */
2372 class ClassResolverVisitor extends TypeDefinitionVisitor {
2373 ClassElement get element => super.element;
2374
2375 ClassResolverVisitor(Compiler compiler, ClassElement classElement)
2376 : super(compiler, classElement);
2377
2378 DartType visitClassNode(ClassNode node) {
2379 compiler.ensure(element != null);
2380 compiler.ensure(element.resolutionState == STATE_STARTED);
2381
2382 InterfaceType type = element.computeType(compiler);
2383 scope = new TypeDeclarationScope(scope, element);
2384 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet.
2385 // As a side-effect, this may get us back here trying to
2386 // resolve this class again.
2387 resolveTypeVariableBounds(node.typeParameters);
2388
2389 // Find super type.
2390 DartType supertype = visit(node.superclass);
2391 if (supertype != null && supertype.element.isExtendable()) {
2392 element.supertype = supertype;
2393 if (isBlackListed(supertype)) {
2394 error(node.superclass, MessageKind.CANNOT_EXTEND, [supertype]);
2395 }
2396 } else if (supertype != null) {
2397 error(node.superclass, MessageKind.TYPE_NAME_EXPECTED);
2398 }
2399 final objectElement = compiler.objectClass;
2400 if (!identical(element, objectElement) && element.supertype == null) {
2401 if (objectElement == null) {
2402 compiler.internalError("Internal error: cannot resolve Object",
2403 node: node);
2404 } else {
2405 objectElement.ensureResolved(compiler);
2406 }
2407 // TODO(ahe): This should be objectElement.computeType(...).
2408 element.supertype = new InterfaceType(objectElement);
2409 }
2410 assert(element.interfaces == null);
2411 Link<DartType> interfaces = const Link<DartType>();
2412 for (Link<Node> link = node.interfaces.nodes;
2413 !link.isEmpty();
2414 link = link.tail) {
2415 DartType interfaceType = visit(link.head);
2416 if (interfaceType != null && interfaceType.element.isExtendable()) {
2417 interfaces = interfaces.prepend(interfaceType);
2418 if (isBlackListed(interfaceType)) {
2419 error(link.head, MessageKind.CANNOT_IMPLEMENT, [interfaceType]);
2420 }
2421 } else {
2422 error(link.head, MessageKind.TYPE_NAME_EXPECTED);
2423 }
2424 }
2425 element.interfaces = interfaces;
2426 calculateAllSupertypes(element);
2427
2428 if (node.defaultClause != null) {
2429 element.defaultClass = visit(node.defaultClause);
2430 }
2431 addDefaultConstructorIfNeeded(element);
2432 return element.computeType(compiler);
2433 }
2434
2435 DartType visitTypeAnnotation(TypeAnnotation node) {
2436 return visit(node.typeName);
2437 }
2438
2439 DartType visitIdentifier(Identifier node) {
2440 Element element = scope.lookup(node.source);
2441 if (element == null) {
2442 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
2443 return null;
2444 } else if (!element.impliesType() && !element.isTypeVariable()) {
2445 error(node, MessageKind.NOT_A_TYPE, [node]);
2446 return null;
2447 } else {
2448 if (element.isTypeVariable()) {
2449 TypeVariableElement variableElement = element;
2450 return variableElement.type;
2451 } else if (element.isTypedef()) {
2452 compiler.unimplemented('visitIdentifier for typedefs', node: node);
2453 } else {
2454 // TODO(ngeoffray): Use type variables.
2455 return element.computeType(compiler);
2456 }
2457 }
2458 return null;
2459 }
2460
2461 DartType visitSend(Send node) {
2462 Identifier prefix = node.receiver.asIdentifier();
2463 if (prefix == null) {
2464 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
2465 return null;
2466 }
2467 Element element = scope.lookup(prefix.source);
2468 if (element == null || !identical(element.kind, ElementKind.PREFIX)) {
2469 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
2470 return null;
2471 }
2472 PrefixElement prefixElement = element;
2473 Identifier selector = node.selector.asIdentifier();
2474 var e = prefixElement.lookupLocalMember(selector.source);
2475 if (e == null || !e.impliesType()) {
2476 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
2477 return null;
2478 }
2479 return e.computeType(compiler);
2480 }
2481
2482 void calculateAllSupertypes(ClassElement cls) {
2483 // TODO(karlklose): substitute type variables.
2484 // TODO(karlklose): check if type arguments match, if a classelement occurs
2485 // more than once in the supertypes.
2486 if (cls.allSupertypes != null) return;
2487 final DartType supertype = cls.supertype;
2488 if (supertype != null) {
2489 ClassElement superElement = supertype.element;
2490 Link<DartType> superSupertypes = superElement.allSupertypes;
2491 assert(superSupertypes != null);
2492 Link<DartType> supertypes = superSupertypes.prepend(supertype);
2493 for (Link<DartType> interfaces = cls.interfaces;
2494 !interfaces.isEmpty();
2495 interfaces = interfaces.tail) {
2496 ClassElement element = interfaces.head.element;
2497 Link<DartType> interfaceSupertypes = element.allSupertypes;
2498 assert(interfaceSupertypes != null);
2499 supertypes = supertypes.reversePrependAll(interfaceSupertypes);
2500 supertypes = supertypes.prepend(interfaces.head);
2501 }
2502 cls.allSupertypes = supertypes;
2503 } else {
2504 assert(identical(cls, compiler.objectClass));
2505 cls.allSupertypes = const Link<DartType>();
2506 }
2507 }
2508
2509 /**
2510 * Add a synthetic nullary constructor if there are no other
2511 * constructors.
2512 */
2513 void addDefaultConstructorIfNeeded(ClassElement element) {
2514 if (element.hasConstructor) return;
2515 SynthesizedConstructorElement constructor =
2516 new SynthesizedConstructorElement(element);
2517 element.addToScope(constructor, compiler);
2518 DartType returnType = compiler.types.voidType;
2519 constructor.type = new FunctionType(returnType, const Link<DartType>(),
2520 constructor);
2521 constructor.cachedNode =
2522 new FunctionExpression(new Identifier(element.position()),
2523 new NodeList.empty(),
2524 new Block(new NodeList.empty()),
2525 null, Modifiers.EMPTY, null, null);
2526 }
2527
2528 isBlackListed(DartType type) {
2529 LibraryElement lib = element.getLibrary();
2530 return
2531 !identical(lib, compiler.coreLibrary) &&
2532 !identical(lib, compiler.coreImplLibrary) &&
2533 !identical(lib, compiler.jsHelperLibrary) &&
2534 (identical(type.element, compiler.dynamicClass) ||
2535 identical(type.element, compiler.boolClass) ||
2536 identical(type.element, compiler.numClass) ||
2537 identical(type.element, compiler.intClass) ||
2538 identical(type.element, compiler.doubleClass) ||
2539 identical(type.element, compiler.stringClass) ||
2540 identical(type.element, compiler.nullClass) ||
2541 identical(type.element, compiler.functionClass));
2542 }
2543 }
2544
2545 class ClassSupertypeResolver extends CommonResolverVisitor {
2546 Scope context;
2547 ClassElement classElement;
2548
2549 ClassSupertypeResolver(Compiler compiler, ClassElement cls)
2550 : context = cls.buildEnclosingScope(),
2551 this.classElement = cls,
2552 super(compiler);
2553
2554 void loadSupertype(ClassElement element, Node from) {
2555 compiler.resolver.loadSupertypes(element, from);
2556 element.ensureResolved(compiler);
2557 }
2558
2559 void visitClassNode(ClassNode node) {
2560 if (node.superclass == null) {
2561 if (!identical(classElement, compiler.objectClass)) {
2562 loadSupertype(compiler.objectClass, node);
2563 }
2564 } else {
2565 node.superclass.accept(this);
2566 }
2567 for (Link<Node> link = node.interfaces.nodes;
2568 !link.isEmpty();
2569 link = link.tail) {
2570 link.head.accept(this);
2571 }
2572 }
2573
2574 void visitTypeAnnotation(TypeAnnotation node) {
2575 node.typeName.accept(this);
2576 }
2577
2578 void visitIdentifier(Identifier node) {
2579 Element element = context.lookup(node.source);
2580 if (element == null) {
2581 error(node, MessageKind.CANNOT_RESOLVE_TYPE, [node]);
2582 } else if (!element.impliesType()) {
2583 error(node, MessageKind.NOT_A_TYPE, [node]);
2584 } else {
2585 if (element.isClass()) {
2586 loadSupertype(element, node);
2587 } else {
2588 compiler.reportMessage(
2589 compiler.spanFromNode(node),
2590 MessageKind.TYPE_NAME_EXPECTED.error([]),
2591 api.Diagnostic.ERROR);
2592 }
2593 }
2594 }
2595
2596 void visitSend(Send node) {
2597 Identifier prefix = node.receiver.asIdentifier();
2598 if (prefix == null) {
2599 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
2600 return;
2601 }
2602 Element element = context.lookup(prefix.source);
2603 if (element == null || !identical(element.kind, ElementKind.PREFIX)) {
2604 error(node.receiver, MessageKind.NOT_A_PREFIX, [node.receiver]);
2605 return;
2606 }
2607 PrefixElement prefixElement = element;
2608 Identifier selector = node.selector.asIdentifier();
2609 var e = prefixElement.lookupLocalMember(selector.source);
2610 if (e == null || !e.impliesType()) {
2611 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE, [node.selector]);
2612 return;
2613 }
2614 loadSupertype(e, node);
2615 }
2616 }
2617
2618 class VariableDefinitionsVisitor extends CommonResolverVisitor<SourceString> {
2619 VariableDefinitions definitions;
2620 ResolverVisitor resolver;
2621 ElementKind kind;
2622 VariableListElement variables;
2623
2624 VariableDefinitionsVisitor(Compiler compiler,
2625 this.definitions, this.resolver, this.kind)
2626 : super(compiler) {
2627 variables = new VariableListElement.node(
2628 definitions, ElementKind.VARIABLE_LIST, resolver.scope.element);
2629 }
2630
2631 SourceString visitSendSet(SendSet node) {
2632 assert(node.arguments.tail.isEmpty()); // Sanity check
2633 resolver.visit(node.arguments.head);
2634 return visit(node.selector);
2635 }
2636
2637 SourceString visitIdentifier(Identifier node) => node.source;
2638
2639 visitNodeList(NodeList node) {
2640 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
2641 SourceString name = visit(link.head);
2642 VariableElement element =
2643 new VariableElement(name, variables, kind, link.head);
2644 resolver.defineElement(link.head, element);
2645 }
2646 }
2647 }
2648
2649 /**
2650 * [SignatureResolver] resolves function signatures.
2651 */
2652 class SignatureResolver extends CommonResolverVisitor<Element> {
2653 final Element enclosingElement;
2654 Link<Element> optionalParameters = const Link<Element>();
2655 int optionalParameterCount = 0;
2656 bool optionalParametersAreNamed = false;
2657 VariableDefinitions currentDefinitions;
2658
2659 SignatureResolver(Compiler compiler, this.enclosingElement) : super(compiler);
2660
2661 Element visitNodeList(NodeList node) {
2662 // This must be a list of optional arguments.
2663 String value = node.beginToken.stringValue;
2664 if ((!identical(value, '[')) && (!identical(value, '{'))) {
2665 internalError(node, "expected optional parameters");
2666 }
2667 optionalParametersAreNamed = (identical(value, '{'));
2668 LinkBuilder<Element> elements = analyzeNodes(node.nodes);
2669 optionalParameterCount = elements.length;
2670 optionalParameters = elements.toLink();
2671 return null;
2672 }
2673
2674 Element visitVariableDefinitions(VariableDefinitions node) {
2675 Link<Node> definitions = node.definitions.nodes;
2676 if (definitions.isEmpty()) {
2677 cancel(node, 'internal error: no parameter definition');
2678 return null;
2679 }
2680 if (!definitions.tail.isEmpty()) {
2681 cancel(definitions.tail.head, 'internal error: extra definition');
2682 return null;
2683 }
2684 Node definition = definitions.head;
2685 if (definition is NodeList) {
2686 cancel(node, 'optional parameters are not implemented');
2687 }
2688
2689 if (currentDefinitions != null) {
2690 cancel(node, 'function type parameters not supported');
2691 }
2692 currentDefinitions = node;
2693 Element element = definition.accept(this);
2694 currentDefinitions = null;
2695 return element;
2696 }
2697
2698 Element visitIdentifier(Identifier node) {
2699 Element variables = new VariableListElement.node(currentDefinitions,
2700 ElementKind.VARIABLE_LIST, enclosingElement);
2701 // Ensure a parameter is not typed 'void'.
2702 variables.computeType(compiler);
2703 return new VariableElement(node.source, variables,
2704 ElementKind.PARAMETER, node);
2705 }
2706
2707 SourceString getParameterName(Send node) {
2708 var identifier = node.selector.asIdentifier();
2709 if (identifier != null) {
2710 // Normal parameter: [:Type name:].
2711 return identifier.source;
2712 } else {
2713 // Function type parameter: [:void name(DartType arg):].
2714 var functionExpression = node.selector.asFunctionExpression();
2715 if (functionExpression != null &&
2716 functionExpression.name.asIdentifier() != null) {
2717 return functionExpression.name.asIdentifier().source;
2718 } else {
2719 cancel(node,
2720 'internal error: unimplemented receiver on parameter send');
2721 }
2722 }
2723 }
2724
2725 // The only valid [Send] can be in constructors and must be of the form
2726 // [:this.x:] (where [:x:] represents an instance field).
2727 FieldParameterElement visitSend(Send node) {
2728 FieldParameterElement element;
2729 if (node.receiver.asIdentifier() == null ||
2730 !node.receiver.asIdentifier().isThis()) {
2731 error(node, MessageKind.INVALID_PARAMETER, []);
2732 } else if (!identical(enclosingElement.kind, ElementKind.GENERATIVE_CONSTRUC TOR)) {
2733 error(node, MessageKind.FIELD_PARAMETER_NOT_ALLOWED, []);
2734 } else {
2735 SourceString name = getParameterName(node);
2736 Element fieldElement = currentClass.lookupLocalMember(name);
2737 if (fieldElement == null || !identical(fieldElement.kind, ElementKind.FIEL D)) {
2738 error(node, MessageKind.NOT_A_FIELD, [name]);
2739 } else if (!fieldElement.isInstanceMember()) {
2740 error(node, MessageKind.NOT_INSTANCE_FIELD, [name]);
2741 }
2742 Element variables = new VariableListElement.node(currentDefinitions,
2743 ElementKind.VARIABLE_LIST, enclosingElement);
2744 element = new FieldParameterElement(name, fieldElement, variables, node);
2745 }
2746 return element;
2747 }
2748
2749 Element visitSendSet(SendSet node) {
2750 Element element;
2751 if (node.receiver != null) {
2752 element = visitSend(node);
2753 } else if (node.selector.asIdentifier() != null) {
2754 Element variables = new VariableListElement.node(currentDefinitions,
2755 ElementKind.VARIABLE_LIST, enclosingElement);
2756 element = new VariableElement(node.selector.asIdentifier().source,
2757 variables, ElementKind.PARAMETER, node);
2758 }
2759 // Visit the value. The compile time constant handler will
2760 // make sure it's a compile time constant.
2761 resolveExpression(node.arguments.head);
2762 return element;
2763 }
2764
2765 Element visitFunctionExpression(FunctionExpression node) {
2766 // This is a function typed parameter.
2767 // TODO(ahe): Resolve the function type.
2768 return visit(node.name);
2769 }
2770
2771 LinkBuilder<Element> analyzeNodes(Link<Node> link) {
2772 LinkBuilder<Element> elements = new LinkBuilder<Element>();
2773 for (; !link.isEmpty(); link = link.tail) {
2774 Element element = link.head.accept(this);
2775 if (element != null) {
2776 elements.addLast(element);
2777 } else {
2778 // If parameter is null, the current node should be the last,
2779 // and a list of optional named parameters.
2780 if (!link.tail.isEmpty() || (link.head is !NodeList)) {
2781 internalError(link.head, "expected optional parameters");
2782 }
2783 }
2784 }
2785 return elements;
2786 }
2787
2788 /**
2789 * Resolves formal parameters and return type to a [FunctionSignature].
2790 */
2791 static FunctionSignature analyze(Compiler compiler,
2792 NodeList formalParameters,
2793 Node returnNode,
2794 Element element) {
2795 SignatureResolver visitor = new SignatureResolver(compiler, element);
2796 Link<Element> parameters = const Link<Element>();
2797 int requiredParameterCount = 0;
2798 if (formalParameters == null) {
2799 if (!element.isGetter()) {
2800 compiler.reportMessage(compiler.spanFromElement(element),
2801 MessageKind.MISSING_FORMALS.error([]),
2802 api.Diagnostic.ERROR);
2803 }
2804 } else {
2805 if (element.isGetter()) {
2806 if (!element.getLibrary().isPlatformLibrary) {
2807 // TODO(ahe): Remove the isPlatformLibrary check.
2808 if (!identical(formalParameters.getEndToken().next.stringValue, 'nativ e')) {
2809 // TODO(ahe): Remove the check for native keyword.
2810 compiler.reportMessage(compiler.spanFromNode(formalParameters),
2811 MessageKind.EXTRA_FORMALS.error([]),
2812 api.Diagnostic.WARNING);
2813 }
2814 }
2815 }
2816 LinkBuilder<Element> parametersBuilder =
2817 visitor.analyzeNodes(formalParameters.nodes);
2818 requiredParameterCount = parametersBuilder.length;
2819 parameters = parametersBuilder.toLink();
2820 }
2821 DartType returnType = compiler.resolveReturnType(element, returnNode);
2822 return new FunctionSignature(parameters,
2823 visitor.optionalParameters,
2824 requiredParameterCount,
2825 visitor.optionalParameterCount,
2826 visitor.optionalParametersAreNamed,
2827 returnType);
2828 }
2829
2830 // TODO(ahe): This is temporary.
2831 void resolveExpression(Node node) {
2832 if (node == null) return;
2833 node.accept(new ResolverVisitor(compiler, enclosingElement));
2834 }
2835
2836 // TODO(ahe): This is temporary.
2837 ClassElement get currentClass {
2838 return enclosingElement.isMember()
2839 ? enclosingElement.getEnclosingClass() : null;
2840 }
2841 }
2842
2843 class ConstructorResolver extends CommonResolverVisitor<Element> {
2844 final ResolverVisitor resolver;
2845 // TODO(ngeoffray): have this context at the call site.
2846 final bool inConstContext;
2847
2848 ConstructorResolver(Compiler compiler,
2849 this.resolver,
2850 this.inConstContext)
2851 : super(compiler);
2852
2853 visitNode(Node node) {
2854 throw 'not supported';
2855 }
2856
2857 failOrReturnErroneousElement(Element enclosing, Node diagnosticNode,
2858 SourceString targetName, MessageKind kind,
2859 List arguments) {
2860 if (inConstContext) {
2861 error(diagnosticNode, kind, arguments);
2862 } else {
2863 ResolutionWarning warning = new ResolutionWarning(kind, arguments);
2864 compiler.reportWarning(diagnosticNode, warning);
2865 return new ErroneousFunctionElement(kind, arguments, targetName,
2866 enclosing);
2867 }
2868 }
2869
2870 Selector createConstructorSelector(SourceString constructorName) {
2871 return constructorName == const SourceString('')
2872 ? new Selector.callDefaultConstructor(
2873 resolver.enclosingElement.getLibrary())
2874 : new Selector.callConstructor(
2875 constructorName,
2876 resolver.enclosingElement.getLibrary());
2877 }
2878
2879 // TODO(ngeoffray): method named lookup should not report errors.
2880 FunctionElement lookupConstructor(ClassElement cls,
2881 Node diagnosticNode,
2882 SourceString constructorName) {
2883 cls.ensureResolved(compiler);
2884 Selector selector = createConstructorSelector(constructorName);
2885 Element result = cls.lookupConstructor(selector);
2886 if (result == null) {
2887 String fullConstructorName =
2888 resolver.compiler.resolver.constructorNameForDiagnostics(
2889 cls.name,
2890 constructorName);
2891 return failOrReturnErroneousElement(
2892 cls,
2893 diagnosticNode,
2894 new SourceString(fullConstructorName),
2895 MessageKind.CANNOT_FIND_CONSTRUCTOR,
2896 [fullConstructorName]);
2897 } else if (inConstContext && !result.modifiers.isConst()) {
2898 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
2899 }
2900 return result;
2901 }
2902
2903 visitNewExpression(NewExpression node) {
2904 Node selector = node.send.selector;
2905 Element e = visit(selector);
2906 if (!Elements.isUnresolved(e) && identical(e.kind, ElementKind.CLASS)) {
2907 ClassElement cls = e;
2908 cls.ensureResolved(compiler);
2909 if (cls.isInterface() && (cls.defaultClass == null)) {
2910 error(selector, MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]);
2911 }
2912 e = lookupConstructor(cls, selector, const SourceString(''));
2913 }
2914 return e;
2915 }
2916
2917 visitTypeAnnotation(TypeAnnotation node) {
2918 return visit(node.typeName);
2919 }
2920
2921 visitSend(Send node) {
2922 Element e = visit(node.receiver);
2923 if (Elements.isUnresolved(e)) return e;
2924 Identifier name = node.selector.asIdentifier();
2925 if (name == null) internalError(node.selector, 'unexpected node');
2926
2927 if (identical(e.kind, ElementKind.CLASS)) {
2928 ClassElement cls = e;
2929 cls.ensureResolved(compiler);
2930 if (cls.isInterface() && (cls.defaultClass == null)) {
2931 error(node.receiver, MessageKind.CANNOT_INSTANTIATE_INTERFACE,
2932 [cls.name]);
2933 }
2934 return lookupConstructor(cls, name, name.source);
2935 } else if (identical(e.kind, ElementKind.PREFIX)) {
2936 PrefixElement prefix = e;
2937 e = prefix.lookupLocalMember(name.source);
2938 if (e == null) {
2939 return failOrReturnErroneousElement(resolver.enclosingElement, name,
2940 name.source,
2941 MessageKind.CANNOT_RESOLVE,
2942 [name]);
2943 } else if (!identical(e.kind, ElementKind.CLASS)) {
2944 error(node, MessageKind.NOT_A_TYPE, [name]);
2945 }
2946 } else {
2947 internalError(node.receiver, 'unexpected element $e');
2948 }
2949 return e;
2950 }
2951
2952 Element visitIdentifier(Identifier node) {
2953 SourceString name = node.source;
2954 Element e = resolver.lookup(node, name);
2955 if (e == null) {
2956 return failOrReturnErroneousElement(resolver.enclosingElement, node, name,
2957 MessageKind.CANNOT_RESOLVE, [name]);
2958 } else if (identical(e.kind, ElementKind.TYPEDEF)) {
2959 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]);
2960 } else if (!identical(e.kind, ElementKind.CLASS)
2961 && !identical(e.kind, ElementKind.PREFIX)) {
2962 error(node, MessageKind.NOT_A_TYPE, [name]);
2963 }
2964 return e;
2965 }
2966 }
2967
2968 abstract class Scope {
2969 final Element element;
2970 final Scope parent;
2971
2972 Scope(this.parent, this.element);
2973 abstract Element add(Element element);
2974
2975 Element lookup(SourceString name) {
2976 Element result = localLookup(name);
2977 if (result != null) return result;
2978 return parent.lookup(name);
2979 }
2980
2981 Element lexicalLookup(SourceString name) {
2982 Element result = localLookup(name);
2983 if (result != null) return result;
2984 return parent.lexicalLookup(name);
2985 }
2986
2987 abstract Element localLookup(SourceString name);
2988 }
2989
2990 class VariableScope extends Scope {
2991 VariableScope(parent, element) : super(parent, element);
2992
2993 Element add(Element newElement) {
2994 throw "Cannot add element to VariableScope";
2995 }
2996
2997 Element localLookup(SourceString name) => null;
2998
2999 String toString() => '$element > $parent';
3000 }
3001
3002 /**
3003 * [TypeDeclarationScope] defines the outer scope of a type declaration in
3004 * which the declared type variables and the entities in the enclosing scope are
3005 * available but where declared and inherited members are not available. This
3006 * scope is only used for class/interface declarations during resolution of the
3007 * class hierarchy. In all other cases [ClassScope] is used.
3008 */
3009 class TypeDeclarationScope extends Scope {
3010 TypeDeclarationElement get element => super.element;
3011
3012 TypeDeclarationScope(parent, TypeDeclarationElement element)
3013 : super(parent, element) {
3014 assert(parent != null);
3015 }
3016
3017 Element add(Element newElement) {
3018 throw "Cannot add element to TypeDeclarationScope";
3019 }
3020
3021 Element localLookup(SourceString name) {
3022 Link<DartType> typeVariableLink = element.typeVariables;
3023 while (!typeVariableLink.isEmpty()) {
3024 TypeVariableType typeVariable = typeVariableLink.head;
3025 if (typeVariable.name == name) {
3026 return typeVariable.element;
3027 }
3028 typeVariableLink = typeVariableLink.tail;
3029 }
3030 return null;
3031 }
3032
3033 String toString() =>
3034 'TypeDeclarationScope($element)';
3035 }
3036
3037 class MethodScope extends Scope {
3038 final Map<SourceString, Element> elements;
3039
3040 MethodScope(Scope parent, Element element)
3041 : super(parent, element),
3042 this.elements = new Map<SourceString, Element>() {
3043 assert(parent != null);
3044 }
3045
3046 Element localLookup(SourceString name) => elements[name];
3047
3048 Element add(Element newElement) {
3049 if (elements.containsKey(newElement.name)) {
3050 return elements[newElement.name];
3051 }
3052 elements[newElement.name] = newElement;
3053 return newElement;
3054 }
3055
3056 String toString() => '$element${elements.getKeys()}';
3057 }
3058
3059 class BlockScope extends MethodScope {
3060 BlockScope(Scope parent) : super(parent, parent.element);
3061
3062 String toString() => 'block${elements.getKeys()}';
3063 }
3064
3065 /**
3066 * [ClassScope] defines the inner scope of a class/interface declaration in
3067 * which declared members, declared type variables, entities in the enclosing
3068 * scope and inherited members are available, in the given order.
3069 */
3070 class ClassScope extends TypeDeclarationScope {
3071 bool inStaticContext = false;
3072
3073 ClassScope(Scope parentScope, ClassElement element)
3074 : super(parentScope, element) {
3075 assert(parent != null);
3076 }
3077
3078 Element localLookup(SourceString name) {
3079 ClassElement cls = element;
3080 Element result = cls.lookupLocalMember(name);
3081 if (result != null) return result;
3082 if (!inStaticContext) {
3083 // If not in a static context, we can lookup in the
3084 // TypeDeclaration scope, which contains the type variables of
3085 // the class.
3086 result = super.localLookup(name);
3087 }
3088 return result;
3089 }
3090
3091 Element lookup(SourceString name) {
3092 Element result = localLookup(name);
3093 if (result != null) return result;
3094 result = parent.lookup(name);
3095 if (result != null) return result;
3096 ClassElement cls = element;
3097 return cls.lookupSuperMember(name);
3098 }
3099
3100 Element add(Element newElement) {
3101 throw "Cannot add an element in a class scope";
3102 }
3103
3104 String toString() => 'ClassScope($element)';
3105 }
3106
3107 // TODO(johnniwinther): Refactor scopes to avoid class explosion.
3108 class PatchClassScope extends TypeDeclarationScope {
3109 bool inStaticContext = false;
3110 ClassElement get origin => element;
3111 final ClassElement patch;
3112
3113 PatchClassScope(Scope parentScope,
3114 ClassElement origin, ClassElement this.patch)
3115 : super(parentScope, origin) {
3116 assert(parent != null);
3117 }
3118
3119 Element localLookup(SourceString name) {
3120 Element result = patch.lookupLocalMember(name);
3121 if (result != null) return result;
3122 result = origin.lookupLocalMember(name);
3123 if (result != null) return result;
3124 if (!inStaticContext) {
3125 // If not in a static context, we can lookup in the
3126 // TypeDeclaration scope, which contains the type variables of
3127 // the class.
3128 result = super.localLookup(name);
3129 if (result != null) return result;
3130 }
3131 result = parent.lookup(name);
3132 if (result != null) return result;
3133 return result;
3134 }
3135
3136 Element lookup(SourceString name) {
3137 Element result = localLookup(name);
3138 if (result != null) return result;
3139 // TODO(johnniwinther): Should we support patch lookup on supertypes?
3140 return origin.lookupSuperMember(name);
3141 }
3142
3143 Element add(Element newElement) {
3144 throw "Cannot add an element in a class scope";
3145 }
3146
3147 String toString() => 'PatchClassScope($origin,$patch)';
3148 }
3149
3150 class LocalClassScope extends Scope {
3151 LocalClassScope(ClassElement element)
3152 : super(null, element);
3153
3154 Element lookup(SourceString name) => localLookup(name);
3155
3156 Element localLookup(SourceString name) {
3157 ClassElement cls = element;
3158 return cls.lookupLocalMember(name);
3159 }
3160
3161 Element add(Element newElement) {
3162 throw "Cannot add an element in a class scope";
3163 }
3164
3165 String toString() => 'LocalClassScope($element)';
3166 }
3167
3168 class LocalPatchClassScope extends Scope {
3169 ClassElement get origin => element;
3170 final ClassElement patch;
3171
3172 LocalPatchClassScope(ClassElement origin, ClassElement this.patch)
3173 : super(null, origin);
3174
3175 Element lookup(SourceString name) => localLookup(name);
3176
3177 Element localLookup(SourceString name) {
3178 Element result = patch.lookupLocalMember(name);
3179 if (result != null) return result;
3180 return origin.lookupLocalMember(name);
3181 }
3182
3183
3184 Element add(Element newElement) {
3185 throw "Cannot add an element in a class scope";
3186 }
3187
3188 String toString() => 'LocalPatchClassScope($origin,$patch)';
3189 }
3190
3191 class TopScope extends Scope {
3192 LibraryElement get library => element;
3193
3194 TopScope(LibraryElement library) : super(null, library);
3195
3196 Element localLookup(SourceString name) => library.find(name);
3197 Element lookup(SourceString name) => localLookup(name);
3198 Element lexicalLookup(SourceString name) => localLookup(name);
3199
3200 Element add(Element newElement) {
3201 throw "Cannot add an element in the top scope";
3202 }
3203 String toString() => 'LibraryScope($element)';
3204 }
3205
3206 class PatchLibraryScope extends Scope {
3207 LibraryElement get origin => element;
3208 final LibraryElement patch;
3209
3210 PatchLibraryScope(LibraryElement origin, LibraryElement this.patch)
3211 : super(null, origin);
3212
3213 Element localLookup(SourceString name) {
3214 Element result = patch.find(name);
3215 if (result != null) {
3216 return result;
3217 }
3218 result = origin.find(name);
3219 if (result != null) {
3220 return result;
3221 }
3222 return result;
3223 }
3224 Element lookup(SourceString name) => localLookup(name);
3225 Element lexicalLookup(SourceString name) => localLookup(name);
3226
3227 Element add(Element newElement) {
3228 throw "Cannot add an element in a patch library scope";
3229 }
3230 String toString() => 'PatchLibraryScope($origin,$patch)';
3231 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698