| OLD | NEW |
| 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 dart2js.resolution; | 5 library dart2js.resolution; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
| 8 | 8 |
| 9 import '../common/names.dart' show | 9 import '../common/names.dart' show |
| 10 Identifiers; | 10 Identifiers; |
| 11 import '../common/resolution.dart' show |
| 12 Parsing, |
| 13 Resolution; |
| 11 import '../common/tasks.dart' show | 14 import '../common/tasks.dart' show |
| 12 CompilerTask, | 15 CompilerTask, |
| 13 DeferredAction; | 16 DeferredAction; |
| 14 import '../compiler.dart' show | 17 import '../compiler.dart' show |
| 15 Compiler; | 18 Compiler; |
| 16 import '../compile_time_constants.dart' show | 19 import '../compile_time_constants.dart' show |
| 17 ConstantCompiler; | 20 ConstantCompiler; |
| 18 import '../constants/values.dart' show | 21 import '../constants/values.dart' show |
| 19 ConstantValue; | 22 ConstantValue; |
| 20 import '../dart_types.dart'; | 23 import '../dart_types.dart'; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 import 'tree_elements.dart'; | 65 import 'tree_elements.dart'; |
| 63 import 'typedefs.dart'; | 66 import 'typedefs.dart'; |
| 64 | 67 |
| 65 class ResolverTask extends CompilerTask { | 68 class ResolverTask extends CompilerTask { |
| 66 final ConstantCompiler constantCompiler; | 69 final ConstantCompiler constantCompiler; |
| 67 | 70 |
| 68 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler); | 71 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler); |
| 69 | 72 |
| 70 String get name => 'Resolver'; | 73 String get name => 'Resolver'; |
| 71 | 74 |
| 75 Resolution get resolution => compiler.resolution; |
| 76 |
| 77 Parsing get parsing => compiler.parsing; |
| 78 |
| 72 WorldImpact resolve(Element element) { | 79 WorldImpact resolve(Element element) { |
| 73 return measure(() { | 80 return measure(() { |
| 74 if (Elements.isErroneous(element)) { | 81 if (Elements.isErroneous(element)) { |
| 75 // TODO(johnniwinther): Add a predicate for this. | 82 // TODO(johnniwinther): Add a predicate for this. |
| 76 assert(invariant(element, element is! ErroneousElement, | 83 assert(invariant(element, element is! ErroneousElement, |
| 77 message: "Element $element expected to have parse errors.")); | 84 message: "Element $element expected to have parse errors.")); |
| 78 _ensureTreeElements(element); | 85 _ensureTreeElements(element); |
| 79 return const WorldImpact(); | 86 return const WorldImpact(); |
| 80 } | 87 } |
| 81 | 88 |
| 82 WorldImpact processMetadata([WorldImpact result]) { | 89 WorldImpact processMetadata([WorldImpact result]) { |
| 83 for (MetadataAnnotation metadata in element.implementation.metadata) { | 90 for (MetadataAnnotation metadata in element.implementation.metadata) { |
| 84 metadata.ensureResolved(compiler); | 91 metadata.ensureResolved(resolution); |
| 85 } | 92 } |
| 86 return result; | 93 return result; |
| 87 } | 94 } |
| 88 | 95 |
| 89 ElementKind kind = element.kind; | 96 ElementKind kind = element.kind; |
| 90 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) || | 97 if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR) || |
| 91 identical(kind, ElementKind.FUNCTION) || | 98 identical(kind, ElementKind.FUNCTION) || |
| 92 identical(kind, ElementKind.GETTER) || | 99 identical(kind, ElementKind.GETTER) || |
| 93 identical(kind, ElementKind.SETTER)) { | 100 identical(kind, ElementKind.SETTER)) { |
| 94 return processMetadata(resolveMethodElement(element)); | 101 return processMetadata(resolveMethodElement(element)); |
| 95 } | 102 } |
| 96 | 103 |
| 97 if (identical(kind, ElementKind.FIELD)) { | 104 if (identical(kind, ElementKind.FIELD)) { |
| 98 return processMetadata(resolveField(element)); | 105 return processMetadata(resolveField(element)); |
| 99 } | 106 } |
| 100 if (element.isClass) { | 107 if (element.isClass) { |
| 101 ClassElement cls = element; | 108 ClassElement cls = element; |
| 102 cls.ensureResolved(compiler); | 109 cls.ensureResolved(resolution); |
| 103 return processMetadata(const WorldImpact()); | 110 return processMetadata(const WorldImpact()); |
| 104 } else if (element.isTypedef) { | 111 } else if (element.isTypedef) { |
| 105 TypedefElement typdef = element; | 112 TypedefElement typdef = element; |
| 106 return processMetadata(resolveTypedef(typdef)); | 113 return processMetadata(resolveTypedef(typdef)); |
| 107 } | 114 } |
| 108 | 115 |
| 109 compiler.unimplemented(element, "resolve($element)"); | 116 compiler.unimplemented(element, "resolve($element)"); |
| 110 }); | 117 }); |
| 111 } | 118 } |
| 112 | 119 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 128 return; | 135 return; |
| 129 } | 136 } |
| 130 seen.add(redirection); | 137 seen.add(redirection); |
| 131 redirection = resolver.visitor.resolveConstructorRedirection(redirection); | 138 redirection = resolver.visitor.resolveConstructorRedirection(redirection); |
| 132 } | 139 } |
| 133 } | 140 } |
| 134 | 141 |
| 135 static void processAsyncMarker(Compiler compiler, | 142 static void processAsyncMarker(Compiler compiler, |
| 136 BaseFunctionElementX element, | 143 BaseFunctionElementX element, |
| 137 ResolutionRegistry registry) { | 144 ResolutionRegistry registry) { |
| 145 Resolution resolution = compiler.resolution; |
| 138 FunctionExpression functionExpression = element.node; | 146 FunctionExpression functionExpression = element.node; |
| 139 AsyncModifier asyncModifier = functionExpression.asyncModifier; | 147 AsyncModifier asyncModifier = functionExpression.asyncModifier; |
| 140 if (asyncModifier != null) { | 148 if (asyncModifier != null) { |
| 141 | 149 |
| 142 if (asyncModifier.isAsynchronous) { | 150 if (asyncModifier.isAsynchronous) { |
| 143 element.asyncMarker = asyncModifier.isYielding | 151 element.asyncMarker = asyncModifier.isYielding |
| 144 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; | 152 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; |
| 145 } else { | 153 } else { |
| 146 element.asyncMarker = AsyncMarker.SYNC_STAR; | 154 element.asyncMarker = AsyncMarker.SYNC_STAR; |
| 147 } | 155 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 167 element.asyncMarker.isYielding) { | 175 element.asyncMarker.isYielding) { |
| 168 compiler.reportErrorMessage( | 176 compiler.reportErrorMessage( |
| 169 asyncModifier, | 177 asyncModifier, |
| 170 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, | 178 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, |
| 171 {'modifier': element.asyncMarker}); | 179 {'modifier': element.asyncMarker}); |
| 172 } | 180 } |
| 173 } | 181 } |
| 174 registry.registerAsyncMarker(element); | 182 registry.registerAsyncMarker(element); |
| 175 switch (element.asyncMarker) { | 183 switch (element.asyncMarker) { |
| 176 case AsyncMarker.ASYNC: | 184 case AsyncMarker.ASYNC: |
| 177 compiler.futureClass.ensureResolved(compiler); | 185 compiler.futureClass.ensureResolved(resolution); |
| 178 break; | 186 break; |
| 179 case AsyncMarker.ASYNC_STAR: | 187 case AsyncMarker.ASYNC_STAR: |
| 180 compiler.streamClass.ensureResolved(compiler); | 188 compiler.streamClass.ensureResolved(resolution); |
| 181 break; | 189 break; |
| 182 case AsyncMarker.SYNC_STAR: | 190 case AsyncMarker.SYNC_STAR: |
| 183 compiler.iterableClass.ensureResolved(compiler); | 191 compiler.iterableClass.ensureResolved(resolution); |
| 184 break; | 192 break; |
| 185 } | 193 } |
| 186 } | 194 } |
| 187 } | 195 } |
| 188 | 196 |
| 189 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) { | 197 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) { |
| 190 assert(classElement != null); | 198 assert(classElement != null); |
| 191 while (classElement != null) { | 199 while (classElement != null) { |
| 192 if (classElement.isNative) return true; | 200 if (classElement.isNative) return true; |
| 193 classElement = classElement.superclass; | 201 classElement = classElement.superclass; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 } | 294 } |
| 287 if (element.isSynthesized) { | 295 if (element.isSynthesized) { |
| 288 if (element.isGenerativeConstructor) { | 296 if (element.isGenerativeConstructor) { |
| 289 ResolutionRegistry registry = | 297 ResolutionRegistry registry = |
| 290 new ResolutionRegistry(compiler, _ensureTreeElements(element)); | 298 new ResolutionRegistry(compiler, _ensureTreeElements(element)); |
| 291 ConstructorElement constructor = element.asFunctionElement(); | 299 ConstructorElement constructor = element.asFunctionElement(); |
| 292 ConstructorElement target = constructor.definingConstructor; | 300 ConstructorElement target = constructor.definingConstructor; |
| 293 // Ensure the signature of the synthesized element is | 301 // Ensure the signature of the synthesized element is |
| 294 // resolved. This is the only place where the resolver is | 302 // resolved. This is the only place where the resolver is |
| 295 // seeing this element. | 303 // seeing this element. |
| 296 element.computeSignature(compiler); | 304 element.computeType(resolution); |
| 297 if (!target.isErroneous) { | 305 if (!target.isErroneous) { |
| 298 registry.registerStaticUse(target); | 306 registry.registerStaticUse(target); |
| 299 registry.registerImplicitSuperCall(target); | 307 registry.registerImplicitSuperCall(target); |
| 300 } | 308 } |
| 301 return registry.worldImpact; | 309 return registry.worldImpact; |
| 302 } else { | 310 } else { |
| 303 assert(element.isDeferredLoaderGetter || element.isErroneous); | 311 assert(element.isDeferredLoaderGetter || element.isErroneous); |
| 304 _ensureTreeElements(element); | 312 _ensureTreeElements(element); |
| 305 return const WorldImpact(); | 313 return const WorldImpact(); |
| 306 } | 314 } |
| 307 } else { | 315 } else { |
| 308 element.parseNode(compiler); | 316 element.parseNode(resolution.parsing); |
| 309 element.computeType(compiler); | 317 element.computeType(resolution); |
| 310 FunctionElementX implementation = element; | 318 FunctionElementX implementation = element; |
| 311 if (element.isExternal) { | 319 if (element.isExternal) { |
| 312 implementation = compiler.backend.resolveExternalFunction(element); | 320 implementation = compiler.backend.resolveExternalFunction(element); |
| 313 } | 321 } |
| 314 return resolveMethodElementImplementation( | 322 return resolveMethodElementImplementation( |
| 315 implementation, implementation.node); | 323 implementation, implementation.node); |
| 316 } | 324 } |
| 317 }); | 325 }); |
| 318 } | 326 } |
| 319 | 327 |
| 320 /// Creates a [ResolverVisitor] for resolving an AST in context of [element]. | 328 /// Creates a [ResolverVisitor] for resolving an AST in context of [element]. |
| 321 /// If [useEnclosingScope] is `true` then the initial scope of the visitor | 329 /// If [useEnclosingScope] is `true` then the initial scope of the visitor |
| 322 /// does not include inner scope of [element]. | 330 /// does not include inner scope of [element]. |
| 323 /// | 331 /// |
| 324 /// This method should only be used by this library (or tests of | 332 /// This method should only be used by this library (or tests of |
| 325 /// this library). | 333 /// this library). |
| 326 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { | 334 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { |
| 327 return new ResolverVisitor(compiler, element, | 335 return new ResolverVisitor(compiler, element, |
| 328 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 336 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
| 329 useEnclosingScope: useEnclosingScope); | 337 useEnclosingScope: useEnclosingScope); |
| 330 } | 338 } |
| 331 | 339 |
| 332 WorldImpact resolveField(FieldElementX element) { | 340 WorldImpact resolveField(FieldElementX element) { |
| 333 VariableDefinitions tree = element.parseNode(compiler); | 341 VariableDefinitions tree = element.parseNode(parsing); |
| 334 if(element.modifiers.isStatic && element.isTopLevel) { | 342 if(element.modifiers.isStatic && element.isTopLevel) { |
| 335 compiler.reportErrorMessage( | 343 compiler.reportErrorMessage( |
| 336 element.modifiers.getStatic(), | 344 element.modifiers.getStatic(), |
| 337 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 345 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
| 338 } | 346 } |
| 339 ResolverVisitor visitor = visitorFor(element); | 347 ResolverVisitor visitor = visitorFor(element); |
| 340 ResolutionRegistry registry = visitor.registry; | 348 ResolutionRegistry registry = visitor.registry; |
| 341 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates | 349 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates |
| 342 // to the backend ast. | 350 // to the backend ast. |
| 343 registry.defineElement(tree.definitions.nodes.head, element); | 351 registry.defineElement(tree.definitions.nodes.head, element); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 if (initializer != null) { | 384 if (initializer != null) { |
| 377 if (!element.modifiers.isConst) { | 385 if (!element.modifiers.isConst) { |
| 378 // TODO(johnniwinther): Determine the const-ness eagerly to avoid | 386 // TODO(johnniwinther): Determine the const-ness eagerly to avoid |
| 379 // unnecessary registrations. | 387 // unnecessary registrations. |
| 380 registry.registerLazyField(); | 388 registry.registerLazyField(); |
| 381 } | 389 } |
| 382 } | 390 } |
| 383 } | 391 } |
| 384 | 392 |
| 385 // Perform various checks as side effect of "computing" the type. | 393 // Perform various checks as side effect of "computing" the type. |
| 386 element.computeType(compiler); | 394 element.computeType(resolution); |
| 387 | 395 |
| 388 return registry.worldImpact; | 396 return registry.worldImpact; |
| 389 } | 397 } |
| 390 | 398 |
| 391 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { | 399 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { |
| 392 DartType type = resolveReturnType(element, annotation); | 400 DartType type = resolveReturnType(element, annotation); |
| 393 if (type.isVoid) { | 401 if (type.isVoid) { |
| 394 compiler.reportErrorMessage( | 402 compiler.reportErrorMessage( |
| 395 annotation, MessageKind.VOID_NOT_ALLOWED); | 403 annotation, MessageKind.VOID_NOT_ALLOWED); |
| 396 } | 404 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 448 while (!seen.isEmpty) { | 456 while (!seen.isEmpty) { |
| 449 ConstructorElementX factory = seen.removeLast(); | 457 ConstructorElementX factory = seen.removeLast(); |
| 450 | 458 |
| 451 // [factory] must already be analyzed but the [TreeElements] might not | 459 // [factory] must already be analyzed but the [TreeElements] might not |
| 452 // have been stored in the enqueuer cache yet. | 460 // have been stored in the enqueuer cache yet. |
| 453 // TODO(johnniwinther): Store [TreeElements] in the cache before | 461 // TODO(johnniwinther): Store [TreeElements] in the cache before |
| 454 // resolution of the element. | 462 // resolution of the element. |
| 455 TreeElements treeElements = factory.treeElements; | 463 TreeElements treeElements = factory.treeElements; |
| 456 assert(invariant(node, treeElements != null, | 464 assert(invariant(node, treeElements != null, |
| 457 message: 'No TreeElements cached for $factory.')); | 465 message: 'No TreeElements cached for $factory.')); |
| 458 FunctionExpression functionNode = factory.parseNode(compiler); | 466 FunctionExpression functionNode = factory.parseNode(parsing); |
| 459 RedirectingFactoryBody redirectionNode = functionNode.body; | 467 RedirectingFactoryBody redirectionNode = functionNode.body; |
| 460 DartType factoryType = treeElements.getType(redirectionNode); | 468 DartType factoryType = treeElements.getType(redirectionNode); |
| 461 if (!factoryType.isDynamic) { | 469 if (!factoryType.isDynamic) { |
| 462 targetType = targetType.substByContext(factoryType); | 470 targetType = targetType.substByContext(factoryType); |
| 463 } | 471 } |
| 464 factory.effectiveTarget = target; | 472 factory.effectiveTarget = target; |
| 465 factory.effectiveTargetType = targetType; | 473 factory.effectiveTargetType = targetType; |
| 466 } | 474 } |
| 467 } | 475 } |
| 468 | 476 |
| 469 /** | 477 /** |
| 470 * Load and resolve the supertypes of [cls]. | 478 * Load and resolve the supertypes of [cls]. |
| 471 * | 479 * |
| 472 * Warning: do not call this method directly. It should only be | 480 * Warning: do not call this method directly. It should only be |
| 473 * called by [resolveClass] and [ClassSupertypeResolver]. | 481 * called by [resolveClass] and [ClassSupertypeResolver]. |
| 474 */ | 482 */ |
| 475 void loadSupertypes(BaseClassElementX cls, Spannable from) { | 483 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
| 476 compiler.withCurrentElement(cls, () => measure(() { | 484 compiler.withCurrentElement(cls, () => measure(() { |
| 477 if (cls.supertypeLoadState == STATE_DONE) return; | 485 if (cls.supertypeLoadState == STATE_DONE) return; |
| 478 if (cls.supertypeLoadState == STATE_STARTED) { | 486 if (cls.supertypeLoadState == STATE_STARTED) { |
| 479 compiler.reportErrorMessage( | 487 compiler.reportErrorMessage( |
| 480 from, | 488 from, |
| 481 MessageKind.CYCLIC_CLASS_HIERARCHY, | 489 MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 482 {'className': cls.name}); | 490 {'className': cls.name}); |
| 483 cls.supertypeLoadState = STATE_DONE; | 491 cls.supertypeLoadState = STATE_DONE; |
| 484 cls.hasIncompleteHierarchy = true; | 492 cls.hasIncompleteHierarchy = true; |
| 485 cls.allSupertypesAndSelf = | 493 cls.allSupertypesAndSelf = |
| 486 compiler.objectClass.allSupertypesAndSelf.extendClass( | 494 compiler.objectClass.allSupertypesAndSelf.extendClass( |
| 487 cls.computeType(compiler)); | 495 cls.computeType(resolution)); |
| 488 cls.supertype = cls.allSupertypes.head; | 496 cls.supertype = cls.allSupertypes.head; |
| 489 assert(invariant(from, cls.supertype != null, | 497 assert(invariant(from, cls.supertype != null, |
| 490 message: 'Missing supertype on cyclic class $cls.')); | 498 message: 'Missing supertype on cyclic class $cls.')); |
| 491 cls.interfaces = const Link<DartType>(); | 499 cls.interfaces = const Link<DartType>(); |
| 492 return; | 500 return; |
| 493 } | 501 } |
| 494 cls.supertypeLoadState = STATE_STARTED; | 502 cls.supertypeLoadState = STATE_STARTED; |
| 495 compiler.withCurrentElement(cls, () { | 503 compiler.withCurrentElement(cls, () { |
| 496 // TODO(ahe): Cache the node in cls. | 504 // TODO(ahe): Cache the node in cls. |
| 497 cls.parseNode(compiler).accept( | 505 cls.parseNode(parsing).accept( |
| 498 new ClassSupertypeResolver(compiler, cls)); | 506 new ClassSupertypeResolver(compiler, cls)); |
| 499 if (cls.supertypeLoadState != STATE_DONE) { | 507 if (cls.supertypeLoadState != STATE_DONE) { |
| 500 cls.supertypeLoadState = STATE_DONE; | 508 cls.supertypeLoadState = STATE_DONE; |
| 501 } | 509 } |
| 502 }); | 510 }); |
| 503 })); | 511 })); |
| 504 } | 512 } |
| 505 | 513 |
| 506 // TODO(johnniwinther): Remove this queue when resolution has been split into | 514 // TODO(johnniwinther): Remove this queue when resolution has been split into |
| 507 // syntax and semantic resolution. | 515 // syntax and semantic resolution. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 521 resolveTypeDeclaration()) { | 529 resolveTypeDeclaration()) { |
| 522 return compiler.withCurrentElement(element, () { | 530 return compiler.withCurrentElement(element, () { |
| 523 return measure(() { | 531 return measure(() { |
| 524 TypeDeclarationElement previousResolvedTypeDeclaration = | 532 TypeDeclarationElement previousResolvedTypeDeclaration = |
| 525 currentlyResolvedTypeDeclaration; | 533 currentlyResolvedTypeDeclaration; |
| 526 currentlyResolvedTypeDeclaration = element; | 534 currentlyResolvedTypeDeclaration = element; |
| 527 var result = resolveTypeDeclaration(); | 535 var result = resolveTypeDeclaration(); |
| 528 if (previousResolvedTypeDeclaration == null) { | 536 if (previousResolvedTypeDeclaration == null) { |
| 529 do { | 537 do { |
| 530 while (!pendingClassesToBeResolved.isEmpty) { | 538 while (!pendingClassesToBeResolved.isEmpty) { |
| 531 pendingClassesToBeResolved.removeFirst().ensureResolved(compiler); | 539 pendingClassesToBeResolved.removeFirst().ensureResolved(resolution
); |
| 532 } | 540 } |
| 533 while (!pendingClassesToBePostProcessed.isEmpty) { | 541 while (!pendingClassesToBePostProcessed.isEmpty) { |
| 534 _postProcessClassElement( | 542 _postProcessClassElement( |
| 535 pendingClassesToBePostProcessed.removeFirst()); | 543 pendingClassesToBePostProcessed.removeFirst()); |
| 536 } | 544 } |
| 537 } while (!pendingClassesToBeResolved.isEmpty); | 545 } while (!pendingClassesToBeResolved.isEmpty); |
| 538 assert(pendingClassesToBeResolved.isEmpty); | 546 assert(pendingClassesToBeResolved.isEmpty); |
| 539 assert(pendingClassesToBePostProcessed.isEmpty); | 547 assert(pendingClassesToBePostProcessed.isEmpty); |
| 540 } | 548 } |
| 541 currentlyResolvedTypeDeclaration = previousResolvedTypeDeclaration; | 549 currentlyResolvedTypeDeclaration = previousResolvedTypeDeclaration; |
| 542 return result; | 550 return result; |
| 543 }); | 551 }); |
| 544 }); | 552 }); |
| 545 } | 553 } |
| 546 | 554 |
| 547 /** | 555 /** |
| 548 * Resolve the class [element]. | 556 * Resolve the class [element]. |
| 549 * | 557 * |
| 550 * Before calling this method, [element] was constructed by the | 558 * Before calling this method, [element] was constructed by the |
| 551 * scanner and most fields are null or empty. This method fills in | 559 * scanner and most fields are null or empty. This method fills in |
| 552 * these fields and also ensure that the supertypes of [element] are | 560 * these fields and also ensure that the supertypes of [element] are |
| 553 * resolved. | 561 * resolved. |
| 554 * | 562 * |
| 555 * Warning: Do not call this method directly. Instead use | 563 * Warning: Do not call this method directly. Instead use |
| 556 * [:element.ensureResolved(compiler):]. | 564 * [:element.ensureResolved(resolution):]. |
| 557 */ | 565 */ |
| 558 TreeElements resolveClass(BaseClassElementX element) { | 566 TreeElements resolveClass(BaseClassElementX element) { |
| 559 return _resolveTypeDeclaration(element, () { | 567 return _resolveTypeDeclaration(element, () { |
| 560 // TODO(johnniwinther): Store the mapping in the resolution enqueuer. | 568 // TODO(johnniwinther): Store the mapping in the resolution enqueuer. |
| 561 ResolutionRegistry registry = | 569 ResolutionRegistry registry = |
| 562 new ResolutionRegistry(compiler, _ensureTreeElements(element)); | 570 new ResolutionRegistry(compiler, _ensureTreeElements(element)); |
| 563 resolveClassInternal(element, registry); | 571 resolveClassInternal(element, registry); |
| 564 return element.treeElements; | 572 return element.treeElements; |
| 565 }); | 573 }); |
| 566 } | 574 } |
| 567 | 575 |
| 568 void ensureClassWillBeResolvedInternal(ClassElement element) { | 576 void ensureClassWillBeResolvedInternal(ClassElement element) { |
| 569 if (currentlyResolvedTypeDeclaration == null) { | 577 if (currentlyResolvedTypeDeclaration == null) { |
| 570 element.ensureResolved(compiler); | 578 element.ensureResolved(resolution); |
| 571 } else { | 579 } else { |
| 572 pendingClassesToBeResolved.add(element); | 580 pendingClassesToBeResolved.add(element); |
| 573 } | 581 } |
| 574 } | 582 } |
| 575 | 583 |
| 576 void resolveClassInternal(BaseClassElementX element, | 584 void resolveClassInternal(BaseClassElementX element, |
| 577 ResolutionRegistry registry) { | 585 ResolutionRegistry registry) { |
| 578 if (!element.isPatch) { | 586 if (!element.isPatch) { |
| 579 compiler.withCurrentElement(element, () => measure(() { | 587 compiler.withCurrentElement(element, () => measure(() { |
| 580 assert(element.resolutionState == STATE_NOT_STARTED); | 588 assert(element.resolutionState == STATE_NOT_STARTED); |
| 581 element.resolutionState = STATE_STARTED; | 589 element.resolutionState = STATE_STARTED; |
| 582 Node tree = element.parseNode(compiler); | 590 Node tree = element.parseNode(parsing); |
| 583 loadSupertypes(element, tree); | 591 loadSupertypes(element, tree); |
| 584 | 592 |
| 585 ClassResolverVisitor visitor = | 593 ClassResolverVisitor visitor = |
| 586 new ClassResolverVisitor(compiler, element, registry); | 594 new ClassResolverVisitor(compiler, element, registry); |
| 587 visitor.visit(tree); | 595 visitor.visit(tree); |
| 588 element.resolutionState = STATE_DONE; | 596 element.resolutionState = STATE_DONE; |
| 589 compiler.onClassResolved(element); | 597 compiler.onClassResolved(element); |
| 590 pendingClassesToBePostProcessed.add(element); | 598 pendingClassesToBePostProcessed.add(element); |
| 591 })); | 599 })); |
| 592 if (element.isPatched) { | 600 if (element.isPatched) { |
| 593 // Ensure handling patch after origin. | 601 // Ensure handling patch after origin. |
| 594 element.patch.ensureResolved(compiler); | 602 element.patch.ensureResolved(resolution); |
| 595 } | 603 } |
| 596 } else { // Handle patch classes: | 604 } else { // Handle patch classes: |
| 597 element.resolutionState = STATE_STARTED; | 605 element.resolutionState = STATE_STARTED; |
| 598 // Ensure handling origin before patch. | 606 // Ensure handling origin before patch. |
| 599 element.origin.ensureResolved(compiler); | 607 element.origin.ensureResolved(resolution); |
| 600 // Ensure that the type is computed. | 608 // Ensure that the type is computed. |
| 601 element.computeType(compiler); | 609 element.computeType(resolution); |
| 602 // Copy class hierarchy from origin. | 610 // Copy class hierarchy from origin. |
| 603 element.supertype = element.origin.supertype; | 611 element.supertype = element.origin.supertype; |
| 604 element.interfaces = element.origin.interfaces; | 612 element.interfaces = element.origin.interfaces; |
| 605 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf; | 613 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf; |
| 606 // Stepwise assignment to ensure invariant. | 614 // Stepwise assignment to ensure invariant. |
| 607 element.supertypeLoadState = STATE_STARTED; | 615 element.supertypeLoadState = STATE_STARTED; |
| 608 element.supertypeLoadState = STATE_DONE; | 616 element.supertypeLoadState = STATE_DONE; |
| 609 element.resolutionState = STATE_DONE; | 617 element.resolutionState = STATE_DONE; |
| 610 // TODO(johnniwinther): Check matching type variables and | 618 // TODO(johnniwinther): Check matching type variables and |
| 611 // empty extends/implements clauses. | 619 // empty extends/implements clauses. |
| 612 } | 620 } |
| 613 } | 621 } |
| 614 | 622 |
| 615 void _postProcessClassElement(BaseClassElementX element) { | 623 void _postProcessClassElement(BaseClassElementX element) { |
| 616 for (MetadataAnnotation metadata in element.implementation.metadata) { | 624 for (MetadataAnnotation metadata in element.implementation.metadata) { |
| 617 metadata.ensureResolved(compiler); | 625 metadata.ensureResolved(resolution); |
| 618 ConstantValue value = | 626 ConstantValue value = |
| 619 compiler.constants.getConstantValue(metadata.constant); | 627 compiler.constants.getConstantValue(metadata.constant); |
| 620 if (!element.isProxy && compiler.isProxyConstant(value)) { | 628 if (!element.isProxy && compiler.isProxyConstant(value)) { |
| 621 element.isProxy = true; | 629 element.isProxy = true; |
| 622 } | 630 } |
| 623 } | 631 } |
| 624 | 632 |
| 625 // Force resolution of metadata on non-instance members since they may be | 633 // Force resolution of metadata on non-instance members since they may be |
| 626 // inspected by the backend while emitting. Metadata on instance members is | 634 // inspected by the backend while emitting. Metadata on instance members is |
| 627 // handled as a result of processing instantiated class members in the | 635 // handled as a result of processing instantiated class members in the |
| 628 // enqueuer. | 636 // enqueuer. |
| 629 // TODO(ahe): Avoid this eager resolution. | 637 // TODO(ahe): Avoid this eager resolution. |
| 630 element.forEachMember((_, Element member) { | 638 element.forEachMember((_, Element member) { |
| 631 if (!member.isInstanceMember) { | 639 if (!member.isInstanceMember) { |
| 632 compiler.withCurrentElement(member, () { | 640 compiler.withCurrentElement(member, () { |
| 633 for (MetadataAnnotation metadata in member.implementation.metadata) { | 641 for (MetadataAnnotation metadata in member.implementation.metadata) { |
| 634 metadata.ensureResolved(compiler); | 642 metadata.ensureResolved(resolution); |
| 635 } | 643 } |
| 636 }); | 644 }); |
| 637 } | 645 } |
| 638 }); | 646 }); |
| 639 | 647 |
| 640 computeClassMember(element, Identifiers.call); | 648 computeClassMember(element, Identifiers.call); |
| 641 } | 649 } |
| 642 | 650 |
| 643 void computeClassMembers(ClassElement element) { | 651 void computeClassMembers(ClassElement element) { |
| 644 MembersCreator.computeAllClassMembers(compiler, element); | 652 MembersCreator.computeAllClassMembers(compiler, element); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 void checkClassMembers(ClassElement cls) { | 749 void checkClassMembers(ClassElement cls) { |
| 742 assert(invariant(cls, cls.isDeclaration)); | 750 assert(invariant(cls, cls.isDeclaration)); |
| 743 if (cls.isObject) return; | 751 if (cls.isObject) return; |
| 744 // TODO(johnniwinther): Should this be done on the implementation element as | 752 // TODO(johnniwinther): Should this be done on the implementation element as |
| 745 // well? | 753 // well? |
| 746 List<Element> constConstructors = <Element>[]; | 754 List<Element> constConstructors = <Element>[]; |
| 747 List<Element> nonFinalInstanceFields = <Element>[]; | 755 List<Element> nonFinalInstanceFields = <Element>[]; |
| 748 cls.forEachMember((holder, member) { | 756 cls.forEachMember((holder, member) { |
| 749 compiler.withCurrentElement(member, () { | 757 compiler.withCurrentElement(member, () { |
| 750 // Perform various checks as side effect of "computing" the type. | 758 // Perform various checks as side effect of "computing" the type. |
| 751 member.computeType(compiler); | 759 member.computeType(resolution); |
| 752 | 760 |
| 753 // Check modifiers. | 761 // Check modifiers. |
| 754 if (member.isFunction && member.modifiers.isFinal) { | 762 if (member.isFunction && member.modifiers.isFinal) { |
| 755 compiler.reportErrorMessage( | 763 compiler.reportErrorMessage( |
| 756 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); | 764 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); |
| 757 } | 765 } |
| 758 if (member.isConstructor) { | 766 if (member.isConstructor) { |
| 759 final mismatchedFlagsBits = | 767 final mismatchedFlagsBits = |
| 760 member.modifiers.flags & | 768 member.modifiers.flags & |
| 761 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); | 769 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 'className': contextElement.enclosingClass.name}), | 969 'className': contextElement.enclosingClass.name}), |
| 962 <DiagnosticMessage>[ | 970 <DiagnosticMessage>[ |
| 963 compiler.createMessage(contextElement, contextMessage), | 971 compiler.createMessage(contextElement, contextMessage), |
| 964 ]); | 972 ]); |
| 965 } | 973 } |
| 966 | 974 |
| 967 | 975 |
| 968 FunctionSignature resolveSignature(FunctionElementX element) { | 976 FunctionSignature resolveSignature(FunctionElementX element) { |
| 969 MessageKind defaultValuesError = null; | 977 MessageKind defaultValuesError = null; |
| 970 if (element.isFactoryConstructor) { | 978 if (element.isFactoryConstructor) { |
| 971 FunctionExpression body = element.parseNode(compiler); | 979 FunctionExpression body = element.parseNode(parsing); |
| 972 if (body.isRedirectingFactory) { | 980 if (body.isRedirectingFactory) { |
| 973 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; | 981 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; |
| 974 } | 982 } |
| 975 } | 983 } |
| 976 return compiler.withCurrentElement(element, () { | 984 return compiler.withCurrentElement(element, () { |
| 977 FunctionExpression node = | 985 FunctionExpression node = element.parseNode(parsing); |
| 978 compiler.parser.measure(() => element.parseNode(compiler)); | |
| 979 return measure(() => SignatureResolver.analyze( | 986 return measure(() => SignatureResolver.analyze( |
| 980 compiler, node.parameters, node.returnType, element, | 987 compiler, node.parameters, node.returnType, element, |
| 981 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 988 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
| 982 defaultValuesError: defaultValuesError, | 989 defaultValuesError: defaultValuesError, |
| 983 createRealParameters: true)); | 990 createRealParameters: true)); |
| 984 }); | 991 }); |
| 985 } | 992 } |
| 986 | 993 |
| 987 WorldImpact resolveTypedef(TypedefElementX element) { | 994 WorldImpact resolveTypedef(TypedefElementX element) { |
| 988 if (element.isResolved) return const WorldImpact(); | 995 if (element.isResolved) return const WorldImpact(); |
| 989 compiler.world.allTypedefs.add(element); | 996 compiler.world.allTypedefs.add(element); |
| 990 return _resolveTypeDeclaration(element, () { | 997 return _resolveTypeDeclaration(element, () { |
| 991 ResolutionRegistry registry = new ResolutionRegistry( | 998 ResolutionRegistry registry = new ResolutionRegistry( |
| 992 compiler, _ensureTreeElements(element)); | 999 compiler, _ensureTreeElements(element)); |
| 993 return compiler.withCurrentElement(element, () { | 1000 return compiler.withCurrentElement(element, () { |
| 994 return measure(() { | 1001 return measure(() { |
| 995 assert(element.resolutionState == STATE_NOT_STARTED); | 1002 assert(element.resolutionState == STATE_NOT_STARTED); |
| 996 element.resolutionState = STATE_STARTED; | 1003 element.resolutionState = STATE_STARTED; |
| 997 Typedef node = | 1004 Typedef node = element.parseNode(parsing); |
| 998 compiler.parser.measure(() => element.parseNode(compiler)); | |
| 999 TypedefResolverVisitor visitor = | 1005 TypedefResolverVisitor visitor = |
| 1000 new TypedefResolverVisitor(compiler, element, registry); | 1006 new TypedefResolverVisitor(compiler, element, registry); |
| 1001 visitor.visit(node); | 1007 visitor.visit(node); |
| 1002 element.resolutionState = STATE_DONE; | 1008 element.resolutionState = STATE_DONE; |
| 1003 return registry.worldImpact; | 1009 return registry.worldImpact; |
| 1004 }); | 1010 }); |
| 1005 }); | 1011 }); |
| 1006 }); | 1012 }); |
| 1007 } | 1013 } |
| 1008 | 1014 |
| 1009 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { | 1015 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { |
| 1010 compiler.withCurrentElement(annotation.annotatedElement, () => measure(() { | 1016 compiler.withCurrentElement(annotation.annotatedElement, () => measure(() { |
| 1011 assert(annotation.resolutionState == STATE_NOT_STARTED); | 1017 assert(annotation.resolutionState == STATE_NOT_STARTED); |
| 1012 annotation.resolutionState = STATE_STARTED; | 1018 annotation.resolutionState = STATE_STARTED; |
| 1013 | 1019 |
| 1014 Node node = annotation.parseNode(compiler); | 1020 Node node = annotation.parseNode(parsing); |
| 1015 Element annotatedElement = annotation.annotatedElement; | 1021 Element annotatedElement = annotation.annotatedElement; |
| 1016 AnalyzableElement context = annotatedElement.analyzableElement; | 1022 AnalyzableElement context = annotatedElement.analyzableElement; |
| 1017 ClassElement classElement = annotatedElement.enclosingClass; | 1023 ClassElement classElement = annotatedElement.enclosingClass; |
| 1018 if (classElement != null) { | 1024 if (classElement != null) { |
| 1019 // The annotation is resolved in the scope of [classElement]. | 1025 // The annotation is resolved in the scope of [classElement]. |
| 1020 classElement.ensureResolved(compiler); | 1026 classElement.ensureResolved(resolution); |
| 1021 } | 1027 } |
| 1022 assert(invariant(node, context != null, | 1028 assert(invariant(node, context != null, |
| 1023 message: "No context found for metadata annotation " | 1029 message: "No context found for metadata annotation " |
| 1024 "on $annotatedElement.")); | 1030 "on $annotatedElement.")); |
| 1025 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true); | 1031 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true); |
| 1026 ResolutionRegistry registry = visitor.registry; | 1032 ResolutionRegistry registry = visitor.registry; |
| 1027 node.accept(visitor); | 1033 node.accept(visitor); |
| 1028 // TODO(johnniwinther): Avoid passing the [TreeElements] to | 1034 // TODO(johnniwinther): Avoid passing the [TreeElements] to |
| 1029 // [compileMetadata]. | 1035 // [compileMetadata]. |
| 1030 annotation.constant = | 1036 annotation.constant = |
| 1031 constantCompiler.compileMetadata(annotation, node, registry.mapping); | 1037 constantCompiler.compileMetadata(annotation, node, registry.mapping); |
| 1032 constantCompiler.evaluate(annotation.constant); | 1038 constantCompiler.evaluate(annotation.constant); |
| 1033 // TODO(johnniwinther): Register the relation between the annotation | 1039 // TODO(johnniwinther): Register the relation between the annotation |
| 1034 // and the annotated element instead. This will allow the backend to | 1040 // and the annotated element instead. This will allow the backend to |
| 1035 // retrieve the backend constant and only register metadata on the | 1041 // retrieve the backend constant and only register metadata on the |
| 1036 // elements for which it is needed. (Issue 17732). | 1042 // elements for which it is needed. (Issue 17732). |
| 1037 registry.registerMetadataConstant(annotation, annotatedElement); | 1043 registry.registerMetadataConstant(annotation, annotatedElement); |
| 1038 annotation.resolutionState = STATE_DONE; | 1044 annotation.resolutionState = STATE_DONE; |
| 1039 })); | 1045 })); |
| 1040 } | 1046 } |
| 1041 | 1047 |
| 1042 List<MetadataAnnotation> resolveMetadata(Element element, | 1048 List<MetadataAnnotation> resolveMetadata(Element element, |
| 1043 VariableDefinitions node) { | 1049 VariableDefinitions node) { |
| 1044 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; | 1050 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; |
| 1045 for (Metadata annotation in node.metadata.nodes) { | 1051 for (Metadata annotation in node.metadata.nodes) { |
| 1046 ParameterMetadataAnnotation metadataAnnotation = | 1052 ParameterMetadataAnnotation metadataAnnotation = |
| 1047 new ParameterMetadataAnnotation(annotation); | 1053 new ParameterMetadataAnnotation(annotation); |
| 1048 metadataAnnotation.annotatedElement = element; | 1054 metadataAnnotation.annotatedElement = element; |
| 1049 metadata.add(metadataAnnotation.ensureResolved(compiler)); | 1055 metadata.add(metadataAnnotation.ensureResolved(resolution)); |
| 1050 } | 1056 } |
| 1051 return metadata; | 1057 return metadata; |
| 1052 } | 1058 } |
| 1053 } | 1059 } |
| 1054 | 1060 |
| 1055 TreeElements _ensureTreeElements(AnalyzableElementX element) { | 1061 TreeElements _ensureTreeElements(AnalyzableElementX element) { |
| 1056 if (element._treeElements == null) { | 1062 if (element._treeElements == null) { |
| 1057 element._treeElements = new TreeElementMapping(element); | 1063 element._treeElements = new TreeElementMapping(element); |
| 1058 } | 1064 } |
| 1059 return element._treeElements; | 1065 return element._treeElements; |
| 1060 } | 1066 } |
| 1061 | 1067 |
| 1062 abstract class AnalyzableElementX implements AnalyzableElement { | 1068 abstract class AnalyzableElementX implements AnalyzableElement { |
| 1063 TreeElements _treeElements; | 1069 TreeElements _treeElements; |
| 1064 | 1070 |
| 1065 bool get hasTreeElements => _treeElements != null; | 1071 bool get hasTreeElements => _treeElements != null; |
| 1066 | 1072 |
| 1067 TreeElements get treeElements { | 1073 TreeElements get treeElements { |
| 1068 assert(invariant(this, _treeElements !=null, | 1074 assert(invariant(this, _treeElements !=null, |
| 1069 message: "TreeElements have not been computed for $this.")); | 1075 message: "TreeElements have not been computed for $this.")); |
| 1070 return _treeElements; | 1076 return _treeElements; |
| 1071 } | 1077 } |
| 1072 | 1078 |
| 1073 void reuseElement() { | 1079 void reuseElement() { |
| 1074 _treeElements = null; | 1080 _treeElements = null; |
| 1075 } | 1081 } |
| 1076 } | 1082 } |
| OLD | NEW |