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

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

Issue 1286993004: Split resolution into several libraries. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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 library resolution; 5 library dart2js.resolution;
6 6
7 import 'dart:collection' show Queue; 7 import 'dart:collection' show Queue;
8 8
9 import '../common/backend_api.dart' show
10 Backend;
11 import '../common/registry.dart' show
12 Registry;
13 import '../common/tasks.dart' show 9 import '../common/tasks.dart' show
14 CompilerTask, 10 CompilerTask,
15 DeferredAction; 11 DeferredAction;
16 import '../compiler.dart' show 12 import '../compiler.dart' show
17 Compiler, 13 Compiler;
18 isPrivateName; 14 import '../compile_time_constants.dart' show
19 import '../compile_time_constants.dart'; 15 ConstantCompiler;
20 import '../constants/constructors.dart'; 16 import '../constants/values.dart' show
21 import '../constants/expressions.dart'; 17 ConstantValue;
22 import '../constants/values.dart';
23 import '../core_types.dart';
24 import '../dart_backend/dart_backend.dart' show DartBackend;
25 import '../dart_types.dart'; 18 import '../dart_types.dart';
26 import '../diagnostics/invariant.dart' show 19 import '../diagnostics/invariant.dart' show
27 invariant; 20 invariant;
28 import '../diagnostics/messages.dart' show MessageKind; 21 import '../diagnostics/messages.dart' show
22 MessageKind;
29 import '../diagnostics/spannable.dart' show 23 import '../diagnostics/spannable.dart' show
30 Spannable; 24 Spannable;
31 import '../enqueue.dart' show
32 ResolutionEnqueuer,
33 WorldImpact;
34 import '../tree/tree.dart';
35 import '../scanner/scannerlib.dart';
36 import '../elements/elements.dart'; 25 import '../elements/elements.dart';
37 import '../elements/modelx.dart' show 26 import '../elements/modelx.dart' show
38 BaseClassElementX, 27 BaseClassElementX,
39 BaseFunctionElementX, 28 BaseFunctionElementX,
40 ConstructorElementX, 29 ConstructorElementX,
41 ErroneousConstructorElementX,
42 ErroneousElementX,
43 ErroneousFieldElementX,
44 ErroneousInitializingFormalElementX,
45 FieldElementX, 30 FieldElementX,
46 FormalElementX,
47 FunctionElementX, 31 FunctionElementX,
48 FunctionSignatureX,
49 GetterElementX, 32 GetterElementX,
50 InitializingFormalElementX,
51 JumpTargetX,
52 LabelDefinitionX,
53 LocalFunctionElementX,
54 LocalParameterElementX,
55 LocalVariableElementX,
56 MetadataAnnotationX, 33 MetadataAnnotationX,
57 MethodElementX,
58 MixinApplicationElementX, 34 MixinApplicationElementX,
59 ParameterElementX,
60 ParameterMetadataAnnotation, 35 ParameterMetadataAnnotation,
61 SetterElementX, 36 SetterElementX,
62 SynthesizedConstructorElementX, 37 TypedefElementX;
63 TypeVariableElementX, 38 import '../enqueue.dart' show
64 TypedefElementX, 39 WorldImpact;
65 VariableElementX, 40 import '../scanner/scannerlib.dart' show
66 VariableList; 41 isBinaryOperator,
67 import '../ordered_typeset.dart' show OrderedTypeSet, OrderedTypeSetBuilder; 42 isMinusOperator,
68 import '../types/types.dart' show TypeMask; 43 isTernaryOperator,
69 import '../util/util.dart'; 44 isUnaryOperator,
70 import '../universe/universe.dart' show 45 isUserDefinableOperator;
71 CallStructure, 46 import '../tree/tree.dart';
72 Selector, 47 import '../util/util.dart' show
73 SelectorKind, 48 Link,
74 UniverseSelector; 49 LinkBuilder,
75 import '../world.dart' show World; 50 Setlet;
76 51
77 import 'access_semantics.dart'; 52 import 'class_hierarchy.dart';
78 import 'class_members.dart' show MembersCreator; 53 import 'class_members.dart' show MembersCreator;
79 import 'enum_creator.dart'; 54 import 'constructors.dart';
80 import 'operators.dart'; 55 import 'members.dart';
81 import 'secret_tree_element.dart' show getTreeElement, setTreeElement; 56 import 'registry.dart';
82 import 'send_structure.dart'; 57 import 'signatures.dart';
83 58 import 'tree_elements.dart';
84 part 'class_hierarchy.dart'; 59 import 'typedefs.dart';
85 part 'constructors.dart'; 60
Johnni Winther 2015/08/17 08:01:34 The rest of the file is moved here from resolver_c
86 part 'label_scope.dart'; 61 class ResolverTask extends CompilerTask {
87 part 'members.dart'; 62 final ConstantCompiler constantCompiler;
88 part 'registry.dart'; 63
89 part 'resolution_common.dart'; 64 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler);
90 part 'resolution_result.dart'; 65
91 part 'scope.dart'; 66 String get name => 'Resolver';
92 part 'signatures.dart'; 67
93 part 'tree_elements.dart'; 68 WorldImpact resolve(Element element) {
94 part 'typedefs.dart'; 69 return measure(() {
95 part 'type_resolver.dart'; 70 if (Elements.isErroneous(element)) {
96 part 'variables.dart'; 71 // TODO(johnniwinther): Add a predicate for this.
72 assert(invariant(element, element is! ErroneousElement,
73 message: "Element $element expected to have parse errors."));
74 _ensureTreeElements(element);
75 return const WorldImpact();
76 }
77
78 WorldImpact processMetadata([WorldImpact result]) {
79 for (MetadataAnnotation metadata in element.metadata) {
80 metadata.ensureResolved(compiler);
81 }
82 return result;
83 }
84
85 ElementKind kind = element.kind;
86 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) ||
87 identical(kind, ElementKind.FUNCTION) ||
88 identical(kind, ElementKind.GETTER) ||
89 identical(kind, ElementKind.SETTER)) {
90 return processMetadata(resolveMethodElement(element));
91 }
92
93 if (identical(kind, ElementKind.FIELD)) {
94 return processMetadata(resolveField(element));
95 }
96 if (element.isClass) {
97 ClassElement cls = element;
98 cls.ensureResolved(compiler);
99 return processMetadata(const WorldImpact());
100 } else if (element.isTypedef) {
101 TypedefElement typdef = element;
102 return processMetadata(resolveTypedef(typdef));
103 }
104
105 compiler.unimplemented(element, "resolve($element)");
106 });
107 }
108
109 void resolveRedirectingConstructor(InitializerResolver resolver,
110 Node node,
111 FunctionElement constructor,
112 FunctionElement redirection) {
113 assert(invariant(node, constructor.isImplementation,
114 message: 'Redirecting constructors must be resolved on implementation '
115 'elements.'));
116 Setlet<FunctionElement> seen = new Setlet<FunctionElement>();
117 seen.add(constructor);
118 while (redirection != null) {
119 // Ensure that we follow redirections through implementation elements.
120 redirection = redirection.implementation;
121 if (seen.contains(redirection)) {
122 resolver.visitor.error(node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE);
123 return;
124 }
125 seen.add(redirection);
126 redirection = resolver.visitor.resolveConstructorRedirection(redirection);
127 }
128 }
129
130 static void processAsyncMarker(Compiler compiler,
131 BaseFunctionElementX element,
132 ResolutionRegistry registry) {
133 FunctionExpression functionExpression = element.node;
134 AsyncModifier asyncModifier = functionExpression.asyncModifier;
135 if (asyncModifier != null) {
136
137 if (asyncModifier.isAsynchronous) {
138 element.asyncMarker = asyncModifier.isYielding
139 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC;
140 } else {
141 element.asyncMarker = AsyncMarker.SYNC_STAR;
142 }
143 if (element.isAbstract) {
144 compiler.reportError(asyncModifier,
145 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD,
146 {'modifier': element.asyncMarker});
147 } else if (element.isConstructor) {
148 compiler.reportError(asyncModifier,
149 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR,
150 {'modifier': element.asyncMarker});
151 } else {
152 if (element.isSetter) {
153 compiler.reportError(asyncModifier,
154 MessageKind.ASYNC_MODIFIER_ON_SETTER,
155 {'modifier': element.asyncMarker});
156
157 }
158 if (functionExpression.body.asReturn() != null &&
159 element.asyncMarker.isYielding) {
160 compiler.reportError(asyncModifier,
161 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY,
162 {'modifier': element.asyncMarker});
163 }
164 }
165 registry.registerAsyncMarker(element);
166 switch (element.asyncMarker) {
167 case AsyncMarker.ASYNC:
168 compiler.futureClass.ensureResolved(compiler);
169 break;
170 case AsyncMarker.ASYNC_STAR:
171 compiler.streamClass.ensureResolved(compiler);
172 break;
173 case AsyncMarker.SYNC_STAR:
174 compiler.iterableClass.ensureResolved(compiler);
175 break;
176 }
177 }
178 }
179
180 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) {
181 assert(classElement != null);
182 while (classElement != null) {
183 if (classElement.isNative) return true;
184 classElement = classElement.superclass;
185 }
186 return false;
187 }
188
189 WorldImpact resolveMethodElementImplementation(
190 FunctionElement element, FunctionExpression tree) {
191 return compiler.withCurrentElement(element, () {
192 if (element.isExternal && tree.hasBody()) {
193 error(element,
194 MessageKind.EXTERNAL_WITH_BODY,
195 {'functionName': element.name});
196 }
197 if (element.isConstructor) {
198 if (tree.returnType != null) {
199 error(tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE);
200 }
201 if (element.isConst &&
202 tree.hasBody() &&
203 !tree.isRedirectingFactory) {
204 error(tree, MessageKind.CONST_CONSTRUCTOR_HAS_BODY);
205 }
206 }
207
208 ResolverVisitor visitor = visitorFor(element);
209 ResolutionRegistry registry = visitor.registry;
210 registry.defineFunction(tree, element);
211 visitor.setupFunction(tree, element);
212 processAsyncMarker(compiler, element, registry);
213
214 if (element.isGenerativeConstructor) {
215 // Even if there is no initializer list we still have to do the
216 // resolution in case there is an implicit super constructor call.
217 InitializerResolver resolver =
218 new InitializerResolver(visitor, element, tree);
219 FunctionElement redirection = resolver.resolveInitializers();
220 if (redirection != null) {
221 resolveRedirectingConstructor(resolver, tree, element, redirection);
222 }
223 } else if (tree.initializers != null) {
224 error(tree, MessageKind.FUNCTION_WITH_INITIALIZER);
225 }
226
227 if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) {
228 // We need to analyze the redirecting factory bodies to ensure that
229 // we can analyze compile-time constants.
230 visitor.visit(tree.body);
231 }
232
233 // Get the resolution tree and check that the resolved
234 // function doesn't use 'super' if it is mixed into another
235 // class. This is the part of the 'super' mixin check that
236 // happens when a function is resolved after the mixin
237 // application has been performed.
238 TreeElements resolutionTree = registry.mapping;
239 ClassElement enclosingClass = element.enclosingClass;
240 if (enclosingClass != null) {
241 // TODO(johnniwinther): Find another way to obtain mixin uses.
242 Iterable<MixinApplicationElement> mixinUses =
243 compiler.world.allMixinUsesOf(enclosingClass);
244 ClassElement mixin = enclosingClass;
245 for (MixinApplicationElement mixinApplication in mixinUses) {
246 checkMixinSuperUses(resolutionTree, mixinApplication, mixin);
247 }
248 }
249
250 // TODO(9631): support noSuchMethod on native classes.
251 if (Elements.isInstanceMethod(element) &&
252 element.name == Compiler.NO_SUCH_METHOD &&
253 _isNativeClassOrExtendsNativeClass(enclosingClass)) {
254 error(tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE);
255 }
256
257 return registry.worldImpact;
258 });
259
260 }
261
262 WorldImpact resolveMethodElement(FunctionElementX element) {
263 assert(invariant(element, element.isDeclaration));
264 return compiler.withCurrentElement(element, () {
265 if (compiler.enqueuer.resolution.hasBeenResolved(element)) {
266 // TODO(karlklose): Remove the check for [isConstructor]. [elememts]
267 // should never be non-null, not even for constructors.
268 assert(invariant(element, element.isConstructor,
269 message: 'Non-constructor element $element '
270 'has already been analyzed.'));
271 return const WorldImpact();
272 }
273 if (element.isSynthesized) {
274 if (element.isGenerativeConstructor) {
275 ResolutionRegistry registry =
276 new ResolutionRegistry(compiler, _ensureTreeElements(element));
277 ConstructorElement constructor = element.asFunctionElement();
278 ConstructorElement target = constructor.definingConstructor;
279 // Ensure the signature of the synthesized element is
280 // resolved. This is the only place where the resolver is
281 // seeing this element.
282 element.computeSignature(compiler);
283 if (!target.isErroneous) {
284 registry.registerStaticUse(target);
285 registry.registerImplicitSuperCall(target);
286 }
287 return registry.worldImpact;
288 } else {
289 assert(element.isDeferredLoaderGetter || element.isErroneous);
290 _ensureTreeElements(element);
291 return const WorldImpact();
292 }
293 } else {
294 element.parseNode(compiler);
295 element.computeType(compiler);
296 FunctionElementX implementation = element;
297 if (element.isExternal) {
298 implementation = compiler.backend.resolveExternalFunction(element);
299 }
300 return resolveMethodElementImplementation(
301 implementation, implementation.node);
302 }
303 });
304 }
305
306 /// Creates a [ResolverVisitor] for resolving an AST in context of [element].
307 /// If [useEnclosingScope] is `true` then the initial scope of the visitor
308 /// does not include inner scope of [element].
309 ///
310 /// This method should only be used by this library (or tests of
311 /// this library).
312 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) {
313 return new ResolverVisitor(compiler, element,
314 new ResolutionRegistry(compiler, _ensureTreeElements(element)),
315 useEnclosingScope: useEnclosingScope);
316 }
317
318 WorldImpact resolveField(FieldElementX element) {
319 VariableDefinitions tree = element.parseNode(compiler);
320 if(element.modifiers.isStatic && element.isTopLevel) {
321 error(element.modifiers.getStatic(),
322 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC);
323 }
324 ResolverVisitor visitor = visitorFor(element);
325 ResolutionRegistry registry = visitor.registry;
326 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates
327 // to the backend ast.
328 registry.defineElement(tree.definitions.nodes.head, element);
329 // TODO(johnniwinther): Share the resolved type between all variables
330 // declared in the same declaration.
331 if (tree.type != null) {
332 element.variables.type = visitor.resolveTypeAnnotation(tree.type);
333 } else {
334 element.variables.type = const DynamicType();
335 }
336
337 Expression initializer = element.initializer;
338 Modifiers modifiers = element.modifiers;
339 if (initializer != null) {
340 // TODO(johnniwinther): Avoid analyzing initializers if
341 // [Compiler.analyzeSignaturesOnly] is set.
342 visitor.visit(initializer);
343 } else if (modifiers.isConst) {
344 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER);
345 } else if (modifiers.isFinal && !element.isInstanceMember) {
346 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER);
347 } else {
348 registry.registerInstantiatedClass(compiler.nullClass);
349 }
350
351 if (Elements.isStaticOrTopLevelField(element)) {
352 visitor.addDeferredAction(element, () {
353 if (element.modifiers.isConst) {
354 element.constant = constantCompiler.compileConstant(element);
355 } else {
356 constantCompiler.compileVariable(element);
357 }
358 });
359 if (initializer != null) {
360 if (!element.modifiers.isConst) {
361 // TODO(johnniwinther): Determine the const-ness eagerly to avoid
362 // unnecessary registrations.
363 registry.registerLazyField();
364 }
365 }
366 }
367
368 // Perform various checks as side effect of "computing" the type.
369 element.computeType(compiler);
370
371 return registry.worldImpact;
372 }
373
374 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) {
375 DartType type = resolveReturnType(element, annotation);
376 if (type.isVoid) {
377 error(annotation, MessageKind.VOID_NOT_ALLOWED);
378 }
379 return type;
380 }
381
382 DartType resolveReturnType(Element element, TypeAnnotation annotation) {
383 if (annotation == null) return const DynamicType();
384 DartType result = visitorFor(element).resolveTypeAnnotation(annotation);
385 if (result == null) {
386 // TODO(karklose): warning.
387 return const DynamicType();
388 }
389 return result;
390 }
391
392 void resolveRedirectionChain(ConstructorElementX constructor,
393 Spannable node) {
394 ConstructorElementX target = constructor;
395 InterfaceType targetType;
396 List<Element> seen = new List<Element>();
397 // Follow the chain of redirections and check for cycles.
398 while (target.isRedirectingFactory) {
399 if (target.internalEffectiveTarget != null) {
400 // We found a constructor that already has been processed.
401 targetType = target.effectiveTargetType;
402 assert(invariant(target, targetType != null,
403 message: 'Redirection target type has not been computed for '
404 '$target'));
405 target = target.internalEffectiveTarget;
406 break;
407 }
408
409 Element nextTarget = target.immediateRedirectionTarget;
410 if (seen.contains(nextTarget)) {
411 error(node, MessageKind.CYCLIC_REDIRECTING_FACTORY);
412 targetType = target.enclosingClass.thisType;
413 break;
414 }
415 seen.add(target);
416 target = nextTarget;
417 }
418
419 if (targetType == null) {
420 assert(!target.isRedirectingFactory);
421 targetType = target.enclosingClass.thisType;
422 }
423
424 // [target] is now the actual target of the redirections. Run through
425 // the constructors again and set their [redirectionTarget], so that we
426 // do not have to run the loop for these constructors again. Furthermore,
427 // compute [redirectionTargetType] for each factory by computing the
428 // substitution of the target type with respect to the factory type.
429 while (!seen.isEmpty) {
430 ConstructorElementX factory = seen.removeLast();
431
432 // [factory] must already be analyzed but the [TreeElements] might not
433 // have been stored in the enqueuer cache yet.
434 // TODO(johnniwinther): Store [TreeElements] in the cache before
435 // resolution of the element.
436 TreeElements treeElements = factory.treeElements;
437 assert(invariant(node, treeElements != null,
438 message: 'No TreeElements cached for $factory.'));
439 FunctionExpression functionNode = factory.parseNode(compiler);
440 RedirectingFactoryBody redirectionNode = functionNode.body;
441 DartType factoryType = treeElements.getType(redirectionNode);
442 if (!factoryType.isDynamic) {
443 targetType = targetType.substByContext(factoryType);
444 }
445 factory.effectiveTarget = target;
446 factory.effectiveTargetType = targetType;
447 }
448 }
449
450 /**
451 * Load and resolve the supertypes of [cls].
452 *
453 * Warning: do not call this method directly. It should only be
454 * called by [resolveClass] and [ClassSupertypeResolver].
455 */
456 void loadSupertypes(BaseClassElementX cls, Spannable from) {
457 compiler.withCurrentElement(cls, () => measure(() {
458 if (cls.supertypeLoadState == STATE_DONE) return;
459 if (cls.supertypeLoadState == STATE_STARTED) {
460 compiler.reportError(from, MessageKind.CYCLIC_CLASS_HIERARCHY,
461 {'className': cls.name});
462 cls.supertypeLoadState = STATE_DONE;
463 cls.hasIncompleteHierarchy = true;
464 cls.allSupertypesAndSelf =
465 compiler.objectClass.allSupertypesAndSelf.extendClass(
466 cls.computeType(compiler));
467 cls.supertype = cls.allSupertypes.head;
468 assert(invariant(from, cls.supertype != null,
469 message: 'Missing supertype on cyclic class $cls.'));
470 cls.interfaces = const Link<DartType>();
471 return;
472 }
473 cls.supertypeLoadState = STATE_STARTED;
474 compiler.withCurrentElement(cls, () {
475 // TODO(ahe): Cache the node in cls.
476 cls.parseNode(compiler).accept(
477 new ClassSupertypeResolver(compiler, cls));
478 if (cls.supertypeLoadState != STATE_DONE) {
479 cls.supertypeLoadState = STATE_DONE;
480 }
481 });
482 }));
483 }
484
485 // TODO(johnniwinther): Remove this queue when resolution has been split into
486 // syntax and semantic resolution.
487 TypeDeclarationElement currentlyResolvedTypeDeclaration;
488 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>();
489 Queue<ClassElement> pendingClassesToBePostProcessed =
490 new Queue<ClassElement>();
491
492 /// Resolve [element] using [resolveTypeDeclaration].
493 ///
494 /// This methods ensure that class declarations encountered through type
495 /// annotations during the resolution of [element] are resolved after
496 /// [element] has been resolved.
497 // TODO(johnniwinther): Encapsulate this functionality in a
498 // 'TypeDeclarationResolver'.
499 _resolveTypeDeclaration(TypeDeclarationElement element,
500 resolveTypeDeclaration()) {
501 return compiler.withCurrentElement(element, () {
502 return measure(() {
503 TypeDeclarationElement previousResolvedTypeDeclaration =
504 currentlyResolvedTypeDeclaration;
505 currentlyResolvedTypeDeclaration = element;
506 var result = resolveTypeDeclaration();
507 if (previousResolvedTypeDeclaration == null) {
508 do {
509 while (!pendingClassesToBeResolved.isEmpty) {
510 pendingClassesToBeResolved.removeFirst().ensureResolved(compiler);
511 }
512 while (!pendingClassesToBePostProcessed.isEmpty) {
513 _postProcessClassElement(
514 pendingClassesToBePostProcessed.removeFirst());
515 }
516 } while (!pendingClassesToBeResolved.isEmpty);
517 assert(pendingClassesToBeResolved.isEmpty);
518 assert(pendingClassesToBePostProcessed.isEmpty);
519 }
520 currentlyResolvedTypeDeclaration = previousResolvedTypeDeclaration;
521 return result;
522 });
523 });
524 }
525
526 /**
527 * Resolve the class [element].
528 *
529 * Before calling this method, [element] was constructed by the
530 * scanner and most fields are null or empty. This method fills in
531 * these fields and also ensure that the supertypes of [element] are
532 * resolved.
533 *
534 * Warning: Do not call this method directly. Instead use
535 * [:element.ensureResolved(compiler):].
536 */
537 TreeElements resolveClass(BaseClassElementX element) {
538 return _resolveTypeDeclaration(element, () {
539 // TODO(johnniwinther): Store the mapping in the resolution enqueuer.
540 ResolutionRegistry registry =
541 new ResolutionRegistry(compiler, _ensureTreeElements(element));
542 resolveClassInternal(element, registry);
543 return element.treeElements;
544 });
545 }
546
547 void ensureClassWillBeResolvedInternal(ClassElement element) {
548 if (currentlyResolvedTypeDeclaration == null) {
549 element.ensureResolved(compiler);
550 } else {
551 pendingClassesToBeResolved.add(element);
552 }
553 }
554
555 void resolveClassInternal(BaseClassElementX element,
556 ResolutionRegistry registry) {
557 if (!element.isPatch) {
558 compiler.withCurrentElement(element, () => measure(() {
559 assert(element.resolutionState == STATE_NOT_STARTED);
560 element.resolutionState = STATE_STARTED;
561 Node tree = element.parseNode(compiler);
562 loadSupertypes(element, tree);
563
564 ClassResolverVisitor visitor =
565 new ClassResolverVisitor(compiler, element, registry);
566 visitor.visit(tree);
567 element.resolutionState = STATE_DONE;
568 compiler.onClassResolved(element);
569 pendingClassesToBePostProcessed.add(element);
570 }));
571 if (element.isPatched) {
572 // Ensure handling patch after origin.
573 element.patch.ensureResolved(compiler);
574 }
575 } else { // Handle patch classes:
576 element.resolutionState = STATE_STARTED;
577 // Ensure handling origin before patch.
578 element.origin.ensureResolved(compiler);
579 // Ensure that the type is computed.
580 element.computeType(compiler);
581 // Copy class hierarchy from origin.
582 element.supertype = element.origin.supertype;
583 element.interfaces = element.origin.interfaces;
584 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf;
585 // Stepwise assignment to ensure invariant.
586 element.supertypeLoadState = STATE_STARTED;
587 element.supertypeLoadState = STATE_DONE;
588 element.resolutionState = STATE_DONE;
589 // TODO(johnniwinther): Check matching type variables and
590 // empty extends/implements clauses.
591 }
592 }
593
594 void _postProcessClassElement(BaseClassElementX element) {
595 for (MetadataAnnotation metadata in element.metadata) {
596 metadata.ensureResolved(compiler);
597 ConstantValue value =
598 compiler.constants.getConstantValue(metadata.constant);
599 if (!element.isProxy && value == compiler.proxyConstant) {
600 element.isProxy = true;
601 }
602 }
603
604 // Force resolution of metadata on non-instance members since they may be
605 // inspected by the backend while emitting. Metadata on instance members is
606 // handled as a result of processing instantiated class members in the
607 // enqueuer.
608 // TODO(ahe): Avoid this eager resolution.
609 element.forEachMember((_, Element member) {
610 if (!member.isInstanceMember) {
611 compiler.withCurrentElement(member, () {
612 for (MetadataAnnotation metadata in member.metadata) {
613 metadata.ensureResolved(compiler);
614 }
615 });
616 }
617 });
618
619 computeClassMember(element, Compiler.CALL_OPERATOR_NAME);
620 }
621
622 void computeClassMembers(ClassElement element) {
623 MembersCreator.computeAllClassMembers(compiler, element);
624 }
625
626 void computeClassMember(ClassElement element, String name) {
627 MembersCreator.computeClassMembersByName(compiler, element, name);
628 }
629
630 void checkClass(ClassElement element) {
631 computeClassMembers(element);
632 if (element.isMixinApplication) {
633 checkMixinApplication(element);
634 } else {
635 checkClassMembers(element);
636 }
637 }
638
639 void checkMixinApplication(MixinApplicationElementX mixinApplication) {
640 Modifiers modifiers = mixinApplication.modifiers;
641 int illegalFlags = modifiers.flags & ~Modifiers.FLAG_ABSTRACT;
642 if (illegalFlags != 0) {
643 Modifiers illegalModifiers = new Modifiers.withFlags(null, illegalFlags);
644 compiler.reportError(
645 modifiers,
646 MessageKind.ILLEGAL_MIXIN_APPLICATION_MODIFIERS,
647 {'modifiers': illegalModifiers});
648 }
649
650 // In case of cyclic mixin applications, the mixin chain will have
651 // been cut. If so, we have already reported the error to the
652 // user so we just return from here.
653 ClassElement mixin = mixinApplication.mixin;
654 if (mixin == null) return;
655
656 // Check that we're not trying to use Object as a mixin.
657 if (mixin.superclass == null) {
658 compiler.reportError(mixinApplication,
659 MessageKind.ILLEGAL_MIXIN_OBJECT);
660 // Avoid reporting additional errors for the Object class.
661 return;
662 }
663
664 if (mixin.isEnumClass) {
665 // Mixing in an enum has already caused a compile-time error.
666 return;
667 }
668
669 // Check that the mixed in class has Object as its superclass.
670 if (!mixin.superclass.isObject) {
671 compiler.reportError(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS);
672 }
673
674 // Check that the mixed in class doesn't have any constructors and
675 // make sure we aren't mixing in methods that use 'super'.
676 mixin.forEachLocalMember((AstElement member) {
677 if (member.isGenerativeConstructor && !member.isSynthesized) {
678 compiler.reportError(member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR);
679 } else {
680 // Get the resolution tree and check that the resolved member
681 // doesn't use 'super'. This is the part of the 'super' mixin
682 // check that happens when a function is resolved before the
683 // mixin application has been performed.
684 // TODO(johnniwinther): Obtain the [TreeElements] for [member]
685 // differently.
686 if (compiler.enqueuer.resolution.hasBeenResolved(member)) {
687 checkMixinSuperUses(
688 member.resolvedAst.elements,
689 mixinApplication,
690 mixin);
691 }
692 }
693 });
694 }
695
696 void checkMixinSuperUses(TreeElements resolutionTree,
697 MixinApplicationElement mixinApplication,
698 ClassElement mixin) {
699 // TODO(johnniwinther): Avoid the use of [TreeElements] here.
700 if (resolutionTree == null) return;
701 Iterable<Node> superUses = resolutionTree.superUses;
702 if (superUses.isEmpty) return;
703 compiler.reportError(mixinApplication,
704 MessageKind.ILLEGAL_MIXIN_WITH_SUPER,
705 {'className': mixin.name});
706 // Show the user the problematic uses of 'super' in the mixin.
707 for (Node use in superUses) {
708 compiler.reportInfo(
709 use,
710 MessageKind.ILLEGAL_MIXIN_SUPER_USE);
711 }
712 }
713
714 void checkClassMembers(ClassElement cls) {
715 assert(invariant(cls, cls.isDeclaration));
716 if (cls.isObject) return;
717 // TODO(johnniwinther): Should this be done on the implementation element as
718 // well?
719 List<Element> constConstructors = <Element>[];
720 List<Element> nonFinalInstanceFields = <Element>[];
721 cls.forEachMember((holder, member) {
722 compiler.withCurrentElement(member, () {
723 // Perform various checks as side effect of "computing" the type.
724 member.computeType(compiler);
725
726 // Check modifiers.
727 if (member.isFunction && member.modifiers.isFinal) {
728 compiler.reportError(
729 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER);
730 }
731 if (member.isConstructor) {
732 final mismatchedFlagsBits =
733 member.modifiers.flags &
734 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT);
735 if (mismatchedFlagsBits != 0) {
736 final mismatchedFlags =
737 new Modifiers.withFlags(null, mismatchedFlagsBits);
738 compiler.reportError(
739 member,
740 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS,
741 {'modifiers': mismatchedFlags});
742 }
743 if (member.modifiers.isConst) {
744 constConstructors.add(member);
745 }
746 }
747 if (member.isField) {
748 if (member.modifiers.isConst && !member.modifiers.isStatic) {
749 compiler.reportError(
750 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER);
751 }
752 if (!member.modifiers.isStatic && !member.modifiers.isFinal) {
753 nonFinalInstanceFields.add(member);
754 }
755 }
756 checkAbstractField(member);
757 checkUserDefinableOperator(member);
758 });
759 });
760 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) {
761 Spannable span = constConstructors.length > 1
762 ? cls : constConstructors[0];
763 compiler.reportError(span,
764 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS,
765 {'className': cls.name});
766 if (constConstructors.length > 1) {
767 for (Element constructor in constConstructors) {
768 compiler.reportInfo(constructor,
769 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR);
770 }
771 }
772 for (Element field in nonFinalInstanceFields) {
773 compiler.reportInfo(field,
774 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD);
775 }
776 }
777 }
778
779 void checkAbstractField(Element member) {
780 // Only check for getters. The test can only fail if there is both a setter
781 // and a getter with the same name, and we only need to check each abstract
782 // field once, so we just ignore setters.
783 if (!member.isGetter) return;
784
785 // Find the associated abstract field.
786 ClassElement classElement = member.enclosingClass;
787 Element lookupElement = classElement.lookupLocalMember(member.name);
788 if (lookupElement == null) {
789 compiler.internalError(member,
790 "No abstract field for accessor");
791 } else if (!identical(lookupElement.kind, ElementKind.ABSTRACT_FIELD)) {
792 if (lookupElement.isErroneous || lookupElement.isAmbiguous) return;
793 compiler.internalError(member,
794 "Inaccessible abstract field for accessor");
795 }
796 AbstractFieldElement field = lookupElement;
797
798 GetterElementX getter = field.getter;
799 if (getter == null) return;
800 SetterElementX setter = field.setter;
801 if (setter == null) return;
802 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
803 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT;
804 if (!identical(getterFlags, setterFlags)) {
805 final mismatchedFlags =
806 new Modifiers.withFlags(null, getterFlags ^ setterFlags);
807 compiler.reportError(
808 field.getter,
809 MessageKind.GETTER_MISMATCH,
810 {'modifiers': mismatchedFlags});
811 compiler.reportError(
812 field.setter,
813 MessageKind.SETTER_MISMATCH,
814 {'modifiers': mismatchedFlags});
815 }
816 }
817
818 void checkUserDefinableOperator(Element member) {
819 FunctionElement function = member.asFunctionElement();
820 if (function == null) return;
821 String value = member.name;
822 if (value == null) return;
823 if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return;
824
825 bool isMinus = false;
826 int requiredParameterCount;
827 MessageKind messageKind;
828 if (identical(value, 'unary-')) {
829 isMinus = true;
830 messageKind = MessageKind.MINUS_OPERATOR_BAD_ARITY;
831 requiredParameterCount = 0;
832 } else if (isMinusOperator(value)) {
833 isMinus = true;
834 messageKind = MessageKind.MINUS_OPERATOR_BAD_ARITY;
835 requiredParameterCount = 1;
836 } else if (isUnaryOperator(value)) {
837 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY;
838 requiredParameterCount = 0;
839 } else if (isBinaryOperator(value)) {
840 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY;
841 requiredParameterCount = 1;
842 if (identical(value, '==')) checkOverrideHashCode(member);
843 } else if (isTernaryOperator(value)) {
844 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY;
845 requiredParameterCount = 2;
846 } else {
847 compiler.internalError(function,
848 'Unexpected user defined operator $value');
849 }
850 checkArity(function, requiredParameterCount, messageKind, isMinus);
851 }
852
853 void checkOverrideHashCode(FunctionElement operatorEquals) {
854 if (operatorEquals.isAbstract) return;
855 ClassElement cls = operatorEquals.enclosingClass;
856 Element hashCodeImplementation =
857 cls.lookupLocalMember('hashCode');
858 if (hashCodeImplementation != null) return;
859 compiler.reportHint(
860 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE,
861 {'class': cls.name});
862 }
863
864 void checkArity(FunctionElement function,
865 int requiredParameterCount, MessageKind messageKind,
866 bool isMinus) {
867 FunctionExpression node = function.node;
868 FunctionSignature signature = function.functionSignature;
869 if (signature.requiredParameterCount != requiredParameterCount) {
870 Node errorNode = node;
871 if (node.parameters != null) {
872 if (isMinus ||
873 signature.requiredParameterCount < requiredParameterCount) {
874 // If there are too few parameters, point to the whole parameter list.
875 // For instance
876 //
877 // int operator +() {}
878 // ^^
879 //
880 // int operator []=(value) {}
881 // ^^^^^^^
882 //
883 // For operator -, always point the whole parameter list, like
884 //
885 // int operator -(a, b) {}
886 // ^^^^^^
887 //
888 // instead of
889 //
890 // int operator -(a, b) {}
891 // ^
892 //
893 // since the correction might not be to remove 'b' but instead to
894 // remove 'a, b'.
895 errorNode = node.parameters;
896 } else {
897 errorNode = node.parameters.nodes.skip(requiredParameterCount).head;
898 }
899 }
900 compiler.reportError(
901 errorNode, messageKind, {'operatorName': function.name});
902 }
903 if (signature.optionalParameterCount != 0) {
904 Node errorNode =
905 node.parameters.nodes.skip(signature.requiredParameterCount).head;
906 if (signature.optionalParametersAreNamed) {
907 compiler.reportError(
908 errorNode,
909 MessageKind.OPERATOR_NAMED_PARAMETERS,
910 {'operatorName': function.name});
911 } else {
912 compiler.reportError(
913 errorNode,
914 MessageKind.OPERATOR_OPTIONAL_PARAMETERS,
915 {'operatorName': function.name});
916 }
917 }
918 }
919
920 reportErrorWithContext(Element errorneousElement,
921 MessageKind errorMessage,
922 Element contextElement,
923 MessageKind contextMessage) {
924 compiler.reportError(
925 errorneousElement,
926 errorMessage,
927 {'memberName': contextElement.name,
928 'className': contextElement.enclosingClass.name});
929 compiler.reportInfo(contextElement, contextMessage);
930 }
931
932
933 FunctionSignature resolveSignature(FunctionElementX element) {
934 MessageKind defaultValuesError = null;
935 if (element.isFactoryConstructor) {
936 FunctionExpression body = element.parseNode(compiler);
937 if (body.isRedirectingFactory) {
938 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT;
939 }
940 }
941 return compiler.withCurrentElement(element, () {
942 FunctionExpression node =
943 compiler.parser.measure(() => element.parseNode(compiler));
944 return measure(() => SignatureResolver.analyze(
945 compiler, node.parameters, node.returnType, element,
946 new ResolutionRegistry(compiler, _ensureTreeElements(element)),
947 defaultValuesError: defaultValuesError,
948 createRealParameters: true));
949 });
950 }
951
952 WorldImpact resolveTypedef(TypedefElementX element) {
953 if (element.isResolved) return const WorldImpact();
954 compiler.world.allTypedefs.add(element);
955 return _resolveTypeDeclaration(element, () {
956 ResolutionRegistry registry = new ResolutionRegistry(
957 compiler, _ensureTreeElements(element));
958 return compiler.withCurrentElement(element, () {
959 return measure(() {
960 assert(element.resolutionState == STATE_NOT_STARTED);
961 element.resolutionState = STATE_STARTED;
962 Typedef node =
963 compiler.parser.measure(() => element.parseNode(compiler));
964 TypedefResolverVisitor visitor =
965 new TypedefResolverVisitor(compiler, element, registry);
966 visitor.visit(node);
967 element.resolutionState = STATE_DONE;
968 return registry.worldImpact;
969 });
970 });
971 });
972 }
973
974 void resolveMetadataAnnotation(MetadataAnnotationX annotation) {
975 compiler.withCurrentElement(annotation.annotatedElement, () => measure(() {
976 assert(annotation.resolutionState == STATE_NOT_STARTED);
977 annotation.resolutionState = STATE_STARTED;
978
979 Node node = annotation.parseNode(compiler);
980 Element annotatedElement = annotation.annotatedElement;
981 AnalyzableElement context = annotatedElement.analyzableElement;
982 ClassElement classElement = annotatedElement.enclosingClass;
983 if (classElement != null) {
984 // The annotation is resolved in the scope of [classElement].
985 classElement.ensureResolved(compiler);
986 }
987 assert(invariant(node, context != null,
988 message: "No context found for metadata annotation "
989 "on $annotatedElement."));
990 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true);
991 ResolutionRegistry registry = visitor.registry;
992 node.accept(visitor);
993 // TODO(johnniwinther): Avoid passing the [TreeElements] to
994 // [compileMetadata].
995 annotation.constant =
996 constantCompiler.compileMetadata(annotation, node, registry.mapping);
997 // TODO(johnniwinther): Register the relation between the annotation
998 // and the annotated element instead. This will allow the backend to
999 // retrieve the backend constant and only register metadata on the
1000 // elements for which it is needed. (Issue 17732).
1001 registry.registerMetadataConstant(annotation, annotatedElement);
1002 annotation.resolutionState = STATE_DONE;
1003 }));
1004 }
1005
1006 error(Spannable node, MessageKind kind, [arguments = const {}]) {
1007 compiler.reportError(node, kind, arguments);
1008 }
1009
1010 Link<MetadataAnnotation> resolveMetadata(Element element,
1011 VariableDefinitions node) {
1012 LinkBuilder<MetadataAnnotation> metadata =
1013 new LinkBuilder<MetadataAnnotation>();
1014 for (Metadata annotation in node.metadata.nodes) {
1015 ParameterMetadataAnnotation metadataAnnotation =
1016 new ParameterMetadataAnnotation(annotation);
1017 metadataAnnotation.annotatedElement = element;
1018 metadata.addLast(metadataAnnotation.ensureResolved(compiler));
1019 }
1020 return metadata.toLink();
1021 }
1022 }
1023
1024 TreeElements _ensureTreeElements(AnalyzableElementX element) {
1025 if (element._treeElements == null) {
1026 element._treeElements = new TreeElementMapping(element);
1027 }
1028 return element._treeElements;
1029 }
1030
1031 abstract class AnalyzableElementX implements AnalyzableElement {
1032 TreeElements _treeElements;
1033
1034 bool get hasTreeElements => _treeElements != null;
1035
1036 TreeElements get treeElements {
1037 assert(invariant(this, _treeElements !=null,
1038 message: "TreeElements have not been computed for $this."));
1039 return _treeElements;
1040 }
1041
1042 void reuseElement() {
1043 _treeElements = null;
1044 }
1045 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/registry.dart ('k') | pkg/compiler/lib/src/resolution/resolution_common.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698