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

Side by Side Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1152963003: Split resolution/members.dart into several parts. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 7 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of resolution; 5 part of resolution;
6 6
7 abstract class TreeElements {
8 AnalyzableElement get analyzedElement;
9 Iterable<Node> get superUses;
10
11 /// Iterables of the dependencies that this [TreeElement] records of
12 /// [analyzedElement].
13 Iterable<Element> get allElements;
14 void forEachConstantNode(f(Node n, ConstantExpression c));
15
16 /// A set of additional dependencies. See [registerDependency] below.
17 Iterable<Element> get otherDependencies;
18
19 Element operator[](Node node);
20
21 SendStructure getSendStructure(Send send);
22
23 // TODO(johnniwinther): Investigate whether [Node] could be a [Send].
24 Selector getSelector(Node node);
25 Selector getGetterSelectorInComplexSendSet(SendSet node);
26 Selector getOperatorSelectorInComplexSendSet(SendSet node);
27 DartType getType(Node node);
28 void setSelector(Node node, Selector selector);
29 void setGetterSelectorInComplexSendSet(SendSet node, Selector selector);
30 void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector);
31
32 /// Returns the for-in loop variable for [node].
33 Element getForInVariable(ForIn node);
34 Selector getIteratorSelector(ForIn node);
35 Selector getMoveNextSelector(ForIn node);
36 Selector getCurrentSelector(ForIn node);
37 void setIteratorSelector(ForIn node, Selector selector);
38 void setMoveNextSelector(ForIn node, Selector selector);
39 void setCurrentSelector(ForIn node, Selector selector);
40 void setConstant(Node node, ConstantExpression constant);
41 ConstantExpression getConstant(Node node);
42 bool isAssert(Send send);
43
44 /// Returns the [FunctionElement] defined by [node].
45 FunctionElement getFunctionDefinition(FunctionExpression node);
46
47 /// Returns target constructor for the redirecting factory body [node].
48 ConstructorElement getRedirectingTargetConstructor(
49 RedirectingFactoryBody node);
50
51 /**
52 * Returns [:true:] if [node] is a type literal.
53 *
54 * Resolution marks this by setting the type on the node to be the
55 * type that the literal refers to.
56 */
57 bool isTypeLiteral(Send node);
58
59 /// Returns the type that the type literal [node] refers to.
60 DartType getTypeLiteralType(Send node);
61
62 /// Register additional dependencies required by [analyzedElement].
63 /// For example, elements that are used by a backend.
64 void registerDependency(Element element);
65
66 /// Returns a list of nodes that potentially mutate [element] anywhere in its
67 /// scope.
68 List<Node> getPotentialMutations(VariableElement element);
69
70 /// Returns a list of nodes that potentially mutate [element] in [node].
71 List<Node> getPotentialMutationsIn(Node node, VariableElement element);
72
73 /// Returns a list of nodes that potentially mutate [element] in a closure.
74 List<Node> getPotentialMutationsInClosure(VariableElement element);
75
76 /// Returns a list of nodes that access [element] within a closure in [node].
77 List<Node> getAccessesByClosureIn(Node node, VariableElement element);
78
79 /// Returns the jump target defined by [node].
80 JumpTarget getTargetDefinition(Node node);
81
82 /// Returns the jump target of the [node].
83 JumpTarget getTargetOf(GotoStatement node);
84
85 /// Returns the label defined by [node].
86 LabelDefinition getLabelDefinition(Label node);
87
88 /// Returns the label that [node] targets.
89 LabelDefinition getTargetLabel(GotoStatement node);
90 }
91
92 class TreeElementMapping implements TreeElements {
93 final AnalyzableElement analyzedElement;
94 Map<Spannable, Selector> _selectors;
95 Map<Node, DartType> _types;
96 Setlet<Node> _superUses;
97 Setlet<Element> _otherDependencies;
98 Map<Node, ConstantExpression> _constants;
99 Map<VariableElement, List<Node>> _potentiallyMutated;
100 Map<Node, Map<VariableElement, List<Node>>> _potentiallyMutatedIn;
101 Map<VariableElement, List<Node>> _potentiallyMutatedInClosure;
102 Map<Node, Map<VariableElement, List<Node>>> _accessedByClosureIn;
103 Setlet<Element> _elements;
104 Setlet<Send> _asserts;
105 Maplet<Send, SendStructure> _sendStructureMap;
106
107 /// Map from nodes to the targets they define.
108 Map<Node, JumpTarget> _definedTargets;
109
110 /// Map from goto statements to their targets.
111 Map<GotoStatement, JumpTarget> _usedTargets;
112
113 /// Map from labels to their label definition.
114 Map<Label, LabelDefinition> _definedLabels;
115
116 /// Map from labeled goto statements to the labels they target.
117 Map<GotoStatement, LabelDefinition> _targetLabels;
118
119 final int hashCode = ++_hashCodeCounter;
120 static int _hashCodeCounter = 0;
121
122 TreeElementMapping(this.analyzedElement);
123
124 operator []=(Node node, Element element) {
125 // TODO(johnniwinther): Simplify this invariant to use only declarations in
126 // [TreeElements].
127 assert(invariant(node, () {
128 if (!element.isErroneous && analyzedElement != null && element.isPatch) {
129 return analyzedElement.implementationLibrary.isPatch;
130 }
131 return true;
132 }));
133 // TODO(ahe): Investigate why the invariant below doesn't hold.
134 // assert(invariant(node,
135 // getTreeElement(node) == element ||
136 // getTreeElement(node) == null,
137 // message: '${getTreeElement(node)}; $element'));
138
139 if (_elements == null) {
140 _elements = new Setlet<Element>();
141 }
142 _elements.add(element);
143 setTreeElement(node, element);
144 }
145
146 operator [](Node node) => getTreeElement(node);
147
148 SendStructure getSendStructure(Send send) {
149 if (_sendStructureMap == null) return null;
150 return _sendStructureMap[send];
151 }
152
153 void setSendStructure(Send send, SendStructure sendStructure) {
154 if (_sendStructureMap == null) {
155 _sendStructureMap = new Maplet<Send, SendStructure>();
156 }
157 _sendStructureMap[send] = sendStructure;
158 }
159
160 void setType(Node node, DartType type) {
161 if (_types == null) {
162 _types = new Maplet<Node, DartType>();
163 }
164 _types[node] = type;
165 }
166
167 DartType getType(Node node) => _types != null ? _types[node] : null;
168
169 Iterable<Node> get superUses {
170 return _superUses != null ? _superUses : const <Node>[];
171 }
172
173 void addSuperUse(Node node) {
174 if (_superUses == null) {
175 _superUses = new Setlet<Node>();
176 }
177 _superUses.add(node);
178 }
179
180 Selector _getSelector(Spannable node) {
181 return _selectors != null ? _selectors[node] : null;
182 }
183
184 void _setSelector(Spannable node, Selector selector) {
185 if (_selectors == null) {
186 _selectors = new Maplet<Spannable, Selector>();
187 }
188 _selectors[node] = selector;
189 }
190
191 void setSelector(Node node, Selector selector) {
192 _setSelector(node, selector);
193 }
194
195 Selector getSelector(Node node) => _getSelector(node);
196
197 int getSelectorCount() => _selectors == null ? 0 : _selectors.length;
198
199 void setGetterSelectorInComplexSendSet(SendSet node, Selector selector) {
200 _setSelector(node.selector, selector);
201 }
202
203 Selector getGetterSelectorInComplexSendSet(SendSet node) {
204 return _getSelector(node.selector);
205 }
206
207 void setOperatorSelectorInComplexSendSet(SendSet node, Selector selector) {
208 _setSelector(node.assignmentOperator, selector);
209 }
210
211 Selector getOperatorSelectorInComplexSendSet(SendSet node) {
212 return _getSelector(node.assignmentOperator);
213 }
214
215 // The following methods set selectors on the "for in" node. Since
216 // we're using three selectors, we need to use children of the node,
217 // and we arbitrarily choose which ones.
218
219 void setIteratorSelector(ForIn node, Selector selector) {
220 _setSelector(node, selector);
221 }
222
223 Selector getIteratorSelector(ForIn node) {
224 return _getSelector(node);
225 }
226
227 void setMoveNextSelector(ForIn node, Selector selector) {
228 _setSelector(node.forToken, selector);
229 }
230
231 Selector getMoveNextSelector(ForIn node) {
232 return _getSelector(node.forToken);
233 }
234
235 void setCurrentSelector(ForIn node, Selector selector) {
236 _setSelector(node.inToken, selector);
237 }
238
239 Selector getCurrentSelector(ForIn node) {
240 return _getSelector(node.inToken);
241 }
242
243 Element getForInVariable(ForIn node) {
244 return this[node];
245 }
246
247 void setConstant(Node node, ConstantExpression constant) {
248 if (_constants == null) {
249 _constants = new Maplet<Node, ConstantExpression>();
250 }
251 _constants[node] = constant;
252 }
253
254 ConstantExpression getConstant(Node node) {
255 return _constants != null ? _constants[node] : null;
256 }
257
258 bool isTypeLiteral(Send node) {
259 return getType(node) != null;
260 }
261
262 DartType getTypeLiteralType(Send node) {
263 return getType(node);
264 }
265
266 void registerDependency(Element element) {
267 if (element == null) return;
268 if (_otherDependencies == null) {
269 _otherDependencies = new Setlet<Element>();
270 }
271 _otherDependencies.add(element.implementation);
272 }
273
274 Iterable<Element> get otherDependencies {
275 return _otherDependencies != null ? _otherDependencies : const <Element>[];
276 }
277
278 List<Node> getPotentialMutations(VariableElement element) {
279 if (_potentiallyMutated == null) return const <Node>[];
280 List<Node> mutations = _potentiallyMutated[element];
281 if (mutations == null) return const <Node>[];
282 return mutations;
283 }
284
285 void registerPotentialMutation(VariableElement element, Node mutationNode) {
286 if (_potentiallyMutated == null) {
287 _potentiallyMutated = new Maplet<VariableElement, List<Node>>();
288 }
289 _potentiallyMutated.putIfAbsent(element, () => <Node>[]).add(mutationNode);
290 }
291
292 List<Node> getPotentialMutationsIn(Node node, VariableElement element) {
293 if (_potentiallyMutatedIn == null) return const <Node>[];
294 Map<VariableElement, List<Node>> mutationsIn = _potentiallyMutatedIn[node];
295 if (mutationsIn == null) return const <Node>[];
296 List<Node> mutations = mutationsIn[element];
297 if (mutations == null) return const <Node>[];
298 return mutations;
299 }
300
301 void registerPotentialMutationIn(Node contextNode, VariableElement element,
302 Node mutationNode) {
303 if (_potentiallyMutatedIn == null) {
304 _potentiallyMutatedIn =
305 new Maplet<Node, Map<VariableElement, List<Node>>>();
306 }
307 Map<VariableElement, List<Node>> mutationMap =
308 _potentiallyMutatedIn.putIfAbsent(contextNode,
309 () => new Maplet<VariableElement, List<Node>>());
310 mutationMap.putIfAbsent(element, () => <Node>[]).add(mutationNode);
311 }
312
313 List<Node> getPotentialMutationsInClosure(VariableElement element) {
314 if (_potentiallyMutatedInClosure == null) return const <Node>[];
315 List<Node> mutations = _potentiallyMutatedInClosure[element];
316 if (mutations == null) return const <Node>[];
317 return mutations;
318 }
319
320 void registerPotentialMutationInClosure(VariableElement element,
321 Node mutationNode) {
322 if (_potentiallyMutatedInClosure == null) {
323 _potentiallyMutatedInClosure = new Maplet<VariableElement, List<Node>>();
324 }
325 _potentiallyMutatedInClosure.putIfAbsent(
326 element, () => <Node>[]).add(mutationNode);
327 }
328
329 List<Node> getAccessesByClosureIn(Node node, VariableElement element) {
330 if (_accessedByClosureIn == null) return const <Node>[];
331 Map<VariableElement, List<Node>> accessesIn = _accessedByClosureIn[node];
332 if (accessesIn == null) return const <Node>[];
333 List<Node> accesses = accessesIn[element];
334 if (accesses == null) return const <Node>[];
335 return accesses;
336 }
337
338 void setAccessedByClosureIn(Node contextNode, VariableElement element,
339 Node accessNode) {
340 if (_accessedByClosureIn == null) {
341 _accessedByClosureIn = new Map<Node, Map<VariableElement, List<Node>>>();
342 }
343 Map<VariableElement, List<Node>> accessMap =
344 _accessedByClosureIn.putIfAbsent(contextNode,
345 () => new Maplet<VariableElement, List<Node>>());
346 accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode);
347 }
348
349 String toString() => 'TreeElementMapping($analyzedElement)';
350
351 Iterable<Element> get allElements {
352 return _elements != null ? _elements : const <Element>[];
353 }
354
355 void forEachConstantNode(f(Node n, ConstantExpression c)) {
356 if (_constants != null) {
357 _constants.forEach(f);
358 }
359 }
360
361 void setAssert(Send node) {
362 if (_asserts == null) {
363 _asserts = new Setlet<Send>();
364 }
365 _asserts.add(node);
366 }
367
368 bool isAssert(Send node) {
369 return _asserts != null && _asserts.contains(node);
370 }
371
372 FunctionElement getFunctionDefinition(FunctionExpression node) {
373 return this[node];
374 }
375
376 ConstructorElement getRedirectingTargetConstructor(
377 RedirectingFactoryBody node) {
378 return this[node];
379 }
380
381 void defineTarget(Node node, JumpTarget target) {
382 if (_definedTargets == null) {
383 _definedTargets = new Maplet<Node, JumpTarget>();
384 }
385 _definedTargets[node] = target;
386 }
387
388 void undefineTarget(Node node) {
389 if (_definedTargets != null) {
390 _definedTargets.remove(node);
391 if (_definedTargets.isEmpty) {
392 _definedTargets = null;
393 }
394 }
395 }
396
397 JumpTarget getTargetDefinition(Node node) {
398 return _definedTargets != null ? _definedTargets[node] : null;
399 }
400
401 void registerTargetOf(GotoStatement node, JumpTarget target) {
402 if (_usedTargets == null) {
403 _usedTargets = new Maplet<GotoStatement, JumpTarget>();
404 }
405 _usedTargets[node] = target;
406 }
407
408 JumpTarget getTargetOf(GotoStatement node) {
409 return _usedTargets != null ? _usedTargets[node] : null;
410 }
411
412 void defineLabel(Label label, LabelDefinition target) {
413 if (_definedLabels == null) {
414 _definedLabels = new Maplet<Label, LabelDefinition>();
415 }
416 _definedLabels[label] = target;
417 }
418
419 void undefineLabel(Label label) {
420 if (_definedLabels != null) {
421 _definedLabels.remove(label);
422 if (_definedLabels.isEmpty) {
423 _definedLabels = null;
424 }
425 }
426 }
427
428 LabelDefinition getLabelDefinition(Label label) {
429 return _definedLabels != null ? _definedLabels[label] : null;
430 }
431
432 void registerTargetLabel(GotoStatement node, LabelDefinition label) {
433 assert(node.target != null);
434 if (_targetLabels == null) {
435 _targetLabels = new Maplet<GotoStatement, LabelDefinition>();
436 }
437 _targetLabels[node] = label;
438 }
439
440 LabelDefinition getTargetLabel(GotoStatement node) {
441 assert(node.target != null);
442 return _targetLabels != null ? _targetLabels[node] : null;
443 }
444 }
445
446 class ResolverTask extends CompilerTask {
447 final ConstantCompiler constantCompiler;
448
449 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler);
450
451 String get name => 'Resolver';
452
453 TreeElements resolve(Element element) {
454 return measure(() {
455 if (Elements.isErroneous(element)) return null;
456
457 processMetadata([result]) {
458 for (MetadataAnnotation metadata in element.metadata) {
459 metadata.ensureResolved(compiler);
460 }
461 return result;
462 }
463
464 ElementKind kind = element.kind;
465 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) ||
466 identical(kind, ElementKind.FUNCTION) ||
467 identical(kind, ElementKind.GETTER) ||
468 identical(kind, ElementKind.SETTER)) {
469 return processMetadata(resolveMethodElement(element));
470 }
471
472 if (identical(kind, ElementKind.FIELD)) {
473 return processMetadata(resolveField(element));
474 }
475 if (element.isClass) {
476 ClassElement cls = element;
477 cls.ensureResolved(compiler);
478 return processMetadata();
479 } else if (element.isTypedef) {
480 TypedefElement typdef = element;
481 return processMetadata(resolveTypedef(typdef));
482 }
483
484 compiler.unimplemented(element, "resolve($element)");
485 });
486 }
487
488 void resolveRedirectingConstructor(InitializerResolver resolver,
489 Node node,
490 FunctionElement constructor,
491 FunctionElement redirection) {
492 assert(invariant(node, constructor.isImplementation,
493 message: 'Redirecting constructors must be resolved on implementation '
494 'elements.'));
495 Setlet<FunctionElement> seen = new Setlet<FunctionElement>();
496 seen.add(constructor);
497 while (redirection != null) {
498 // Ensure that we follow redirections through implementation elements.
499 redirection = redirection.implementation;
500 if (seen.contains(redirection)) {
501 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
502 return;
503 }
504 seen.add(redirection);
505 redirection = resolver.visitor.resolveConstructorRedirection(redirection);
506 }
507 }
508
509 static void processAsyncMarker(Compiler compiler,
510 BaseFunctionElementX element,
511 Registry registry) {
512 FunctionExpression functionExpression = element.node;
513 AsyncModifier asyncModifier = functionExpression.asyncModifier;
514 if (asyncModifier != null) {
515
516 if (asyncModifier.isAsynchronous) {
517 element.asyncMarker = asyncModifier.isYielding
518 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC;
519 } else {
520 element.asyncMarker = AsyncMarker.SYNC_STAR;
521 }
522 if (element.isAbstract) {
523 compiler.reportError(asyncModifier,
524 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD,
525 {'modifier': element.asyncMarker});
526 } else if (element.isConstructor) {
527 compiler.reportError(asyncModifier,
528 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR,
529 {'modifier': element.asyncMarker});
530 } else {
531 if (element.isSetter) {
532 compiler.reportError(asyncModifier,
533 MessageKind.ASYNC_MODIFIER_ON_SETTER,
534 {'modifier': element.asyncMarker});
535
536 }
537 if (functionExpression.body.asReturn() != null &&
538 element.asyncMarker.isYielding) {
539 compiler.reportError(asyncModifier,
540 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
541 {'modifier': element.asyncMarker});
542 }
543 }
544 registry.registerAsyncMarker(element);
545 switch (element.asyncMarker) {
546 case AsyncMarker.ASYNC:
547 compiler.futureClass.ensureResolved(compiler);
548 break;
549 case AsyncMarker.ASYNC_STAR:
550 compiler.streamClass.ensureResolved(compiler);
551 break;
552 case AsyncMarker.SYNC_STAR:
553 compiler.iterableClass.ensureResolved(compiler);
554 break;
555 }
556 }
557 }
558
559 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) {
560 assert(classElement != null);
561 while (classElement != null) {
562 if (classElement.isNative) return true;
563 classElement = classElement.superclass;
564 }
565 return false;
566 }
567
568 TreeElements resolveMethodElementImplementation(
569 FunctionElement element, FunctionExpression tree) {
570 return compiler.withCurrentElement(element, () {
571 if (element.isExternal && tree.hasBody()) {
572 error(element,
573 MessageKind.EXTERNAL_WITH_BODY,
574 {'functionName': element.name});
575 }
576 if (element.isConstructor) {
577 if (tree.returnType != null) {
578 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE);
579 }
580 if (element.isConst &&
581 tree.hasBody() &&
582 !tree.isRedirectingFactory) {
583 error(tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY);
584 }
585 }
586
587 ResolverVisitor visitor = visitorFor(element);
588 ResolutionRegistry registry = visitor.registry;
589 registry.defineFunction(tree, element);
590 visitor.setupFunction(tree, element);
591 processAsyncMarker(compiler, element, registry);
592
593 if (element.isGenerativeConstructor) {
594 // Even if there is no initializer list we still have to do the
595 // resolution in case there is an implicit super constructor call.
596 InitializerResolver resolver = new InitializerResolver(visitor);
597 FunctionElement redirection =
598 resolver.resolveInitializers(element, tree);
599 if (redirection != null) {
600 resolveRedirectingConstructor(resolver, tree, element, redirection);
601 }
602 } else if (tree.initializers != null) {
603 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER);
604 }
605
606 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) {
607 // We need to analyze the redirecting factory bodies to ensure that
608 // we can analyze compile-time constants.
609 visitor.visit(tree.body);
610 }
611
612 // Get the resolution tree and check that the resolved
613 // function doesn't use 'super' if it is mixed into another
614 // class. This is the part of the 'super' mixin check that
615 // happens when a function is resolved after the mixin
616 // application has been performed.
617 TreeElements resolutionTree = registry.mapping;
618 ClassElement enclosingClass = element.enclosingClass;
619 if (enclosingClass != null) {
620 // TODO(johnniwinther): Find another way to obtain mixin uses.
621 Iterable<MixinApplicationElement> mixinUses =
622 compiler.world.allMixinUsesOf(enclosingClass);
623 ClassElement mixin = enclosingClass;
624 for (MixinApplicationElement mixinApplication in mixinUses) {
625 checkMixinSuperUses(resolutionTree, mixinApplication, mixin);
626 }
627 }
628
629 // TODO(9631): support noSuchMethod on native classes.
630 if (Elements.isInstanceMethod(element) &&
631 element.name == Compiler.NO_SUCH_METHOD &&
632 _isNativeClassOrExtendsNativeClass(enclosingClass)) {
633 error(tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE);
634 }
635
636 return resolutionTree;
637 });
638
639 }
640
641 TreeElements resolveMethodElement(FunctionElementX element) {
642 assert(invariant(element, element.isDeclaration));
643 return compiler.withCurrentElement(element, () {
644 if (compiler.enqueuer.resolution.hasBeenResolved(element)) {
645 // TODO(karlklose): Remove the check for [isConstructor]. [elememts]
646 // should never be non-null, not even for constructors.
647 assert(invariant(element, element.isConstructor,
648 message: 'Non-constructor element $element '
649 'has already been analyzed.'));
650 return element.resolvedAst.elements;
651 }
652 if (element.isSynthesized) {
653 if (element.isGenerativeConstructor) {
654 ResolutionRegistry registry =
655 new ResolutionRegistry(compiler, element);
656 ConstructorElement constructor = element.asFunctionElement();
657 ConstructorElement target = constructor.definingConstructor;
658 // Ensure the signature of the synthesized element is
659 // resolved. This is the only place where the resolver is
660 // seeing this element.
661 element.computeSignature(compiler);
662 if (!target.isErroneous) {
663 registry.registerStaticUse(target);
664 registry.registerImplicitSuperCall(target);
665 }
666 return registry.mapping;
667 } else {
668 assert(element.isDeferredLoaderGetter || element.isErroneous);
669 return _ensureTreeElements(element);
670 }
671 } else {
672 element.parseNode(compiler);
673 element.computeType(compiler);
674 FunctionElementX implementation = element;
675 if (element.isExternal) {
676 implementation = compiler.backend.resolveExternalFunction(element);
677 }
678 return resolveMethodElementImplementation(
679 implementation, implementation.node);
680 }
681 });
682 }
683
684 /// Creates a [ResolverVisitor] for resolving an AST in context of [element].
685 /// If [useEnclosingScope] is `true` then the initial scope of the visitor
686 /// does not include inner scope of [element].
687 ///
688 /// This method should only be used by this library (or tests of
689 /// this library).
690 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) {
691 return new ResolverVisitor(compiler, element,
692 new ResolutionRegistry(compiler, element),
693 useEnclosingScope: useEnclosingScope);
694 }
695
696 TreeElements resolveField(FieldElementX element) {
697 VariableDefinitions tree = element.parseNode(compiler);
698 if(element.modifiers.isStatic && element.isTopLevel) {
699 error(element.modifiers.getStatic(),
700 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC);
701 }
702 ResolverVisitor visitor = visitorFor(element);
703 ResolutionRegistry registry = visitor.registry;
704 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates
705 // to the backend ast.
706 registry.defineElement(tree.definitions.nodes.head, element);
707 // TODO(johnniwinther): Share the resolved type between all variables
708 // declared in the same declaration.
709 if (tree.type != null) {
710 element.variables.type = visitor.resolveTypeAnnotation(tree.type);
711 } else {
712 element.variables.type = const DynamicType();
713 }
714
715 Expression initializer = element.initializer;
716 Modifiers modifiers = element.modifiers;
717 if (initializer != null) {
718 // TODO(johnniwinther): Avoid analyzing initializers if
719 // [Compiler.analyzeSignaturesOnly] is set.
720 visitor.visit(initializer);
721 } else if (modifiers.isConst) {
722 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER);
723 } else if (modifiers.isFinal && !element.isInstanceMember) {
724 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER);
725 } else {
726 registry.registerInstantiatedClass(compiler.nullClass);
727 }
728
729 if (Elements.isStaticOrTopLevelField(element)) {
730 visitor.addDeferredAction(element, () {
731 if (element.modifiers.isConst) {
732 element.constant = constantCompiler.compileConstant(element);
733 } else {
734 constantCompiler.compileVariable(element);
735 }
736 });
737 if (initializer != null) {
738 if (!element.modifiers.isConst) {
739 // TODO(johnniwinther): Determine the const-ness eagerly to avoid
740 // unnecessary registrations.
741 registry.registerLazyField();
742 }
743 }
744 }
745
746 // Perform various checks as side effect of "computing" the type.
747 element.computeType(compiler);
748
749 return registry.mapping;
750 }
751
752 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) {
753 DartType type = resolveReturnType(element, annotation);
754 if (type.isVoid) {
755 error(annotation, MessageKind.VOID_NOT_ALLOWED);
756 }
757 return type;
758 }
759
760 DartType resolveReturnType(Element element, TypeAnnotation annotation) {
761 if (annotation == null) return const DynamicType();
762 DartType result = visitorFor(element).resolveTypeAnnotation(annotation);
763 if (result == null) {
764 // TODO(karklose): warning.
765 return const DynamicType();
766 }
767 return result;
768 }
769
770 void resolveRedirectionChain(ConstructorElementX constructor,
771 Spannable node) {
772 ConstructorElementX target = constructor;
773 InterfaceType targetType;
774 List<Element> seen = new List<Element>();
775 // Follow the chain of redirections and check for cycles.
776 while (target.isRedirectingFactory) {
777 if (target.internalEffectiveTarget != null) {
778 // We found a constructor that already has been processed.
779 targetType = target.effectiveTargetType;
780 assert(invariant(target, targetType != null,
781 message: 'Redirection target type has not been computed for '
782 '$target'));
783 target = target.internalEffectiveTarget;
784 break;
785 }
786
787 Element nextTarget = target.immediateRedirectionTarget;
788 if (seen.contains(nextTarget)) {
789 error(node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
790 targetType = target.enclosingClass.thisType;
791 break;
792 }
793 seen.add(target);
794 target = nextTarget;
795 }
796
797 if (targetType == null) {
798 assert(!target.isRedirectingFactory);
799 targetType = target.enclosingClass.thisType;
800 }
801
802 // [target] is now the actual target of the redirections. Run through
803 // the constructors again and set their [redirectionTarget], so that we
804 // do not have to run the loop for these constructors again. Furthermore,
805 // compute [redirectionTargetType] for each factory by computing the
806 // substitution of the target type with respect to the factory type.
807 while (!seen.isEmpty) {
808 ConstructorElementX factory = seen.removeLast();
809
810 // [factory] must already be analyzed but the [TreeElements] might not
811 // have been stored in the enqueuer cache yet.
812 // TODO(johnniwinther): Store [TreeElements] in the cache before
813 // resolution of the element.
814 TreeElements treeElements = factory.treeElements;
815 assert(invariant(node, treeElements != null,
816 message: 'No TreeElements cached for $factory.'));
817 FunctionExpression functionNode = factory.parseNode(compiler);
818 RedirectingFactoryBody redirectionNode = functionNode.body;
819 DartType factoryType = treeElements.getType(redirectionNode);
820 if (!factoryType.isDynamic) {
821 targetType = targetType.substByContext(factoryType);
822 }
823 factory.effectiveTarget = target;
824 factory.effectiveTargetType = targetType;
825 }
826 }
827
828 /**
829 * Load and resolve the supertypes of [cls].
830 *
831 * Warning: do not call this method directly. It should only be
832 * called by [resolveClass] and [ClassSupertypeResolver].
833 */
834 void loadSupertypes(BaseClassElementX cls, Spannable from) {
835 compiler.withCurrentElement(cls, () => measure(() {
836 if (cls.supertypeLoadState == STATE_DONE) return;
837 if (cls.supertypeLoadState == STATE_STARTED) {
838 compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY,
839 {'className': cls.name});
840 cls.supertypeLoadState = STATE_DONE;
841 cls.hasIncompleteHierarchy = true;
842 cls.allSupertypesAndSelf =
843 compiler.objectClass.allSupertypesAndSelf.extendClass(
844 cls.computeType(compiler));
845 cls.supertype = cls.allSupertypes.head;
846 assert(invariant(from, cls.supertype != null,
847 message: 'Missing supertype on cyclic class $cls.'));
848 cls.interfaces = const Link<DartType>();
849 return;
850 }
851 cls.supertypeLoadState = STATE_STARTED;
852 compiler.withCurrentElement(cls, () {
853 // TODO(ahe): Cache the node in cls.
854 cls.parseNode(compiler).accept(
855 new ClassSupertypeResolver(compiler, cls));
856 if (cls.supertypeLoadState != STATE_DONE) {
857 cls.supertypeLoadState = STATE_DONE;
858 }
859 });
860 }));
861 }
862
863 // TODO(johnniwinther): Remove this queue when resolution has been split into
864 // syntax and semantic resolution.
865 TypeDeclarationElement currentlyResolvedTypeDeclaration;
866 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
867 Queue<ClassElement> pendingClassesToBePostProcessed =
868 new Queue<ClassElement>();
869
870 /// Resolve [element] using [resolveTypeDeclaration].
871 ///
872 /// This methods ensure that class declarations encountered through type
873 /// annotations during the resolution of [element] are resolved after
874 /// [element] has been resolved.
875 // TODO(johnniwinther): Encapsulate this functionality in a
876 // 'TypeDeclarationResolver'.
877 _resolveTypeDeclaration(TypeDeclarationElement element,
878 resolveTypeDeclaration()) {
879 return compiler.withCurrentElement(element, () {
880 return measure(() {
881 TypeDeclarationElement previousResolvedTypeDeclaration =
882 currentlyResolvedTypeDeclaration;
883 currentlyResolvedTypeDeclaration = element;
884 var result = resolveTypeDeclaration();
885 if (previousResolvedTypeDeclaration == null) {
886 do {
887 while (!pendingClassesToBeResolved.isEmpty) {
888 pendingClassesToBeResolved.removeFirst().ensureResolved(compiler);
889 }
890 while (!pendingClassesToBePostProcessed.isEmpty) {
891 _postProcessClassElement(
892 pendingClassesToBePostProcessed.removeFirst());
893 }
894 } while (!pendingClassesToBeResolved.isEmpty);
895 assert(pendingClassesToBeResolved.isEmpty);
896 assert(pendingClassesToBePostProcessed.isEmpty);
897 }
898 currentlyResolvedTypeDeclaration = previousResolvedTypeDeclaration;
899 return result;
900 });
901 });
902 }
903
904 /**
905 * Resolve the class [element].
906 *
907 * Before calling this method, [element] was constructed by the
908 * scanner and most fields are null or empty. This method fills in
909 * these fields and also ensure that the supertypes of [element] are
910 * resolved.
911 *
912 * Warning: Do not call this method directly. Instead use
913 * [:element.ensureResolved(compiler):].
914 */
915 TreeElements resolveClass(BaseClassElementX element) {
916 return _resolveTypeDeclaration(element, () {
917 // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
918 ResolutionRegistry registry = new ResolutionRegistry(compiler, element);
919 resolveClassInternal(element, registry);
920 return element.treeElements;
921 });
922 }
923
924 void _ensureClassWillBeResolved(ClassElement element) {
925 if (currentlyResolvedTypeDeclaration == null) {
926 element.ensureResolved(compiler);
927 } else {
928 pendingClassesToBeResolved.add(element);
929 }
930 }
931
932 void resolveClassInternal(BaseClassElementX element,
933 ResolutionRegistry registry) {
934 if (!element.isPatch) {
935 compiler.withCurrentElement(element, () => measure(() {
936 assert(element.resolutionState == STATE_NOT_STARTED);
937 element.resolutionState = STATE_STARTED;
938 Node tree = element.parseNode(compiler);
939 loadSupertypes(element, tree);
940
941 ClassResolverVisitor visitor =
942 new ClassResolverVisitor(compiler, element, registry);
943 visitor.visit(tree);
944 element.resolutionState = STATE_DONE;
945 compiler.onClassResolved(element);
946 pendingClassesToBePostProcessed.add(element);
947 }));
948 if (element.isPatched) {
949 // Ensure handling patch after origin.
950 element.patch.ensureResolved(compiler);
951 }
952 } else { // Handle patch classes:
953 element.resolutionState = STATE_STARTED;
954 // Ensure handling origin before patch.
955 element.origin.ensureResolved(compiler);
956 // Ensure that the type is computed.
957 element.computeType(compiler);
958 // Copy class hierarchy from origin.
959 element.supertype = element.origin.supertype;
960 element.interfaces = element.origin.interfaces;
961 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf;
962 // Stepwise assignment to ensure invariant.
963 element.supertypeLoadState = STATE_STARTED;
964 element.supertypeLoadState = STATE_DONE;
965 element.resolutionState = STATE_DONE;
966 // TODO(johnniwinther): Check matching type variables and
967 // empty extends/implements clauses.
968 }
969 }
970
971 void _postProcessClassElement(BaseClassElementX element) {
972 for (MetadataAnnotation metadata in element.metadata) {
973 metadata.ensureResolved(compiler);
974 if (!element.isProxy &&
975 metadata.constant.value == compiler.proxyConstant) {
976 element.isProxy = true;
977 }
978 }
979
980 // Force resolution of metadata on non-instance members since they may be
981 // inspected by the backend while emitting. Metadata on instance members is
982 // handled as a result of processing instantiated class members in the
983 // enqueuer.
984 // TODO(ahe): Avoid this eager resolution.
985 element.forEachMember((_, Element member) {
986 if (!member.isInstanceMember) {
987 compiler.withCurrentElement(member, () {
988 for (MetadataAnnotation metadata in member.metadata) {
989 metadata.ensureResolved(compiler);
990 }
991 });
992 }
993 });
994
995 computeClassMember(element, Compiler.CALL_OPERATOR_NAME);
996 }
997
998 void computeClassMembers(ClassElement element) {
999 MembersCreator.computeAllClassMembers(compiler, element);
1000 }
1001
1002 void computeClassMember(ClassElement element, String name) {
1003 MembersCreator.computeClassMembersByName(compiler, element, name);
1004 }
1005
1006 void checkClass(ClassElement element) {
1007 computeClassMembers(element);
1008 if (element.isMixinApplication) {
1009 checkMixinApplication(element);
1010 } else {
1011 checkClassMembers(element);
1012 }
1013 }
1014
1015 void checkMixinApplication(MixinApplicationElementX mixinApplication) {
1016 Modifiers modifiers = mixinApplication.modifiers;
1017 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT;
1018 if (illegalFlags != 0) {
1019 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags);
1020 compiler.reportError(
1021 modifiers,
1022 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS,
1023 {'modifiers': illegalModifiers});
1024 }
1025
1026 // In case of cyclic mixin applications, the mixin chain will have
1027 // been cut. If so, we have already reported the error to the
1028 // user so we just return from here.
1029 ClassElement mixin = mixinApplication.mixin;
1030 if (mixin == null) return;
1031
1032 // Check that we're not trying to use Object as a mixin.
1033 if (mixin.superclass == null) {
1034 compiler.reportError(mixinApplication,
1035 MessageKind.ILLEGAL_MIXIN_OBJECT);
1036 // Avoid reporting additional errors for the Object class.
1037 return;
1038 }
1039
1040 if (mixin.isEnumClass) {
1041 // Mixing in an enum has already caused a compile-time error.
1042 return;
1043 }
1044
1045 // Check that the mixed in class has Object as its superclass.
1046 if (!mixin.superclass.isObject) {
1047 compiler.reportError(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS);
1048 }
1049
1050 // Check that the mixed in class doesn't have any constructors and
1051 // make sure we aren't mixing in methods that use 'super'.
1052 mixin.forEachLocalMember((AstElement member) {
1053 if (member.isGenerativeConstructor && !member.isSynthesized) {
1054 compiler.reportError(member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR);
1055 } else {
1056 // Get the resolution tree and check that the resolved member
1057 // doesn't use 'super'. This is the part of the 'super' mixin
1058 // check that happens when a function is resolved before the
1059 // mixin application has been performed.
1060 // TODO(johnniwinther): Obtain the [TreeElements] for [member]
1061 // differently.
1062 if (compiler.enqueuer.resolution.hasBeenResolved(member)) {
1063 checkMixinSuperUses(
1064 member.resolvedAst.elements,
1065 mixinApplication,
1066 mixin);
1067 }
1068 }
1069 });
1070 }
1071
1072 void checkMixinSuperUses(TreeElements resolutionTree,
1073 MixinApplicationElement mixinApplication,
1074 ClassElement mixin) {
1075 // TODO(johnniwinther): Avoid the use of [TreeElements] here.
1076 if (resolutionTree == null) return;
1077 Iterable<Node> superUses = resolutionTree.superUses;
1078 if (superUses.isEmpty) return;
1079 compiler.reportError(mixinApplication,
1080 MessageKind.ILLEGAL_MIXIN_WITH_SUPER,
1081 {'className': mixin.name});
1082 // Show the user the problematic uses of 'super' in the mixin.
1083 for (Node use in superUses) {
1084 compiler.reportInfo(
1085 use,
1086 MessageKind.ILLEGAL_MIXIN_SUPER_USE);
1087 }
1088 }
1089
1090 void checkClassMembers(ClassElement cls) {
1091 assert(invariant(cls, cls.isDeclaration));
1092 if (cls.isObject) return;
1093 // TODO(johnniwinther): Should this be done on the implementation element as
1094 // well?
1095 List<Element> constConstructors = <Element>[];
1096 List<Element> nonFinalInstanceFields = <Element>[];
1097 cls.forEachMember((holder, member) {
1098 compiler.withCurrentElement(member, () {
1099 // Perform various checks as side effect of "computing" the type.
1100 member.computeType(compiler);
1101
1102 // Check modifiers.
1103 if (member.isFunction && member.modifiers.isFinal) {
1104 compiler.reportError(
1105 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER);
1106 }
1107 if (member.isConstructor) {
1108 final mismatchedFlagsBits =
1109 member.modifiers.flags &
1110 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT);
1111 if (mismatchedFlagsBits != 0) {
1112 final mismatchedFlags =
1113 new Modifiers.withFlags(null, mismatchedFlagsBits);
1114 compiler.reportError(
1115 member,
1116 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS,
1117 {'modifiers': mismatchedFlags});
1118 }
1119 if (member.modifiers.isConst) {
1120 constConstructors.add(member);
1121 }
1122 }
1123 if (member.isField) {
1124 if (member.modifiers.isConst && !member.modifiers.isStatic) {
1125 compiler.reportError(
1126 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER);
1127 }
1128 if (!member.modifiers.isStatic && !member.modifiers.isFinal) {
1129 nonFinalInstanceFields.add(member);
1130 }
1131 }
1132 checkAbstractField(member);
1133 checkUserDefinableOperator(member);
1134 });
1135 });
1136 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) {
1137 Spannable span = constConstructors.length > 1
1138 ? cls : constConstructors[0];
1139 compiler.reportError(span,
1140 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
1141 {'className': cls.name});
1142 if (constConstructors.length > 1) {
1143 for (Element constructor in constConstructors) {
1144 compiler.reportInfo(constructor,
1145 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR);
1146 }
1147 }
1148 for (Element field in nonFinalInstanceFields) {
1149 compiler.reportInfo(field,
1150 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD);
1151 }
1152 }
1153 }
1154
1155 void checkAbstractField(Element member) {
1156 // Only check for getters. The test can only fail if there is both a setter
1157 // and a getter with the same name, and we only need to check each abstract
1158 // field once, so we just ignore setters.
1159 if (!member.isGetter) return;
1160
1161 // Find the associated abstract field.
1162 ClassElement classElement = member.enclosingClass;
1163 Element lookupElement = classElement.lookupLocalMember(member.name);
1164 if (lookupElement == null) {
1165 compiler.internalError(member,
1166 "No abstract field for accessor");
1167 } else if (!identical(lookupElement.kind, ElementKind.ABSTRACT_FIELD)) {
1168 if (lookupElement.isErroneous || lookupElement.isAmbiguous) return;
1169 compiler.internalError(member,
1170 "Inaccessible abstract field for accessor");
1171 }
1172 AbstractFieldElement field = lookupElement;
1173
1174 MethodElementX getter = field.getter;
1175 if (getter == null) return;
1176 MethodElementX setter = field.setter;
1177 if (setter == null) return;
1178 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
1179 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
1180 if (!identical(getterFlags, setterFlags)) {
1181 final mismatchedFlags =
1182 new Modifiers.withFlags(null, getterFlags ^ setterFlags);
1183 compiler.reportError(
1184 field.getter,
1185 MessageKind.GETTER_MISMATCH,
1186 {'modifiers': mismatchedFlags});
1187 compiler.reportError(
1188 field.setter,
1189 MessageKind.SETTER_MISMATCH,
1190 {'modifiers': mismatchedFlags});
1191 }
1192 }
1193
1194 void checkUserDefinableOperator(Element member) {
1195 FunctionElement function = member.asFunctionElement();
1196 if (function == null) return;
1197 String value = member.name;
1198 if (value == null) return;
1199 if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return;
1200
1201 bool isMinus = false;
1202 int requiredParameterCount;
1203 MessageKind messageKind;
1204 if (identical(value, 'unary-')) {
1205 isMinus = true;
1206 messageKind = MessageKind.MINUS_OPERATOR_BAD_ARITY;
1207 requiredParameterCount = 0;
1208 } else if (isMinusOperator(value)) {
1209 isMinus = true;
1210 messageKind = MessageKind.MINUS_OPERATOR_BAD_ARITY;
1211 requiredParameterCount = 1;
1212 } else if (isUnaryOperator(value)) {
1213 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY;
1214 requiredParameterCount = 0;
1215 } else if (isBinaryOperator(value)) {
1216 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY;
1217 requiredParameterCount = 1;
1218 if (identical(value, '==')) checkOverrideHashCode(member);
1219 } else if (isTernaryOperator(value)) {
1220 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY;
1221 requiredParameterCount = 2;
1222 } else {
1223 compiler.internalError(function,
1224 'Unexpected user defined operator $value');
1225 }
1226 checkArity(function, requiredParameterCount, messageKind, isMinus);
1227 }
1228
1229 void checkOverrideHashCode(FunctionElement operatorEquals) {
1230 if (operatorEquals.isAbstract) return;
1231 ClassElement cls = operatorEquals.enclosingClass;
1232 Element hashCodeImplementation =
1233 cls.lookupLocalMember('hashCode');
1234 if (hashCodeImplementation != null) return;
1235 compiler.reportHint(
1236 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE,
1237 {'class': cls.name});
1238 }
1239
1240 void checkArity(FunctionElement function,
1241 int requiredParameterCount, MessageKind messageKind,
1242 bool isMinus) {
1243 FunctionExpression node = function.node;
1244 FunctionSignature signature = function.functionSignature;
1245 if (signature.requiredParameterCount != requiredParameterCount) {
1246 Node errorNode = node;
1247 if (node.parameters != null) {
1248 if (isMinus ||
1249 signature.requiredParameterCount < requiredParameterCount) {
1250 // If there are too few parameters, point to the whole parameter list.
1251 // For instance
1252 //
1253 // int operator +() {}
1254 // ^^
1255 //
1256 // int operator []=(value) {}
1257 // ^^^^^^^
1258 //
1259 // For operator -, always point the whole parameter list, like
1260 //
1261 // int operator -(a, b) {}
1262 // ^^^^^^
1263 //
1264 // instead of
1265 //
1266 // int operator -(a, b) {}
1267 // ^
1268 //
1269 // since the correction might not be to remove 'b' but instead to
1270 // remove 'a, b'.
1271 errorNode = node.parameters;
1272 } else {
1273 errorNode = node.parameters.nodes.skip(requiredParameterCount).head;
1274 }
1275 }
1276 compiler.reportError(
1277 errorNode, messageKind, {'operatorName': function.name});
1278 }
1279 if (signature.optionalParameterCount != 0) {
1280 Node errorNode =
1281 node.parameters.nodes.skip(signature.requiredParameterCount).head;
1282 if (signature.optionalParametersAreNamed) {
1283 compiler.reportError(
1284 errorNode,
1285 MessageKind.OPERATOR_NAMED_PARAMETERS,
1286 {'operatorName': function.name});
1287 } else {
1288 compiler.reportError(
1289 errorNode,
1290 MessageKind.OPERATOR_OPTIONAL_PARAMETERS,
1291 {'operatorName': function.name});
1292 }
1293 }
1294 }
1295
1296 reportErrorWithContext(Element errorneousElement,
1297 MessageKind errorMessage,
1298 Element contextElement,
1299 MessageKind contextMessage) {
1300 compiler.reportError(
1301 errorneousElement,
1302 errorMessage,
1303 {'memberName': contextElement.name,
1304 'className': contextElement.enclosingClass.name});
1305 compiler.reportInfo(contextElement, contextMessage);
1306 }
1307
1308
1309 FunctionSignature resolveSignature(FunctionElementX element) {
1310 MessageKind defaultValuesError = null;
1311 if (element.isFactoryConstructor) {
1312 FunctionExpression body = element.parseNode(compiler);
1313 if (body.isRedirectingFactory) {
1314 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT;
1315 }
1316 }
1317 return compiler.withCurrentElement(element, () {
1318 FunctionExpression node =
1319 compiler.parser.measure(() => element.parseNode(compiler));
1320 return measure(() => SignatureResolver.analyze(
1321 compiler, node.parameters, node.returnType, element,
1322 new ResolutionRegistry(compiler, element),
1323 defaultValuesError: defaultValuesError,
1324 createRealParameters: true));
1325 });
1326 }
1327
1328 TreeElements resolveTypedef(TypedefElementX element) {
1329 if (element.isResolved) return element.treeElements;
1330 compiler.world.allTypedefs.add(element);
1331 return _resolveTypeDeclaration(element, () {
1332 ResolutionRegistry registry = new ResolutionRegistry(compiler, element);
1333 return compiler.withCurrentElement(element, () {
1334 return measure(() {
1335 assert(element.resolutionState == STATE_NOT_STARTED);
1336 element.resolutionState = STATE_STARTED;
1337 Typedef node =
1338 compiler.parser.measure(() => element.parseNode(compiler));
1339 TypedefResolverVisitor visitor =
1340 new TypedefResolverVisitor(compiler, element, registry);
1341 visitor.visit(node);
1342 element.resolutionState = STATE_DONE;
1343 return registry.mapping;
1344 });
1345 });
1346 });
1347 }
1348
1349 void resolveMetadataAnnotation(MetadataAnnotationX annotation) {
1350 compiler.withCurrentElement(annotation.annotatedElement, () => measure(() {
1351 assert(annotation.resolutionState == STATE_NOT_STARTED);
1352 annotation.resolutionState = STATE_STARTED;
1353
1354 Node node = annotation.parseNode(compiler);
1355 Element annotatedElement = annotation.annotatedElement;
1356 AnalyzableElement context = annotatedElement.analyzableElement;
1357 ClassElement classElement = annotatedElement.enclosingClass;
1358 if (classElement != null) {
1359 // The annotation is resolved in the scope of [classElement].
1360 classElement.ensureResolved(compiler);
1361 }
1362 assert(invariant(node, context != null,
1363 message: "No context found for metadata annotation "
1364 "on $annotatedElement."));
1365 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true);
1366 ResolutionRegistry registry = visitor.registry;
1367 node.accept(visitor);
1368 // TODO(johnniwinther): Avoid passing the [TreeElements] to
1369 // [compileMetadata].
1370 annotation.constant =
1371 constantCompiler.compileMetadata(annotation, node, registry.mapping);
1372 // TODO(johnniwinther): Register the relation between the annotation
1373 // and the annotated element instead. This will allow the backend to
1374 // retrieve the backend constant and only register metadata on the
1375 // elements for which it is needed. (Issue 17732).
1376 registry.registerMetadataConstant(annotation, annotatedElement);
1377 annotation.resolutionState = STATE_DONE;
1378 }));
1379 }
1380
1381 error(Spannable node, MessageKind kind, [arguments = const {}]) {
1382 compiler.reportError(node, kind, arguments);
1383 }
1384
1385 Link<MetadataAnnotation> resolveMetadata(Element element,
1386 VariableDefinitions node) {
1387 LinkBuilder<MetadataAnnotation> metadata =
1388 new LinkBuilder<MetadataAnnotation>();
1389 for (Metadata annotation in node.metadata.nodes) {
1390 ParameterMetadataAnnotation metadataAnnotation =
1391 new ParameterMetadataAnnotation(annotation);
1392 metadataAnnotation.annotatedElement = element;
1393 metadata.addLast(metadataAnnotation.ensureResolved(compiler));
1394 }
1395 return metadata.toLink();
1396 }
1397 }
1398
1399 class InitializerResolver {
1400 final ResolverVisitor visitor;
1401 final Map<Element, Node> initialized;
1402 Link<Node> initializers;
1403 bool hasSuper;
1404
1405 InitializerResolver(this.visitor)
1406 : initialized = new Map<Element, Node>(), hasSuper = false;
1407
1408 ResolutionRegistry get registry => visitor.registry;
1409
1410 error(Node node, MessageKind kind, [arguments = const {}]) {
1411 visitor.error(node, kind, arguments);
1412 }
1413
1414 warning(Node node, MessageKind kind, [arguments = const {}]) {
1415 visitor.warning(node, kind, arguments);
1416 }
1417
1418 bool isFieldInitializer(SendSet node) {
1419 if (node.selector.asIdentifier() == null) return false;
1420 if (node.receiver == null) return true;
1421 if (node.receiver.asIdentifier() == null) return false;
1422 return node.receiver.asIdentifier().isThis();
1423 }
1424
1425 reportDuplicateInitializerError(Element field, Node init, Node existing) {
1426 visitor.compiler.reportError(
1427 init,
1428 MessageKind.DUPLICATE_INITIALIZER, {'fieldName': field.name});
1429 visitor.compiler.reportInfo(
1430 existing,
1431 MessageKind.ALREADY_INITIALIZED, {'fieldName': field.name});
1432 }
1433
1434 void checkForDuplicateInitializers(FieldElementX field, Node init) {
1435 // [field] can be null if it could not be resolved.
1436 if (field == null) return;
1437 String name = field.name;
1438 if (initialized.containsKey(field)) {
1439 reportDuplicateInitializerError(field, init, initialized[field]);
1440 } else if (field.isFinal) {
1441 field.parseNode(visitor.compiler);
1442 Expression initializer = field.initializer;
1443 if (initializer != null) {
1444 reportDuplicateInitializerError(field, init, initializer);
1445 }
1446 }
1447 initialized[field] = init;
1448 }
1449
1450 void resolveFieldInitializer(FunctionElement constructor, SendSet init) {
1451 // init is of the form [this.]field = value.
1452 final Node selector = init.selector;
1453 final String name = selector.asIdentifier().source;
1454 // Lookup target field.
1455 Element target;
1456 if (isFieldInitializer(init)) {
1457 target = constructor.enclosingClass.lookupLocalMember(name);
1458 if (target == null) {
1459 error(selector, MessageKind.CANNOT_RESOLVE, {'name': name});
1460 target = new ErroneousFieldElementX(
1461 selector.asIdentifier(), constructor.enclosingClass);
1462 } else if (target.kind != ElementKind.FIELD) {
1463 error(selector, MessageKind.NOT_A_FIELD, {'fieldName': name});
1464 target = new ErroneousFieldElementX(
1465 selector.asIdentifier(), constructor.enclosingClass);
1466 } else if (!target.isInstanceMember) {
1467 error(selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name});
1468 }
1469 } else {
1470 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
1471 }
1472 registry.useElement(init, target);
1473 registry.registerStaticUse(target);
1474 checkForDuplicateInitializers(target, init);
1475 // Resolve initializing value.
1476 visitor.visitInStaticContext(init.arguments.head);
1477 }
1478
1479 ClassElement getSuperOrThisLookupTarget(FunctionElement constructor,
1480 bool isSuperCall,
1481 Node diagnosticNode) {
1482 ClassElement lookupTarget = constructor.enclosingClass;
1483 if (isSuperCall) {
1484 // Calculate correct lookup target and constructor name.
1485 if (identical(lookupTarget, visitor.compiler.objectClass)) {
1486 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
1487 } else {
1488 return lookupTarget.supertype.element;
1489 }
1490 }
1491 return lookupTarget;
1492 }
1493
1494 Element resolveSuperOrThisForSend(FunctionElement constructor,
1495 FunctionExpression functionNode,
1496 Send call) {
1497 // Resolve the selector and the arguments.
1498 ResolverTask resolver = visitor.compiler.resolver;
1499 visitor.inStaticContext(() {
1500 visitor.resolveSelector(call, null);
1501 visitor.resolveArguments(call.argumentsNode);
1502 });
1503 Selector selector = registry.getSelector(call);
1504 bool isSuperCall = Initializers.isSuperConstructorCall(call);
1505
1506 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
1507 isSuperCall,
1508 call);
1509 Selector constructorSelector =
1510 visitor.getRedirectingThisOrSuperConstructorSelector(call);
1511 FunctionElement calledConstructor =
1512 lookupTarget.lookupConstructor(constructorSelector.name);
1513
1514 final bool isImplicitSuperCall = false;
1515 final String className = lookupTarget.name;
1516 verifyThatConstructorMatchesCall(constructor,
1517 calledConstructor,
1518 selector.callStructure,
1519 isImplicitSuperCall,
1520 call,
1521 className,
1522 constructorSelector);
1523
1524 registry.useElement(call, calledConstructor);
1525 registry.registerStaticUse(calledConstructor);
1526 return calledConstructor;
1527 }
1528
1529 void resolveImplicitSuperConstructorSend(FunctionElement constructor,
1530 FunctionExpression functionNode) {
1531 // If the class has a super resolve the implicit super call.
1532 ClassElement classElement = constructor.enclosingClass;
1533 ClassElement superClass = classElement.superclass;
1534 if (classElement != visitor.compiler.objectClass) {
1535 assert(superClass != null);
1536 assert(superClass.resolutionState == STATE_DONE);
1537
1538 final bool isSuperCall = true;
1539 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor,
1540 isSuperCall,
1541 functionNode);
1542 Selector constructorSelector = new Selector.callDefaultConstructor();
1543 Element calledConstructor = lookupTarget.lookupConstructor(
1544 constructorSelector.name);
1545
1546 final String className = lookupTarget.name;
1547 final bool isImplicitSuperCall = true;
1548 verifyThatConstructorMatchesCall(constructor,
1549 calledConstructor,
1550 CallStructure.NO_ARGS,
1551 isImplicitSuperCall,
1552 functionNode,
1553 className,
1554 constructorSelector);
1555 registry.registerImplicitSuperCall(calledConstructor);
1556 registry.registerStaticUse(calledConstructor);
1557 }
1558 }
1559
1560 void verifyThatConstructorMatchesCall(
1561 FunctionElement caller,
1562 ConstructorElementX lookedupConstructor,
1563 CallStructure call,
1564 bool isImplicitSuperCall,
1565 Node diagnosticNode,
1566 String className,
1567 Selector constructorSelector) {
1568 if (lookedupConstructor == null
1569 || !lookedupConstructor.isGenerativeConstructor) {
1570 String fullConstructorName = Elements.constructorNameForDiagnostics(
1571 className,
1572 constructorSelector.name);
1573 MessageKind kind = isImplicitSuperCall
1574 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
1575 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
1576 visitor.compiler.reportError(
1577 diagnosticNode, kind, {'constructorName': fullConstructorName});
1578 } else {
1579 lookedupConstructor.computeSignature(visitor.compiler);
1580 if (!call.signatureApplies(lookedupConstructor)) {
1581 MessageKind kind = isImplicitSuperCall
1582 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
1583 : MessageKind.NO_MATCHING_CONSTRUCTOR;
1584 visitor.compiler.reportError(diagnosticNode, kind);
1585 } else if (caller.isConst
1586 && !lookedupConstructor.isConst) {
1587 visitor.compiler.reportError(
1588 diagnosticNode, MessageKind.CONST_CALLS_NON_CONST);
1589 }
1590 }
1591 }
1592
1593 /**
1594 * Resolve all initializers of this constructor. In the case of a redirecting
1595 * constructor, the resolved constructor's function element is returned.
1596 */
1597 ConstructorElement resolveInitializers(ConstructorElementX constructor,
1598 FunctionExpression functionNode) {
1599 // Keep track of all "this.param" parameters specified for constructor so
1600 // that we can ensure that fields are initialized only once.
1601 FunctionSignature functionParameters = constructor.functionSignature;
1602 functionParameters.forEachParameter((ParameterElement element) {
1603 if (element.isInitializingFormal) {
1604 InitializingFormalElement initializingFormal = element;
1605 checkForDuplicateInitializers(initializingFormal.fieldElement,
1606 element.initializer);
1607 }
1608 });
1609
1610 if (functionNode.initializers == null) {
1611 initializers = const Link<Node>();
1612 } else {
1613 initializers = functionNode.initializers.nodes;
1614 }
1615 bool resolvedSuper = false;
1616 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) {
1617 if (link.head.asSendSet() != null) {
1618 final SendSet init = link.head.asSendSet();
1619 resolveFieldInitializer(constructor, init);
1620 } else if (link.head.asSend() != null) {
1621 final Send call = link.head.asSend();
1622 if (call.argumentsNode == null) {
1623 error(link.head, MessageKind.INVALID_INITIALIZER);
1624 continue;
1625 }
1626 if (Initializers.isSuperConstructorCall(call)) {
1627 if (resolvedSuper) {
1628 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER);
1629 }
1630 resolveSuperOrThisForSend(constructor, functionNode, call);
1631 resolvedSuper = true;
1632 } else if (Initializers.isConstructorRedirect(call)) {
1633 // Check that there is no body (Language specification 7.5.1). If the
1634 // constructor is also const, we already reported an error in
1635 // [resolveMethodElement].
1636 if (functionNode.hasBody() && !constructor.isConst) {
1637 error(functionNode, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY);
1638 }
1639 // Check that there are no other initializers.
1640 if (!initializers.tail.isEmpty) {
1641 error(call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER);
1642 } else {
1643 constructor.isRedirectingGenerative = true;
1644 }
1645 // Check that there are no field initializing parameters.
1646 Compiler compiler = visitor.compiler;
1647 FunctionSignature signature = constructor.functionSignature;
1648 signature.forEachParameter((ParameterElement parameter) {
1649 if (parameter.isInitializingFormal) {
1650 Node node = parameter.node;
1651 error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED);
1652 }
1653 });
1654 return resolveSuperOrThisForSend(constructor, functionNode, call);
1655 } else {
1656 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED);
1657 return null;
1658 }
1659 } else {
1660 error(link.head, MessageKind.INVALID_INITIALIZER);
1661 }
1662 }
1663 if (!resolvedSuper) {
1664 resolveImplicitSuperConstructorSend(constructor, functionNode);
1665 }
1666 return null; // If there was no redirection always return null.
1667 }
1668 }
1669
1670 class CommonResolverVisitor<R> extends Visitor<R> {
1671 final Compiler compiler;
1672
1673 CommonResolverVisitor(Compiler this.compiler);
1674
1675 R visitNode(Node node) {
1676 internalError(node,
1677 'internal error: Unhandled node: ${node.getObjectDescription()}');
1678 return null;
1679 }
1680
1681 R visitEmptyStatement(Node node) => null;
1682
1683 /** Convenience method for visiting nodes that may be null. */
1684 R visit(Node node) => (node == null) ? null : node.accept(this);
1685
1686 void error(Spannable node, MessageKind kind, [Map arguments = const {}]) {
1687 compiler.reportError(node, kind, arguments);
1688 }
1689
1690 void warning(Spannable node, MessageKind kind, [Map arguments = const {}]) {
1691 compiler.reportWarning(node, kind, arguments);
1692 }
1693
1694 void internalError(Spannable node, message) {
1695 compiler.internalError(node, message);
1696 }
1697
1698 void addDeferredAction(Element element, DeferredAction action) {
1699 compiler.enqueuer.resolution.addDeferredAction(element, action);
1700 }
1701 }
1702
1703 abstract class LabelScope {
1704 LabelScope get outer;
1705 LabelDefinition lookup(String label);
1706 }
1707
1708 class LabeledStatementLabelScope implements LabelScope {
1709 final LabelScope outer;
1710 final Map<String, LabelDefinition> labels;
1711 LabeledStatementLabelScope(this.outer, this.labels);
1712 LabelDefinition lookup(String labelName) {
1713 LabelDefinition label = labels[labelName];
1714 if (label != null) return label;
1715 return outer.lookup(labelName);
1716 }
1717 }
1718
1719 class SwitchLabelScope implements LabelScope {
1720 final LabelScope outer;
1721 final Map<String, LabelDefinition> caseLabels;
1722
1723 SwitchLabelScope(this.outer, this.caseLabels);
1724
1725 LabelDefinition lookup(String labelName) {
1726 LabelDefinition result = caseLabels[labelName];
1727 if (result != null) return result;
1728 return outer.lookup(labelName);
1729 }
1730 }
1731
1732 class EmptyLabelScope implements LabelScope {
1733 const EmptyLabelScope();
1734 LabelDefinition lookup(String label) => null;
1735 LabelScope get outer {
1736 throw 'internal error: empty label scope has no outer';
1737 }
1738 }
1739
1740 class StatementScope {
1741 LabelScope labels;
1742 Link<JumpTarget> breakTargetStack;
1743 Link<JumpTarget> continueTargetStack;
1744 // Used to provide different numbers to statements if one is inside the other.
1745 // Can be used to make otherwise duplicate labels unique.
1746 int nestingLevel = 0;
1747
1748 StatementScope()
1749 : labels = const EmptyLabelScope(),
1750 breakTargetStack = const Link<JumpTarget>(),
1751 continueTargetStack = const Link<JumpTarget>();
1752
1753 LabelDefinition lookupLabel(String label) {
1754 return labels.lookup(label);
1755 }
1756
1757 JumpTarget currentBreakTarget() =>
1758 breakTargetStack.isEmpty ? null : breakTargetStack.head;
1759
1760 JumpTarget currentContinueTarget() =>
1761 continueTargetStack.isEmpty ? null : continueTargetStack.head;
1762
1763 void enterLabelScope(Map<String, LabelDefinition> elements) {
1764 labels = new LabeledStatementLabelScope(labels, elements);
1765 nestingLevel++;
1766 }
1767
1768 void exitLabelScope() {
1769 nestingLevel--;
1770 labels = labels.outer;
1771 }
1772
1773 void enterLoop(JumpTarget element) {
1774 breakTargetStack = breakTargetStack.prepend(element);
1775 continueTargetStack = continueTargetStack.prepend(element);
1776 nestingLevel++;
1777 }
1778
1779 void exitLoop() {
1780 nestingLevel--;
1781 breakTargetStack = breakTargetStack.tail;
1782 continueTargetStack = continueTargetStack.tail;
1783 }
1784
1785 void enterSwitch(JumpTarget breakElement,
1786 Map<String, LabelDefinition> continueElements) {
1787 breakTargetStack = breakTargetStack.prepend(breakElement);
1788 labels = new SwitchLabelScope(labels, continueElements);
1789 nestingLevel++;
1790 }
1791
1792 void exitSwitch() {
1793 nestingLevel--;
1794 breakTargetStack = breakTargetStack.tail;
1795 labels = labels.outer;
1796 }
1797 }
1798
1799 class TypeResolver {
1800 final Compiler compiler;
1801
1802 TypeResolver(this.compiler);
1803
1804 /// Tries to resolve the type name as an element.
1805 Element resolveTypeName(Identifier prefixName,
1806 Identifier typeName,
1807 Scope scope,
1808 {bool deferredIsMalformed: true}) {
1809 Element element;
1810 bool deferredTypeAnnotation = false;
1811 if (prefixName != null) {
1812 Element prefixElement =
1813 lookupInScope(compiler, prefixName, scope, prefixName.source);
1814 if (prefixElement != null && prefixElement.isPrefix) {
1815 // The receiver is a prefix. Lookup in the imported members.
1816 PrefixElement prefix = prefixElement;
1817 element = prefix.lookupLocalMember(typeName.source);
1818 // TODO(17260, sigurdm): The test for DartBackend is there because
1819 // dart2dart outputs malformed types with prefix.
1820 if (element != null &&
1821 prefix.isDeferred &&
1822 deferredIsMalformed &&
1823 compiler.backend is! DartBackend) {
1824 element = new ErroneousElementX(MessageKind.DEFERRED_TYPE_ANNOTATION,
1825 {'node': typeName},
1826 element.name,
1827 element);
1828 }
1829 } else {
1830 // The caller of this method will create the ErroneousElement for
1831 // the MalformedType.
1832 element = null;
1833 }
1834 } else {
1835 String stringValue = typeName.source;
1836 element = lookupInScope(compiler, typeName, scope, typeName.source);
1837 }
1838 return element;
1839 }
1840
1841 DartType resolveTypeAnnotation(MappingVisitor visitor, TypeAnnotation node,
1842 {bool malformedIsError: false,
1843 bool deferredIsMalformed: true}) {
1844 ResolutionRegistry registry = visitor.registry;
1845
1846 Identifier typeName;
1847 DartType type;
1848
1849 DartType checkNoTypeArguments(DartType type) {
1850 List<DartType> arguments = new List<DartType>();
1851 bool hasTypeArgumentMismatch = resolveTypeArguments(
1852 visitor, node, const <DartType>[], arguments);
1853 if (hasTypeArgumentMismatch) {
1854 return new MalformedType(
1855 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
1856 {'type': node}, typeName.source, visitor.enclosingElement),
1857 type, arguments);
1858 }
1859 return type;
1860 }
1861
1862 Identifier prefixName;
1863 Send send = node.typeName.asSend();
1864 if (send != null) {
1865 // The type name is of the form [: prefix . identifier :].
1866 prefixName = send.receiver.asIdentifier();
1867 typeName = send.selector.asIdentifier();
1868 } else {
1869 typeName = node.typeName.asIdentifier();
1870 if (identical(typeName.source, 'void')) {
1871 type = const VoidType();
1872 checkNoTypeArguments(type);
1873 registry.useType(node, type);
1874 return type;
1875 } else if (identical(typeName.source, 'dynamic')) {
1876 type = const DynamicType();
1877 checkNoTypeArguments(type);
1878 registry.useType(node, type);
1879 return type;
1880 }
1881 }
1882
1883 Element element = resolveTypeName(prefixName, typeName, visitor.scope,
1884 deferredIsMalformed: deferredIsMalformed);
1885
1886 DartType reportFailureAndCreateType(MessageKind messageKind,
1887 Map messageArguments,
1888 {DartType userProvidedBadType,
1889 Element erroneousElement}) {
1890 if (malformedIsError) {
1891 visitor.error(node, messageKind, messageArguments);
1892 } else {
1893 registry.registerThrowRuntimeError();
1894 visitor.warning(node, messageKind, messageArguments);
1895 }
1896 if (erroneousElement == null) {
1897 registry.registerThrowRuntimeError();
1898 erroneousElement = new ErroneousElementX(
1899 messageKind, messageArguments, typeName.source,
1900 visitor.enclosingElement);
1901 }
1902 List<DartType> arguments = <DartType>[];
1903 resolveTypeArguments(visitor, node, const <DartType>[], arguments);
1904 return new MalformedType(erroneousElement,
1905 userProvidedBadType, arguments);
1906 }
1907
1908 // Try to construct the type from the element.
1909 if (element == null) {
1910 type = reportFailureAndCreateType(
1911 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName});
1912 } else if (element.isAmbiguous) {
1913 AmbiguousElement ambiguous = element;
1914 type = reportFailureAndCreateType(
1915 ambiguous.messageKind, ambiguous.messageArguments);
1916 ambiguous.diagnose(registry.mapping.analyzedElement, compiler);
1917 } else if (element.isErroneous) {
1918 if (element is ErroneousElement) {
1919 type = reportFailureAndCreateType(
1920 element.messageKind, element.messageArguments,
1921 erroneousElement: element);
1922 } else {
1923 type = const DynamicType();
1924 }
1925 } else if (!element.impliesType) {
1926 type = reportFailureAndCreateType(
1927 MessageKind.NOT_A_TYPE, {'node': node.typeName});
1928 } else {
1929 bool addTypeVariableBoundsCheck = false;
1930 if (element.isClass) {
1931 ClassElement cls = element;
1932 // TODO(johnniwinther): [_ensureClassWillBeResolved] should imply
1933 // [computeType].
1934 compiler.resolver._ensureClassWillBeResolved(cls);
1935 element.computeType(compiler);
1936 List<DartType> arguments = <DartType>[];
1937 bool hasTypeArgumentMismatch = resolveTypeArguments(
1938 visitor, node, cls.typeVariables, arguments);
1939 if (hasTypeArgumentMismatch) {
1940 type = new BadInterfaceType(cls.declaration,
1941 new InterfaceType.forUserProvidedBadType(cls.declaration,
1942 arguments));
1943 } else {
1944 if (arguments.isEmpty) {
1945 type = cls.rawType;
1946 } else {
1947 type = new InterfaceType(cls.declaration, arguments.toList(growable: false));
1948 addTypeVariableBoundsCheck = true;
1949 }
1950 }
1951 } else if (element.isTypedef) {
1952 TypedefElement typdef = element;
1953 // TODO(johnniwinther): [ensureResolved] should imply [computeType].
1954 typdef.ensureResolved(compiler);
1955 element.computeType(compiler);
1956 List<DartType> arguments = <DartType>[];
1957 bool hasTypeArgumentMismatch = resolveTypeArguments(
1958 visitor, node, typdef.typeVariables, arguments);
1959 if (hasTypeArgumentMismatch) {
1960 type = new BadTypedefType(typdef,
1961 new TypedefType.forUserProvidedBadType(typdef, arguments));
1962 } else {
1963 if (arguments.isEmpty) {
1964 type = typdef.rawType;
1965 } else {
1966 type = new TypedefType(typdef, arguments.toList(growable: false));
1967 addTypeVariableBoundsCheck = true;
1968 }
1969 }
1970 } else if (element.isTypeVariable) {
1971 Element outer =
1972 visitor.enclosingElement.outermostEnclosingMemberOrTopLevel;
1973 bool isInFactoryConstructor =
1974 outer != null && outer.isFactoryConstructor;
1975 if (!outer.isClass &&
1976 !outer.isTypedef &&
1977 !Elements.hasAccessToTypeVariables(visitor.enclosingElement)) {
1978 registry.registerThrowRuntimeError();
1979 type = reportFailureAndCreateType(
1980 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
1981 {'typeVariableName': node},
1982 userProvidedBadType: element.computeType(compiler));
1983 } else {
1984 type = element.computeType(compiler);
1985 }
1986 type = checkNoTypeArguments(type);
1987 } else {
1988 compiler.internalError(node,
1989 "Unexpected element kind ${element.kind}.");
1990 }
1991 if (addTypeVariableBoundsCheck) {
1992 registry.registerTypeVariableBoundCheck();
1993 visitor.addDeferredAction(
1994 visitor.enclosingElement,
1995 () => checkTypeVariableBounds(node, type));
1996 }
1997 }
1998 registry.useType(node, type);
1999 return type;
2000 }
2001
2002 /// Checks the type arguments of [type] against the type variable bounds.
2003 void checkTypeVariableBounds(TypeAnnotation node, GenericType type) {
2004 void checkTypeVariableBound(_, DartType typeArgument,
2005 TypeVariableType typeVariable,
2006 DartType bound) {
2007 if (!compiler.types.isSubtype(typeArgument, bound)) {
2008 compiler.reportWarning(node,
2009 MessageKind.INVALID_TYPE_VARIABLE_BOUND,
2010 {'typeVariable': typeVariable,
2011 'bound': bound,
2012 'typeArgument': typeArgument,
2013 'thisType': type.element.thisType});
2014 }
2015 };
2016
2017 compiler.types.checkTypeVariableBounds(type, checkTypeVariableBound);
2018 }
2019
2020 /**
2021 * Resolves the type arguments of [node] and adds these to [arguments].
2022 *
2023 * Returns [: true :] if the number of type arguments did not match the
2024 * number of type variables.
2025 */
2026 bool resolveTypeArguments(MappingVisitor visitor,
2027 TypeAnnotation node,
2028 List<DartType> typeVariables,
2029 List<DartType> arguments) {
2030 if (node.typeArguments == null) {
2031 return false;
2032 }
2033 int expectedVariables = typeVariables.length;
2034 int index = 0;
2035 bool typeArgumentCountMismatch = false;
2036 for (Link<Node> typeArguments = node.typeArguments.nodes;
2037 !typeArguments.isEmpty;
2038 typeArguments = typeArguments.tail, index++) {
2039 if (index > expectedVariables - 1) {
2040 visitor.warning(
2041 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
2042 typeArgumentCountMismatch = true;
2043 }
2044 DartType argType = resolveTypeAnnotation(visitor, typeArguments.head);
2045 // TODO(karlklose): rewrite to not modify [arguments].
2046 arguments.add(argType);
2047 }
2048 if (index < expectedVariables) {
2049 visitor.warning(node.typeArguments,
2050 MessageKind.MISSING_TYPE_ARGUMENT);
2051 typeArgumentCountMismatch = true;
2052 }
2053 return typeArgumentCountMismatch;
2054 }
2055 }
2056
2057 /**
2058 * Common supertype for resolver visitors that record resolutions in a
2059 * [ResolutionRegistry].
2060 */
2061 abstract class MappingVisitor<T> extends CommonResolverVisitor<T> {
2062 final ResolutionRegistry registry;
2063 final TypeResolver typeResolver;
2064 /// The current enclosing element for the visited AST nodes.
2065 Element get enclosingElement;
2066 /// The current scope of the visitor.
2067 Scope get scope;
2068
2069 MappingVisitor(Compiler compiler, ResolutionRegistry this.registry)
2070 : typeResolver = new TypeResolver(compiler),
2071 super(compiler);
2072
2073 AsyncMarker get currentAsyncMarker => AsyncMarker.SYNC;
2074
2075 /// Add [element] to the current scope and check for duplicate definitions.
2076 void addToScope(Element element) {
2077 Element existing = scope.add(element);
2078 if (existing != element) {
2079 reportDuplicateDefinition(element.name, element, existing);
2080 }
2081 }
2082
2083 void checkLocalDefinitionName(Node node, Element element) {
2084 if (currentAsyncMarker != AsyncMarker.SYNC) {
2085 if (element.name == 'yield' ||
2086 element.name == 'async' ||
2087 element.name == 'await') {
2088 compiler.reportError(
2089 node, MessageKind.ASYNC_KEYWORD_AS_IDENTIFIER,
2090 {'keyword': element.name,
2091 'modifier': currentAsyncMarker});
2092 }
2093 }
2094 }
2095
2096 /// Register [node] as the definition of [element].
2097 void defineLocalVariable(Node node, LocalVariableElement element) {
2098 if (element == null) {
2099 throw compiler.internalError(node, 'element is null');
2100 }
2101 checkLocalDefinitionName(node, element);
2102 registry.defineElement(node, element);
2103 }
2104
2105 void reportDuplicateDefinition(String name,
2106 Spannable definition,
2107 Spannable existing) {
2108 compiler.reportError(definition,
2109 MessageKind.DUPLICATE_DEFINITION, {'name': name});
2110 compiler.reportInfo(existing,
2111 MessageKind.EXISTING_DEFINITION, {'name': name});
2112 }
2113 }
2114
2115 /** 7 /**
2116 * Core implementation of resolution. 8 * Core implementation of resolution.
2117 * 9 *
2118 * Do not subclass or instantiate this class outside this library 10 * Do not subclass or instantiate this class outside this library
2119 * except for testing. 11 * except for testing.
2120 */ 12 */
2121 class ResolverVisitor extends MappingVisitor<ResolutionResult> { 13 class ResolverVisitor extends MappingVisitor<ResolutionResult> {
2122 /** 14 /**
2123 * The current enclosing element for the visited AST nodes. 15 * The current enclosing element for the visited AST nodes.
2124 * 16 *
(...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after
4434 registry.registerInstantiatedClass(compiler.stackTraceClass); 2326 registry.registerInstantiatedClass(compiler.stackTraceClass);
4435 stackTraceElement.variables.type = compiler.stackTraceClass.rawType; 2327 stackTraceElement.variables.type = compiler.stackTraceClass.rawType;
4436 } 2328 }
4437 } 2329 }
4438 2330
4439 visitTypedef(Typedef node) { 2331 visitTypedef(Typedef node) {
4440 internalError(node, 'typedef'); 2332 internalError(node, 'typedef');
4441 } 2333 }
4442 } 2334 }
4443 2335
4444 class TypeDefinitionVisitor extends MappingVisitor<DartType> {
4445 Scope scope;
4446 final TypeDeclarationElement enclosingElement;
4447 TypeDeclarationElement get element => enclosingElement;
4448
4449 TypeDefinitionVisitor(Compiler compiler,
4450 TypeDeclarationElement element,
4451 ResolutionRegistry registry)
4452 : this.enclosingElement = element,
4453 scope = Scope.buildEnclosingScope(element),
4454 super(compiler, registry);
4455
4456 DartType get objectType => compiler.objectClass.rawType;
4457
4458 void resolveTypeVariableBounds(NodeList node) {
4459 if (node == null) return;
4460
4461 Setlet<String> nameSet = new Setlet<String>();
4462 // Resolve the bounds of type variables.
4463 Iterator<DartType> types = element.typeVariables.iterator;
4464 Link<Node> nodeLink = node.nodes;
4465 while (!nodeLink.isEmpty) {
4466 types.moveNext();
4467 TypeVariableType typeVariable = types.current;
4468 String typeName = typeVariable.name;
4469 TypeVariable typeNode = nodeLink.head;
4470 registry.useType(typeNode, typeVariable);
4471 if (nameSet.contains(typeName)) {
4472 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME,
4473 {'typeVariableName': typeName});
4474 }
4475 nameSet.add(typeName);
4476
4477 TypeVariableElementX variableElement = typeVariable.element;
4478 if (typeNode.bound != null) {
4479 DartType boundType = typeResolver.resolveTypeAnnotation(
4480 this, typeNode.bound);
4481 variableElement.boundCache = boundType;
4482
4483 void checkTypeVariableBound() {
4484 Link<TypeVariableElement> seenTypeVariables =
4485 const Link<TypeVariableElement>();
4486 seenTypeVariables = seenTypeVariables.prepend(variableElement);
4487 DartType bound = boundType;
4488 while (bound.isTypeVariable) {
4489 TypeVariableElement element = bound.element;
4490 if (seenTypeVariables.contains(element)) {
4491 if (identical(element, variableElement)) {
4492 // Only report an error on the checked type variable to avoid
4493 // generating multiple errors for the same cyclicity.
4494 warning(typeNode.name, MessageKind.CYCLIC_TYPE_VARIABLE,
4495 {'typeVariableName': variableElement.name});
4496 }
4497 break;
4498 }
4499 seenTypeVariables = seenTypeVariables.prepend(element);
4500 bound = element.bound;
4501 }
4502 }
4503 addDeferredAction(element, checkTypeVariableBound);
4504 } else {
4505 variableElement.boundCache = objectType;
4506 }
4507 nodeLink = nodeLink.tail;
4508 }
4509 assert(!types.moveNext());
4510 }
4511 }
4512
4513 class TypedefResolverVisitor extends TypeDefinitionVisitor {
4514 TypedefElementX get element => enclosingElement;
4515
4516 TypedefResolverVisitor(Compiler compiler,
4517 TypedefElement typedefElement,
4518 ResolutionRegistry registry)
4519 : super(compiler, typedefElement, registry);
4520
4521 visitTypedef(Typedef node) {
4522 TypedefType type = element.computeType(compiler);
4523 scope = new TypeDeclarationScope(scope, element);
4524 resolveTypeVariableBounds(node.typeParameters);
4525
4526 FunctionSignature signature = SignatureResolver.analyze(
4527 compiler, node.formals, node.returnType, element, registry,
4528 defaultValuesError: MessageKind.TYPEDEF_FORMAL_WITH_DEFAULT);
4529 element.functionSignature = signature;
4530
4531 scope = new MethodScope(scope, element);
4532 signature.forEachParameter(addToScope);
4533
4534 element.alias = signature.type;
4535
4536 void checkCyclicReference() {
4537 element.checkCyclicReference(compiler);
4538 }
4539 addDeferredAction(element, checkCyclicReference);
4540 }
4541 }
4542
4543 // TODO(johnniwinther): Replace with a traversal on the AST when the type
4544 // annotations in typedef alias are stored in a [TreeElements] mapping.
4545 class TypedefCyclicVisitor extends BaseDartTypeVisitor {
4546 final Compiler compiler;
4547 final TypedefElementX element;
4548 bool hasCyclicReference = false;
4549
4550 Link<TypedefElement> seenTypedefs = const Link<TypedefElement>();
4551
4552 int seenTypedefsCount = 0;
4553
4554 Link<TypeVariableElement> seenTypeVariables =
4555 const Link<TypeVariableElement>();
4556
4557 TypedefCyclicVisitor(Compiler this.compiler, TypedefElement this.element);
4558
4559 visitType(DartType type, _) {
4560 // Do nothing.
4561 }
4562
4563 visitTypedefType(TypedefType type, _) {
4564 TypedefElementX typedefElement = type.element;
4565 if (seenTypedefs.contains(typedefElement)) {
4566 if (!hasCyclicReference && identical(element, typedefElement)) {
4567 // Only report an error on the checked typedef to avoid generating
4568 // multiple errors for the same cyclicity.
4569 hasCyclicReference = true;
4570 if (seenTypedefsCount == 1) {
4571 // Direct cyclicity.
4572 compiler.reportError(element,
4573 MessageKind.CYCLIC_TYPEDEF,
4574 {'typedefName': element.name});
4575 } else if (seenTypedefsCount == 2) {
4576 // Cyclicity through one other typedef.
4577 compiler.reportError(element,
4578 MessageKind.CYCLIC_TYPEDEF_ONE,
4579 {'typedefName': element.name,
4580 'otherTypedefName': seenTypedefs.head.name});
4581 } else {
4582 // Cyclicity through more than one other typedef.
4583 for (TypedefElement cycle in seenTypedefs) {
4584 if (!identical(typedefElement, cycle)) {
4585 compiler.reportError(element,
4586 MessageKind.CYCLIC_TYPEDEF_ONE,
4587 {'typedefName': element.name,
4588 'otherTypedefName': cycle.name});
4589 }
4590 }
4591 }
4592 ErroneousElementX erroneousElement = new ErroneousElementX(
4593 MessageKind.CYCLIC_TYPEDEF,
4594 {'typedefName': element.name},
4595 element.name, element);
4596 element.alias =
4597 new MalformedType(erroneousElement, typedefElement.alias);
4598 element.hasBeenCheckedForCycles = true;
4599 }
4600 } else {
4601 seenTypedefs = seenTypedefs.prepend(typedefElement);
4602 seenTypedefsCount++;
4603 type.visitChildren(this, null);
4604 typedefElement.alias.accept(this, null);
4605 seenTypedefs = seenTypedefs.tail;
4606 seenTypedefsCount--;
4607 }
4608 }
4609
4610 visitFunctionType(FunctionType type, _) {
4611 type.visitChildren(this, null);
4612 }
4613
4614 visitInterfaceType(InterfaceType type, _) {
4615 type.visitChildren(this, null);
4616 }
4617
4618 visitTypeVariableType(TypeVariableType type, _) {
4619 TypeVariableElement typeVariableElement = type.element;
4620 if (seenTypeVariables.contains(typeVariableElement)) {
4621 // Avoid running in cycles on cyclic type variable bounds.
4622 // Cyclicity is reported elsewhere.
4623 return;
4624 }
4625 seenTypeVariables = seenTypeVariables.prepend(typeVariableElement);
4626 typeVariableElement.bound.accept(this, null);
4627 seenTypeVariables = seenTypeVariables.tail;
4628 }
4629 }
4630
4631 /**
4632 * The implementation of [ResolverTask.resolveClass].
4633 *
4634 * This visitor has to be extra careful as it is building the basic
4635 * element information, and cannot safely look at other elements as
4636 * this may lead to cycles.
4637 *
4638 * This visitor can assume that the supertypes have already been
4639 * resolved, but it cannot call [ResolverTask.resolveClass] directly
4640 * or indirectly (through [ClassElement.ensureResolved]) for any other
4641 * types.
4642 */
4643 class ClassResolverVisitor extends TypeDefinitionVisitor {
4644 BaseClassElementX get element => enclosingElement;
4645
4646 ClassResolverVisitor(Compiler compiler,
4647 ClassElement classElement,
4648 ResolutionRegistry registry)
4649 : super(compiler, classElement, registry);
4650
4651 DartType visitClassNode(ClassNode node) {
4652 if (element == null) {
4653 throw compiler.internalError(node, 'element is null');
4654 }
4655 if (element.resolutionState != STATE_STARTED) {
4656 throw compiler.internalError(element,
4657 'cyclic resolution of class $element');
4658 }
4659
4660 InterfaceType type = element.computeType(compiler);
4661 scope = new TypeDeclarationScope(scope, element);
4662 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet.
4663 // As a side-effect, this may get us back here trying to
4664 // resolve this class again.
4665 resolveTypeVariableBounds(node.typeParameters);
4666
4667 // Setup the supertype for the element (if there is a cycle in the
4668 // class hierarchy, it has already been set to Object).
4669 if (element.supertype == null && node.superclass != null) {
4670 MixinApplication superMixin = node.superclass.asMixinApplication();
4671 if (superMixin != null) {
4672 DartType supertype = resolveSupertype(element, superMixin.superclass);
4673 Link<Node> link = superMixin.mixins.nodes;
4674 while (!link.isEmpty) {
4675 supertype = applyMixin(supertype,
4676 checkMixinType(link.head), link.head);
4677 link = link.tail;
4678 }
4679 element.supertype = supertype;
4680 } else {
4681 element.supertype = resolveSupertype(element, node.superclass);
4682 }
4683 }
4684 // If the super type isn't specified, we provide a default. The language
4685 // specifies [Object] but the backend can pick a specific 'implementation'
4686 // of Object - the JavaScript backend chooses between Object and
4687 // Interceptor.
4688 if (element.supertype == null) {
4689 ClassElement superElement = registry.defaultSuperclass(element);
4690 // Avoid making the superclass (usually Object) extend itself.
4691 if (element != superElement) {
4692 if (superElement == null) {
4693 compiler.internalError(node,
4694 "Cannot resolve default superclass for $element.");
4695 } else {
4696 superElement.ensureResolved(compiler);
4697 }
4698 element.supertype = superElement.computeType(compiler);
4699 }
4700 }
4701
4702 if (element.interfaces == null) {
4703 element.interfaces = resolveInterfaces(node.interfaces, node.superclass);
4704 } else {
4705 assert(invariant(element, element.hasIncompleteHierarchy));
4706 }
4707 calculateAllSupertypes(element);
4708
4709 if (!element.hasConstructor) {
4710 Element superMember = element.superclass.localLookup('');
4711 if (superMember == null || !superMember.isGenerativeConstructor) {
4712 MessageKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR;
4713 Map arguments = {'constructorName': ''};
4714 // TODO(ahe): Why is this a compile-time error? Or if it is an error,
4715 // why do we bother to registerThrowNoSuchMethod below?
4716 compiler.reportError(node, kind, arguments);
4717 superMember = new ErroneousElementX(
4718 kind, arguments, '', element);
4719 registry.registerThrowNoSuchMethod();
4720 } else {
4721 ConstructorElement superConstructor = superMember;
4722 Selector callToMatch = new Selector.call("", element.library, 0);
4723 superConstructor.computeSignature(compiler);
4724 if (!callToMatch.applies(superConstructor, compiler.world)) {
4725 MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT;
4726 compiler.reportError(node, kind);
4727 superMember = new ErroneousElementX(kind, {}, '', element);
4728 }
4729 }
4730 FunctionElement constructor =
4731 new SynthesizedConstructorElementX.forDefault(superMember, element);
4732 if (superMember.isErroneous) {
4733 compiler.elementsWithCompileTimeErrors.add(constructor);
4734 }
4735 element.setDefaultConstructor(constructor, compiler);
4736 }
4737 return element.computeType(compiler);
4738 }
4739
4740 @override
4741 DartType visitEnum(Enum node) {
4742 if (element == null) {
4743 throw compiler.internalError(node, 'element is null');
4744 }
4745 if (element.resolutionState != STATE_STARTED) {
4746 throw compiler.internalError(element,
4747 'cyclic resolution of class $element');
4748 }
4749
4750 InterfaceType enumType = element.computeType(compiler);
4751 element.supertype = compiler.objectClass.computeType(compiler);
4752 element.interfaces = const Link<DartType>();
4753 calculateAllSupertypes(element);
4754
4755 if (node.names.nodes.isEmpty) {
4756 compiler.reportError(node,
4757 MessageKind.EMPTY_ENUM_DECLARATION,
4758 {'enumName': element.name});
4759 }
4760
4761 EnumCreator creator = new EnumCreator(compiler, element);
4762 creator.createMembers();
4763 return enumType;
4764 }
4765
4766 /// Resolves the mixed type for [mixinNode] and checks that the the mixin type
4767 /// is a valid, non-blacklisted interface type. The mixin type is returned.
4768 DartType checkMixinType(TypeAnnotation mixinNode) {
4769 DartType mixinType = resolveType(mixinNode);
4770 if (isBlackListed(mixinType)) {
4771 compiler.reportError(mixinNode,
4772 MessageKind.CANNOT_MIXIN, {'type': mixinType});
4773 } else if (mixinType.isTypeVariable) {
4774 compiler.reportError(mixinNode, MessageKind.CLASS_NAME_EXPECTED);
4775 } else if (mixinType.isMalformed) {
4776 compiler.reportError(mixinNode, MessageKind.CANNOT_MIXIN_MALFORMED,
4777 {'className': element.name, 'malformedType': mixinType});
4778 } else if (mixinType.isEnumType) {
4779 compiler.reportError(mixinNode, MessageKind.CANNOT_MIXIN_ENUM,
4780 {'className': element.name, 'enumType': mixinType});
4781 }
4782 return mixinType;
4783 }
4784
4785 DartType visitNamedMixinApplication(NamedMixinApplication node) {
4786 if (element == null) {
4787 throw compiler.internalError(node, 'element is null');
4788 }
4789 if (element.resolutionState != STATE_STARTED) {
4790 throw compiler.internalError(element,
4791 'cyclic resolution of class $element');
4792 }
4793
4794 if (identical(node.classKeyword.stringValue, 'typedef')) {
4795 // TODO(aprelev@gmail.com): Remove this deprecation diagnostic
4796 // together with corresponding TODO in parser.dart.
4797 compiler.reportWarning(node.classKeyword,
4798 MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX);
4799 }
4800
4801 InterfaceType type = element.computeType(compiler);
4802 scope = new TypeDeclarationScope(scope, element);
4803 resolveTypeVariableBounds(node.typeParameters);
4804
4805 // Generate anonymous mixin application elements for the
4806 // intermediate mixin applications (excluding the last).
4807 DartType supertype = resolveSupertype(element, node.superclass);
4808 Link<Node> link = node.mixins.nodes;
4809 while (!link.tail.isEmpty) {
4810 supertype = applyMixin(supertype, checkMixinType(link.head), link.head);
4811 link = link.tail;
4812 }
4813 doApplyMixinTo(element, supertype, checkMixinType(link.head));
4814 return element.computeType(compiler);
4815 }
4816
4817 DartType applyMixin(DartType supertype, DartType mixinType, Node node) {
4818 String superName = supertype.name;
4819 String mixinName = mixinType.name;
4820 MixinApplicationElementX mixinApplication = new MixinApplicationElementX(
4821 "${superName}+${mixinName}",
4822 element.compilationUnit,
4823 compiler.getNextFreeClassId(),
4824 node,
4825 new Modifiers.withFlags(new NodeList.empty(), Modifiers.FLAG_ABSTRACT));
4826 // Create synthetic type variables for the mixin application.
4827 List<DartType> typeVariables = <DartType>[];
4828 element.typeVariables.forEach((TypeVariableType type) {
4829 TypeVariableElementX typeVariableElement = new TypeVariableElementX(
4830 type.name, mixinApplication, type.element.node);
4831 TypeVariableType typeVariable = new TypeVariableType(typeVariableElement);
4832 typeVariables.add(typeVariable);
4833 });
4834 // Setup bounds on the synthetic type variables.
4835 int index = 0;
4836 element.typeVariables.forEach((TypeVariableType type) {
4837 TypeVariableType typeVariable = typeVariables[index++];
4838 TypeVariableElementX typeVariableElement = typeVariable.element;
4839 typeVariableElement.typeCache = typeVariable;
4840 typeVariableElement.boundCache =
4841 type.element.bound.subst(typeVariables, element.typeVariables);
4842 });
4843 // Setup this and raw type for the mixin application.
4844 mixinApplication.computeThisAndRawType(compiler, typeVariables);
4845 // Substitute in synthetic type variables in super and mixin types.
4846 supertype = supertype.subst(typeVariables, element.typeVariables);
4847 mixinType = mixinType.subst(typeVariables, element.typeVariables);
4848
4849 doApplyMixinTo(mixinApplication, supertype, mixinType);
4850 mixinApplication.resolutionState = STATE_DONE;
4851 mixinApplication.supertypeLoadState = STATE_DONE;
4852 // Replace the synthetic type variables by the original type variables in
4853 // the returned type (which should be the type actually extended).
4854 InterfaceType mixinThisType = mixinApplication.computeType(compiler);
4855 return mixinThisType.subst(element.typeVariables,
4856 mixinThisType.typeArguments);
4857 }
4858
4859 bool isDefaultConstructor(FunctionElement constructor) {
4860 return constructor.name == '' &&
4861 constructor.computeSignature(compiler).parameterCount == 0;
4862 }
4863
4864 FunctionElement createForwardingConstructor(ConstructorElement target,
4865 ClassElement enclosing) {
4866 return new SynthesizedConstructorElementX.notForDefault(
4867 target.name, target, enclosing);
4868 }
4869
4870 void doApplyMixinTo(MixinApplicationElementX mixinApplication,
4871 DartType supertype,
4872 DartType mixinType) {
4873 Node node = mixinApplication.parseNode(compiler);
4874
4875 if (mixinApplication.supertype != null) {
4876 // [supertype] is not null if there was a cycle.
4877 assert(invariant(node, compiler.compilationFailed));
4878 supertype = mixinApplication.supertype;
4879 assert(invariant(node, supertype.element == compiler.objectClass));
4880 } else {
4881 mixinApplication.supertype = supertype;
4882 }
4883
4884 // Named mixin application may have an 'implements' clause.
4885 NamedMixinApplication namedMixinApplication =
4886 node.asNamedMixinApplication();
4887 Link<DartType> interfaces = (namedMixinApplication != null)
4888 ? resolveInterfaces(namedMixinApplication.interfaces,
4889 namedMixinApplication.superclass)
4890 : const Link<DartType>();
4891
4892 // The class that is the result of a mixin application implements
4893 // the interface of the class that was mixed in so always prepend
4894 // that to the interface list.
4895 if (mixinApplication.interfaces == null) {
4896 if (mixinType.isInterfaceType) {
4897 // Avoid malformed types in the interfaces.
4898 interfaces = interfaces.prepend(mixinType);
4899 }
4900 mixinApplication.interfaces = interfaces;
4901 } else {
4902 assert(invariant(mixinApplication,
4903 mixinApplication.hasIncompleteHierarchy));
4904 }
4905
4906 ClassElement superclass = supertype.element;
4907 if (mixinType.kind != TypeKind.INTERFACE) {
4908 mixinApplication.hasIncompleteHierarchy = true;
4909 mixinApplication.allSupertypesAndSelf = superclass.allSupertypesAndSelf;
4910 return;
4911 }
4912
4913 assert(mixinApplication.mixinType == null);
4914 mixinApplication.mixinType = resolveMixinFor(mixinApplication, mixinType);
4915
4916 // Create forwarding constructors for constructor defined in the superclass
4917 // because they are now hidden by the mixin application.
4918 superclass.forEachLocalMember((Element member) {
4919 if (!member.isGenerativeConstructor) return;
4920 FunctionElement forwarder =
4921 createForwardingConstructor(member, mixinApplication);
4922 if (isPrivateName(member.name) &&
4923 mixinApplication.library != superclass.library) {
4924 // Do not create a forwarder to the super constructor, because the mixin
4925 // application is in a different library than the constructor in the
4926 // super class and it is not possible to call that constructor from the
4927 // library using the mixin application.
4928 return;
4929 }
4930 mixinApplication.addConstructor(forwarder);
4931 });
4932 calculateAllSupertypes(mixinApplication);
4933 }
4934
4935 InterfaceType resolveMixinFor(MixinApplicationElement mixinApplication,
4936 DartType mixinType) {
4937 ClassElement mixin = mixinType.element;
4938 mixin.ensureResolved(compiler);
4939
4940 // Check for cycles in the mixin chain.
4941 ClassElement previous = mixinApplication; // For better error messages.
4942 ClassElement current = mixin;
4943 while (current != null && current.isMixinApplication) {
4944 MixinApplicationElement currentMixinApplication = current;
4945 if (currentMixinApplication == mixinApplication) {
4946 compiler.reportError(
4947 mixinApplication, MessageKind.ILLEGAL_MIXIN_CYCLE,
4948 {'mixinName1': current.name, 'mixinName2': previous.name});
4949 // We have found a cycle in the mixin chain. Return null as
4950 // the mixin for this application to avoid getting into
4951 // infinite recursion when traversing members.
4952 return null;
4953 }
4954 previous = current;
4955 current = currentMixinApplication.mixin;
4956 }
4957 registry.registerMixinUse(mixinApplication, mixin);
4958 return mixinType;
4959 }
4960
4961 DartType resolveType(TypeAnnotation node) {
4962 return typeResolver.resolveTypeAnnotation(this, node);
4963 }
4964
4965 DartType resolveSupertype(ClassElement cls, TypeAnnotation superclass) {
4966 DartType supertype = resolveType(superclass);
4967 if (supertype != null) {
4968 if (supertype.isMalformed) {
4969 compiler.reportError(superclass, MessageKind.CANNOT_EXTEND_MALFORMED,
4970 {'className': element.name, 'malformedType': supertype});
4971 return objectType;
4972 } else if (supertype.isEnumType) {
4973 compiler.reportError(superclass, MessageKind.CANNOT_EXTEND_ENUM,
4974 {'className': element.name, 'enumType': supertype});
4975 return objectType;
4976 } else if (!supertype.isInterfaceType) {
4977 compiler.reportError(superclass.typeName,
4978 MessageKind.CLASS_NAME_EXPECTED);
4979 return objectType;
4980 } else if (isBlackListed(supertype)) {
4981 compiler.reportError(superclass, MessageKind.CANNOT_EXTEND,
4982 {'type': supertype});
4983 return objectType;
4984 }
4985 }
4986 return supertype;
4987 }
4988
4989 Link<DartType> resolveInterfaces(NodeList interfaces, Node superclass) {
4990 Link<DartType> result = const Link<DartType>();
4991 if (interfaces == null) return result;
4992 for (Link<Node> link = interfaces.nodes; !link.isEmpty; link = link.tail) {
4993 DartType interfaceType = resolveType(link.head);
4994 if (interfaceType != null) {
4995 if (interfaceType.isMalformed) {
4996 compiler.reportError(superclass,
4997 MessageKind.CANNOT_IMPLEMENT_MALFORMED,
4998 {'className': element.name, 'malformedType': interfaceType});
4999 } else if (interfaceType.isEnumType) {
5000 compiler.reportError(superclass,
5001 MessageKind.CANNOT_IMPLEMENT_ENUM,
5002 {'className': element.name, 'enumType': interfaceType});
5003 } else if (!interfaceType.isInterfaceType) {
5004 // TODO(johnniwinther): Handle dynamic.
5005 TypeAnnotation typeAnnotation = link.head;
5006 error(typeAnnotation.typeName, MessageKind.CLASS_NAME_EXPECTED);
5007 } else {
5008 if (interfaceType == element.supertype) {
5009 compiler.reportError(
5010 superclass,
5011 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
5012 {'type': interfaceType});
5013 compiler.reportError(
5014 link.head,
5015 MessageKind.DUPLICATE_EXTENDS_IMPLEMENTS,
5016 {'type': interfaceType});
5017 }
5018 if (result.contains(interfaceType)) {
5019 compiler.reportError(
5020 link.head,
5021 MessageKind.DUPLICATE_IMPLEMENTS,
5022 {'type': interfaceType});
5023 }
5024 result = result.prepend(interfaceType);
5025 if (isBlackListed(interfaceType)) {
5026 error(link.head, MessageKind.CANNOT_IMPLEMENT,
5027 {'type': interfaceType});
5028 }
5029 }
5030 }
5031 }
5032 return result;
5033 }
5034
5035 /**
5036 * Compute the list of all supertypes.
5037 *
5038 * The elements of this list are ordered as follows: first the supertype that
5039 * the class extends, then the implemented interfaces, and then the supertypes
5040 * of these. The class [Object] appears only once, at the end of the list.
5041 *
5042 * For example, for a class `class C extends S implements I1, I2`, we compute
5043 * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1)
5044 * ++ supertypes(I2),
5045 * where ++ stands for list concatenation.
5046 *
5047 * This order makes sure that if a class implements an interface twice with
5048 * different type arguments, the type used in the most specific class comes
5049 * first.
5050 */
5051 void calculateAllSupertypes(BaseClassElementX cls) {
5052 if (cls.allSupertypesAndSelf != null) return;
5053 final DartType supertype = cls.supertype;
5054 if (supertype != null) {
5055 OrderedTypeSetBuilder allSupertypes = new OrderedTypeSetBuilder(cls);
5056 // TODO(15296): Collapse these iterations to one when the order is not
5057 // needed.
5058 allSupertypes.add(compiler, supertype);
5059 for (Link<DartType> interfaces = cls.interfaces;
5060 !interfaces.isEmpty;
5061 interfaces = interfaces.tail) {
5062 allSupertypes.add(compiler, interfaces.head);
5063 }
5064
5065 addAllSupertypes(allSupertypes, supertype);
5066 for (Link<DartType> interfaces = cls.interfaces;
5067 !interfaces.isEmpty;
5068 interfaces = interfaces.tail) {
5069 addAllSupertypes(allSupertypes, interfaces.head);
5070 }
5071 allSupertypes.add(compiler, cls.computeType(compiler));
5072 cls.allSupertypesAndSelf = allSupertypes.toTypeSet();
5073 } else {
5074 assert(identical(cls, compiler.objectClass));
5075 cls.allSupertypesAndSelf =
5076 new OrderedTypeSet.singleton(cls.computeType(compiler));
5077 }
5078 }
5079
5080 /**
5081 * Adds [type] and all supertypes of [type] to [allSupertypes] while
5082 * substituting type variables.
5083 */
5084 void addAllSupertypes(OrderedTypeSetBuilder allSupertypes,
5085 InterfaceType type) {
5086 ClassElement classElement = type.element;
5087 Link<DartType> supertypes = classElement.allSupertypes;
5088 assert(invariant(element, supertypes != null,
5089 message: "Supertypes not computed on $classElement "
5090 "during resolution of $element"));
5091 while (!supertypes.isEmpty) {
5092 DartType supertype = supertypes.head;
5093 allSupertypes.add(compiler, supertype.substByContext(type));
5094 supertypes = supertypes.tail;
5095 }
5096 }
5097
5098 isBlackListed(DartType type) {
5099 LibraryElement lib = element.library;
5100 return
5101 !identical(lib, compiler.coreLibrary) &&
5102 !compiler.backend.isBackendLibrary(lib) &&
5103 (type.isDynamic ||
5104 identical(type.element, compiler.boolClass) ||
5105 identical(type.element, compiler.numClass) ||
5106 identical(type.element, compiler.intClass) ||
5107 identical(type.element, compiler.doubleClass) ||
5108 identical(type.element, compiler.stringClass) ||
5109 identical(type.element, compiler.nullClass));
5110 }
5111 }
5112
5113 class ClassSupertypeResolver extends CommonResolverVisitor {
5114 Scope context;
5115 ClassElement classElement;
5116
5117 ClassSupertypeResolver(Compiler compiler, ClassElement cls)
5118 : context = Scope.buildEnclosingScope(cls),
5119 this.classElement = cls,
5120 super(compiler);
5121
5122 void loadSupertype(ClassElement element, Node from) {
5123 compiler.resolver.loadSupertypes(element, from);
5124 element.ensureResolved(compiler);
5125 }
5126
5127 void visitNodeList(NodeList node) {
5128 if (node != null) {
5129 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
5130 link.head.accept(this);
5131 }
5132 }
5133 }
5134
5135 void visitClassNode(ClassNode node) {
5136 if (node.superclass == null) {
5137 if (!identical(classElement, compiler.objectClass)) {
5138 loadSupertype(compiler.objectClass, node);
5139 }
5140 } else {
5141 node.superclass.accept(this);
5142 }
5143 visitNodeList(node.interfaces);
5144 }
5145
5146 void visitEnum(Enum node) {
5147 loadSupertype(compiler.objectClass, node);
5148 }
5149
5150 void visitMixinApplication(MixinApplication node) {
5151 node.superclass.accept(this);
5152 visitNodeList(node.mixins);
5153 }
5154
5155 void visitNamedMixinApplication(NamedMixinApplication node) {
5156 node.superclass.accept(this);
5157 visitNodeList(node.mixins);
5158 visitNodeList(node.interfaces);
5159 }
5160
5161 void visitTypeAnnotation(TypeAnnotation node) {
5162 node.typeName.accept(this);
5163 }
5164
5165 void visitIdentifier(Identifier node) {
5166 Element element = lookupInScope(compiler, node, context, node.source);
5167 if (element != null && element.isClass) {
5168 loadSupertype(element, node);
5169 }
5170 }
5171
5172 void visitSend(Send node) {
5173 Identifier prefix = node.receiver.asIdentifier();
5174 if (prefix == null) {
5175 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver});
5176 return;
5177 }
5178 Element element = lookupInScope(compiler, prefix, context, prefix.source);
5179 if (element == null || !identical(element.kind, ElementKind.PREFIX)) {
5180 error(node.receiver, MessageKind.NOT_A_PREFIX, {'node': node.receiver});
5181 return;
5182 }
5183 PrefixElement prefixElement = element;
5184 Identifier selector = node.selector.asIdentifier();
5185 var e = prefixElement.lookupLocalMember(selector.source);
5186 if (e == null || !e.impliesType) {
5187 error(node.selector, MessageKind.CANNOT_RESOLVE_TYPE,
5188 {'typeName': node.selector});
5189 return;
5190 }
5191 loadSupertype(e, node);
5192 }
5193 }
5194
5195 class VariableDefinitionsVisitor extends CommonResolverVisitor<Identifier> {
5196 VariableDefinitions definitions;
5197 ResolverVisitor resolver;
5198 VariableList variables;
5199
5200 VariableDefinitionsVisitor(Compiler compiler,
5201 this.definitions,
5202 this.resolver,
5203 this.variables)
5204 : super(compiler) {
5205 }
5206
5207 ResolutionRegistry get registry => resolver.registry;
5208
5209 Identifier visitSendSet(SendSet node) {
5210 assert(node.arguments.tail.isEmpty); // Sanity check
5211 Identifier identifier = node.selector;
5212 String name = identifier.source;
5213 VariableDefinitionScope scope =
5214 new VariableDefinitionScope(resolver.scope, name);
5215 resolver.visitIn(node.arguments.head, scope);
5216 if (scope.variableReferencedInInitializer) {
5217 compiler.reportError(
5218 identifier, MessageKind.REFERENCE_IN_INITIALIZATION,
5219 {'variableName': name});
5220 }
5221 return identifier;
5222 }
5223
5224 Identifier visitIdentifier(Identifier node) {
5225 // The variable is initialized to null.
5226 registry.registerInstantiatedClass(compiler.nullClass);
5227 if (definitions.modifiers.isConst) {
5228 compiler.reportError(node, MessageKind.CONST_WITHOUT_INITIALIZER);
5229 }
5230 if (definitions.modifiers.isFinal &&
5231 !resolver.allowFinalWithoutInitializer) {
5232 compiler.reportError(node, MessageKind.FINAL_WITHOUT_INITIALIZER);
5233 }
5234 return node;
5235 }
5236
5237 visitNodeList(NodeList node) {
5238 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
5239 Identifier name = visit(link.head);
5240 LocalVariableElementX element = new LocalVariableElementX(
5241 name.source, resolver.enclosingElement,
5242 variables, name.token);
5243 resolver.defineLocalVariable(link.head, element);
5244 resolver.addToScope(element);
5245 if (definitions.modifiers.isConst) {
5246 compiler.enqueuer.resolution.addDeferredAction(element, () {
5247 element.constant =
5248 compiler.resolver.constantCompiler.compileConstant(element);
5249 });
5250 }
5251 }
5252 }
5253 }
5254
5255 class ConstructorResolver extends CommonResolverVisitor<Element> {
5256 final ResolverVisitor resolver;
5257 bool inConstContext;
5258 DartType type;
5259
5260 ConstructorResolver(Compiler compiler, this.resolver,
5261 {bool this.inConstContext: false})
5262 : super(compiler);
5263
5264 ResolutionRegistry get registry => resolver.registry;
5265
5266 visitNode(Node node) {
5267 throw 'not supported';
5268 }
5269
5270 ErroneousConstructorElementX failOrReturnErroneousConstructorElement(
5271 Spannable diagnosticNode,
5272 Element enclosing,
5273 String name,
5274 MessageKind kind,
5275 Map arguments,
5276 {bool isError: false,
5277 bool missingConstructor: false}) {
5278 if (missingConstructor) {
5279 registry.registerThrowNoSuchMethod();
5280 } else {
5281 registry.registerThrowRuntimeError();
5282 }
5283 if (isError || inConstContext) {
5284 compiler.reportError(diagnosticNode, kind, arguments);
5285 } else {
5286 compiler.reportWarning(diagnosticNode, kind, arguments);
5287 }
5288 return new ErroneousConstructorElementX(
5289 kind, arguments, name, enclosing);
5290 }
5291
5292 FunctionElement resolveConstructor(ClassElement cls,
5293 Node diagnosticNode,
5294 String constructorName) {
5295 cls.ensureResolved(compiler);
5296 Element result = cls.lookupConstructor(constructorName);
5297 // TODO(johnniwinther): Use [Name] for lookup.
5298 if (isPrivateName(constructorName) &&
5299 resolver.enclosingElement.library != cls.library) {
5300 result = null;
5301 }
5302 if (result == null) {
5303 String fullConstructorName = Elements.constructorNameForDiagnostics(
5304 cls.name,
5305 constructorName);
5306 return failOrReturnErroneousConstructorElement(
5307 diagnosticNode,
5308 cls, constructorName,
5309 MessageKind.CANNOT_FIND_CONSTRUCTOR,
5310 {'constructorName': fullConstructorName},
5311 missingConstructor: true);
5312 } else if (inConstContext && !result.isConst) {
5313 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
5314 }
5315 return result;
5316 }
5317
5318 Element visitNewExpression(NewExpression node) {
5319 inConstContext = node.isConst;
5320 Node selector = node.send.selector;
5321 Element element = visit(selector);
5322 assert(invariant(selector, element != null,
5323 message: 'No element return for $selector.'));
5324 return finishConstructorReference(element, node.send.selector, node);
5325 }
5326
5327 /// Finishes resolution of a constructor reference and records the
5328 /// type of the constructed instance on [expression].
5329 FunctionElement finishConstructorReference(Element element,
5330 Node diagnosticNode,
5331 Node expression) {
5332 assert(invariant(diagnosticNode, element != null,
5333 message: 'No element return for $diagnosticNode.'));
5334 // Find the unnamed constructor if the reference resolved to a
5335 // class.
5336 if (!Elements.isUnresolved(element) && !element.isConstructor) {
5337 if (element.isClass) {
5338 ClassElement cls = element;
5339 cls.ensureResolved(compiler);
5340 // The unnamed constructor may not exist, so [e] may become unresolved.
5341 element = resolveConstructor(cls, diagnosticNode, '');
5342 } else {
5343 element = failOrReturnErroneousConstructorElement(
5344 diagnosticNode,
5345 element, element.name,
5346 MessageKind.NOT_A_TYPE, {'node': diagnosticNode});
5347 }
5348 } else if (element.isErroneous && element is! ErroneousElementX) {
5349 // Parser error. The error has already been reported.
5350 element = new ErroneousConstructorElementX(
5351 MessageKind.NOT_A_TYPE, {'node': diagnosticNode},
5352 element.name, element);
5353 registry.registerThrowRuntimeError();
5354 }
5355
5356 if (type == null) {
5357 if (Elements.isUnresolved(element)) {
5358 type = const DynamicType();
5359 } else {
5360 type = element.enclosingClass.rawType;
5361 }
5362 }
5363 resolver.registry.setType(expression, type);
5364 return element;
5365 }
5366
5367 Element visitTypeAnnotation(TypeAnnotation node) {
5368 assert(invariant(node, type == null));
5369 // This is not really resolving a type-annotation, but the name of the
5370 // constructor. Therefore we allow deferred types.
5371 type = resolver.resolveTypeAnnotation(node,
5372 malformedIsError: inConstContext,
5373 deferredIsMalformed: false);
5374 registry.registerRequiredType(type, resolver.enclosingElement);
5375 return type.element;
5376 }
5377
5378 Element visitSend(Send node) {
5379 Element element = visit(node.receiver);
5380 assert(invariant(node.receiver, element != null,
5381 message: 'No element return for $node.receiver.'));
5382 if (Elements.isUnresolved(element)) return element;
5383 Identifier name = node.selector.asIdentifier();
5384 if (name == null) internalError(node.selector, 'unexpected node');
5385
5386 if (element.isClass) {
5387 ClassElement cls = element;
5388 cls.ensureResolved(compiler);
5389 return resolveConstructor(cls, name, name.source);
5390 } else if (element.isPrefix) {
5391 PrefixElement prefix = element;
5392 element = prefix.lookupLocalMember(name.source);
5393 element = Elements.unwrap(element, compiler, node);
5394 if (element == null) {
5395 return failOrReturnErroneousConstructorElement(
5396 name,
5397 resolver.enclosingElement, name.source,
5398 MessageKind.CANNOT_RESOLVE, {'name': name});
5399 } else if (!element.isClass) {
5400 return failOrReturnErroneousConstructorElement(
5401 name,
5402 resolver.enclosingElement, name.source,
5403 MessageKind.NOT_A_TYPE, {'node': name},
5404 isError: true);
5405 }
5406 } else {
5407 internalError(node.receiver, 'unexpected element $element');
5408 }
5409 return element;
5410 }
5411
5412 Element visitIdentifier(Identifier node) {
5413 String name = node.source;
5414 Element element = resolver.reportLookupErrorIfAny(
5415 lookupInScope(compiler, node, resolver.scope, name), node, name);
5416 registry.useElement(node, element);
5417 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
5418 if (element == null) {
5419 return failOrReturnErroneousConstructorElement(
5420 node,
5421 resolver.enclosingElement, name,
5422 MessageKind.CANNOT_RESOLVE,
5423 {'name': name});
5424 } else if (element.isErroneous) {
5425 return element;
5426 } else if (element.isTypedef) {
5427 element = failOrReturnErroneousConstructorElement(
5428 node,
5429 resolver.enclosingElement, name,
5430 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name},
5431 isError: true);
5432 } else if (element.isTypeVariable) {
5433 element = failOrReturnErroneousConstructorElement(
5434 node,
5435 resolver.enclosingElement, name,
5436 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
5437 {'typeVariableName': name},
5438 isError: true);
5439 } else if (!element.isClass && !element.isPrefix) {
5440 element = failOrReturnErroneousConstructorElement(
5441 node,
5442 resolver.enclosingElement, name,
5443 MessageKind.NOT_A_TYPE, {'node': name},
5444 isError: true);
5445 }
5446 return element;
5447 }
5448
5449 /// Assumed to be called by [resolveRedirectingFactory].
5450 Element visitRedirectingFactoryBody(RedirectingFactoryBody node) {
5451 Node constructorReference = node.constructorReference;
5452 return finishConstructorReference(visit(constructorReference),
5453 constructorReference, node);
5454 }
5455 }
5456
5457 /// Looks up [name] in [scope] and unwraps the result. 2336 /// Looks up [name] in [scope] and unwraps the result.
5458 Element lookupInScope(Compiler compiler, Node node, 2337 Element lookupInScope(Compiler compiler, Node node,
5459 Scope scope, String name) { 2338 Scope scope, String name) {
5460 return Elements.unwrap(scope.lookup(name), compiler, node); 2339 return Elements.unwrap(scope.lookup(name), compiler, node);
5461 } 2340 }
5462
5463 TreeElements _ensureTreeElements(AnalyzableElementX element) {
5464 if (element._treeElements == null) {
5465 element._treeElements = new TreeElementMapping(element);
5466 }
5467 return element._treeElements;
5468 }
5469
5470 abstract class AnalyzableElementX implements AnalyzableElement {
5471 TreeElements _treeElements;
5472
5473 bool get hasTreeElements => _treeElements != null;
5474
5475 TreeElements get treeElements {
5476 assert(invariant(this, _treeElements !=null,
5477 message: "TreeElements have not been computed for $this."));
5478 return _treeElements;
5479 }
5480
5481 void reuseElement() {
5482 _treeElements = null;
5483 }
5484 }
5485
5486 /// The result of resolving a node.
5487 abstract class ResolutionResult {
5488 Element get element;
5489 }
5490
5491 /// The result for the resolution of a node that points to an [Element].
5492 class ElementResult implements ResolutionResult {
5493 final Element element;
5494
5495 // TODO(johnniwinther): Remove this factory constructor when `null` is never
5496 // passed as an element result.
5497 factory ElementResult(Element element) {
5498 return element != null ? new ElementResult.internal(element) : null;
5499 }
5500
5501 ElementResult.internal(this.element);
5502
5503 String toString() => 'ElementResult($element)';
5504 }
5505
5506 /// The result for the resolution of a node that points to an [DartType].
5507 class TypeResult implements ResolutionResult {
5508 final DartType type;
5509
5510 TypeResult(this.type) {
5511 assert(type != null);
5512 }
5513
5514 Element get element => type.element;
5515
5516 String toString() => 'TypeResult($type)';
5517 }
5518
5519 /// The result for the resolution of the `assert` method.
5520 class AssertResult implements ResolutionResult {
5521 const AssertResult();
5522
5523 Element get element => null;
5524
5525 String toString() => 'AssertResult()';
5526 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/label_scope.dart ('k') | pkg/compiler/lib/src/resolution/resolution.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698