| 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.dart'; | 9 import '../common.dart'; |
| 10 import '../common/names.dart' show Identifiers; | 10 import '../common/names.dart' show Identifiers; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 } | 303 } |
| 304 if (element.isSynthesized) { | 304 if (element.isSynthesized) { |
| 305 if (element.isGenerativeConstructor) { | 305 if (element.isGenerativeConstructor) { |
| 306 ResolutionRegistry registry = | 306 ResolutionRegistry registry = |
| 307 new ResolutionRegistry(this.target, _ensureTreeElements(element)); | 307 new ResolutionRegistry(this.target, _ensureTreeElements(element)); |
| 308 ConstructorElement constructor = element.asFunctionElement(); | 308 ConstructorElement constructor = element.asFunctionElement(); |
| 309 ConstructorElement target = constructor.definingConstructor; | 309 ConstructorElement target = constructor.definingConstructor; |
| 310 // Ensure the signature of the synthesized element is | 310 // Ensure the signature of the synthesized element is |
| 311 // resolved. This is the only place where the resolver is | 311 // resolved. This is the only place where the resolver is |
| 312 // seeing this element. | 312 // seeing this element. |
| 313 FunctionType type = element.computeType(resolution); | 313 ResolutionFunctionType type = element.computeType(resolution); |
| 314 if (!target.isMalformed) { | 314 if (!target.isMalformed) { |
| 315 registry.registerStaticUse(new StaticUse.superConstructorInvoke( | 315 registry.registerStaticUse(new StaticUse.superConstructorInvoke( |
| 316 // TODO(johnniwinther): Provide the right call structure for | 316 // TODO(johnniwinther): Provide the right call structure for |
| 317 // forwarding constructors. | 317 // forwarding constructors. |
| 318 target, | 318 target, |
| 319 CallStructure.NO_ARGS)); | 319 CallStructure.NO_ARGS)); |
| 320 } | 320 } |
| 321 // TODO(johnniwinther): Remove this substitution when synthesized | 321 // TODO(johnniwinther): Remove this substitution when synthesized |
| 322 // constructors handle type variables correctly. | 322 // constructors handle type variables correctly. |
| 323 type = type.substByContext( | 323 type = type.substByContext( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 | 359 |
| 360 WorldImpact resolveField(FieldElementX element) { | 360 WorldImpact resolveField(FieldElementX element) { |
| 361 return reporter.withCurrentElement(element, () { | 361 return reporter.withCurrentElement(element, () { |
| 362 VariableDefinitions tree = element.parseNode(parsingContext); | 362 VariableDefinitions tree = element.parseNode(parsingContext); |
| 363 if (element.modifiers.isStatic && element.isTopLevel) { | 363 if (element.modifiers.isStatic && element.isTopLevel) { |
| 364 reporter.reportErrorMessage(element.modifiers.getStatic(), | 364 reporter.reportErrorMessage(element.modifiers.getStatic(), |
| 365 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 365 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
| 366 } | 366 } |
| 367 ResolverVisitor visitor = visitorFor(element); | 367 ResolverVisitor visitor = visitorFor(element); |
| 368 ResolutionRegistry registry = visitor.registry; | 368 ResolutionRegistry registry = visitor.registry; |
| 369 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrat
es | 369 // TODO(johnniwinther): Maybe remove this when placeholderCollector |
| 370 // to the backend ast. | 370 // migrates to the backend ast. |
| 371 registry.defineElement(element.definition, element); | 371 registry.defineElement(element.definition, element); |
| 372 // TODO(johnniwinther): Share the resolved type between all variables | 372 // TODO(johnniwinther): Share the resolved type between all variables |
| 373 // declared in the same declaration. | 373 // declared in the same declaration. |
| 374 if (tree.type != null) { | 374 if (tree.type != null) { |
| 375 DartType type = visitor.resolveTypeAnnotation(tree.type); | 375 ResolutionDartType type = visitor.resolveTypeAnnotation(tree.type); |
| 376 assert(invariant( | 376 assert(invariant( |
| 377 element, | 377 element, |
| 378 element.variables.type == null || | 378 element.variables.type == null || |
| 379 // Crude check but we have no equivalence relation that | 379 // Crude check but we have no equivalence relation that |
| 380 // equates malformed types, like matching creations of type | 380 // equates malformed types, like matching creations of type |
| 381 // `Foo<Unresolved>`. | 381 // `Foo<Unresolved>`. |
| 382 element.variables.type.toString() == type.toString(), | 382 element.variables.type.toString() == type.toString(), |
| 383 message: "Unexpected type computed for $element. " | 383 message: "Unexpected type computed for $element. " |
| 384 "Was ${element.variables.type}, computed $type.")); | 384 "Was ${element.variables.type}, computed $type.")); |
| 385 element.variables.type = type; | 385 element.variables.type = type; |
| 386 } else if (element.variables.type == null) { | 386 } else if (element.variables.type == null) { |
| 387 // Only assign the dynamic type if the element has no known type. This | 387 // Only assign the dynamic type if the element has no known type. This |
| 388 // happens for enum fields where the type is known but is not in the | 388 // happens for enum fields where the type is known but is not in the |
| 389 // synthesized AST. | 389 // synthesized AST. |
| 390 element.variables.type = const DynamicType(); | 390 element.variables.type = const ResolutionDynamicType(); |
| 391 } else { | 391 } else { |
| 392 registry.registerCheckedModeCheck(element.variables.type); | 392 registry.registerCheckedModeCheck(element.variables.type); |
| 393 } | 393 } |
| 394 | 394 |
| 395 Expression initializer = element.initializer; | 395 Expression initializer = element.initializer; |
| 396 Modifiers modifiers = element.modifiers; | 396 Modifiers modifiers = element.modifiers; |
| 397 if (initializer != null) { | 397 if (initializer != null) { |
| 398 // TODO(johnniwinther): Avoid analyzing initializers if | 398 // TODO(johnniwinther): Avoid analyzing initializers if |
| 399 // [Compiler.analyzeSignaturesOnly] is set. | 399 // [Compiler.analyzeSignaturesOnly] is set. |
| 400 ResolutionResult result = visitor.visit(initializer); | 400 ResolutionResult result = visitor.visit(initializer); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 431 | 431 |
| 432 // Perform various checks as side effect of "computing" the type. | 432 // Perform various checks as side effect of "computing" the type. |
| 433 element.computeType(resolution); | 433 element.computeType(resolution); |
| 434 | 434 |
| 435 resolution.target.resolveNativeElement(element, registry.impactBuilder); | 435 resolution.target.resolveNativeElement(element, registry.impactBuilder); |
| 436 | 436 |
| 437 return registry.impactBuilder; | 437 return registry.impactBuilder; |
| 438 }); | 438 }); |
| 439 } | 439 } |
| 440 | 440 |
| 441 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { | 441 ResolutionDartType resolveTypeAnnotation( |
| 442 DartType type = _resolveReturnType(element, annotation); | 442 Element element, TypeAnnotation annotation) { |
| 443 ResolutionDartType type = _resolveReturnType(element, annotation); |
| 443 if (type.isVoid) { | 444 if (type.isVoid) { |
| 444 reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); | 445 reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); |
| 445 } | 446 } |
| 446 return type; | 447 return type; |
| 447 } | 448 } |
| 448 | 449 |
| 449 DartType _resolveReturnType(Element element, TypeAnnotation annotation) { | 450 ResolutionDartType _resolveReturnType( |
| 450 if (annotation == null) return const DynamicType(); | 451 Element element, TypeAnnotation annotation) { |
| 451 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); | 452 if (annotation == null) return const ResolutionDynamicType(); |
| 453 ResolutionDartType result = |
| 454 visitorFor(element).resolveTypeAnnotation(annotation); |
| 452 assert(invariant(annotation, result != null, | 455 assert(invariant(annotation, result != null, |
| 453 message: "No type computed for $annotation.")); | 456 message: "No type computed for $annotation.")); |
| 454 if (result == null) { | 457 if (result == null) { |
| 455 // TODO(karklose): warning. | 458 // TODO(karklose): warning. |
| 456 return const DynamicType(); | 459 return const ResolutionDynamicType(); |
| 457 } | 460 } |
| 458 return result; | 461 return result; |
| 459 } | 462 } |
| 460 | 463 |
| 461 void resolveRedirectionChain(ConstructorElement constructor, Spannable node) { | 464 void resolveRedirectionChain(ConstructorElement constructor, Spannable node) { |
| 462 ConstructorElement target = constructor; | 465 ConstructorElement target = constructor; |
| 463 DartType targetType; | 466 ResolutionDartType targetType; |
| 464 List<ConstructorElement> seen = new List<ConstructorElement>(); | 467 List<ConstructorElement> seen = new List<ConstructorElement>(); |
| 465 bool isMalformed = false; | 468 bool isMalformed = false; |
| 466 // Follow the chain of redirections and check for cycles. | 469 // Follow the chain of redirections and check for cycles. |
| 467 while (target.isRedirectingFactory) { | 470 while (target.isRedirectingFactory) { |
| 468 if (target.hasEffectiveTarget) { | 471 if (target.hasEffectiveTarget) { |
| 469 // We found a constructor that already has been processed. | 472 // We found a constructor that already has been processed. |
| 470 // TODO(johnniwinther): Should `effectiveTargetType` be part of the | 473 // TODO(johnniwinther): Should `effectiveTargetType` be part of the |
| 471 // interface? | 474 // interface? |
| 472 targetType = | 475 targetType = |
| 473 target.computeEffectiveTargetType(target.enclosingClass.thisType); | 476 target.computeEffectiveTargetType(target.enclosingClass.thisType); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 // do not have to run the loop for these constructors again. Furthermore, | 511 // do not have to run the loop for these constructors again. Furthermore, |
| 509 // compute [redirectionTargetType] for each factory by computing the | 512 // compute [redirectionTargetType] for each factory by computing the |
| 510 // substitution of the target type with respect to the factory type. | 513 // substitution of the target type with respect to the factory type. |
| 511 while (!seen.isEmpty) { | 514 while (!seen.isEmpty) { |
| 512 ConstructorElementX factory = seen.removeLast(); | 515 ConstructorElementX factory = seen.removeLast(); |
| 513 ResolvedAst resolvedAst = factory.resolvedAst; | 516 ResolvedAst resolvedAst = factory.resolvedAst; |
| 514 assert(invariant(node, resolvedAst != null, | 517 assert(invariant(node, resolvedAst != null, |
| 515 message: 'No ResolvedAst for $factory.')); | 518 message: 'No ResolvedAst for $factory.')); |
| 516 FunctionExpression functionNode = resolvedAst.node; | 519 FunctionExpression functionNode = resolvedAst.node; |
| 517 RedirectingFactoryBody redirectionNode = resolvedAst.body; | 520 RedirectingFactoryBody redirectionNode = resolvedAst.body; |
| 518 DartType factoryType = resolvedAst.elements.getType(redirectionNode); | 521 ResolutionDartType factoryType = |
| 522 resolvedAst.elements.getType(redirectionNode); |
| 519 if (!factoryType.isDynamic) { | 523 if (!factoryType.isDynamic) { |
| 520 targetType = targetType.substByContext(factoryType); | 524 targetType = targetType.substByContext(factoryType); |
| 521 } | 525 } |
| 522 factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed); | 526 factory.setEffectiveTarget(target, targetType, isMalformed: isMalformed); |
| 523 } | 527 } |
| 524 } | 528 } |
| 525 | 529 |
| 526 /** | 530 /** |
| 527 * Load and resolve the supertypes of [cls]. | 531 * Load and resolve the supertypes of [cls]. |
| 528 * | 532 * |
| 529 * Warning: do not call this method directly. It should only be | 533 * Warning: do not call this method directly. It should only be |
| 530 * called by [resolveClass] and [ClassSupertypeResolver]. | 534 * called by [resolveClass] and [ClassSupertypeResolver]. |
| 531 */ | 535 */ |
| 532 void loadSupertypes(BaseClassElementX cls, Spannable from) { | 536 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
| 533 measure(() { | 537 measure(() { |
| 534 if (cls.supertypeLoadState == STATE_DONE) return; | 538 if (cls.supertypeLoadState == STATE_DONE) return; |
| 535 if (cls.supertypeLoadState == STATE_STARTED) { | 539 if (cls.supertypeLoadState == STATE_STARTED) { |
| 536 reporter.reportErrorMessage( | 540 reporter.reportErrorMessage( |
| 537 from, MessageKind.CYCLIC_CLASS_HIERARCHY, {'className': cls.name}); | 541 from, MessageKind.CYCLIC_CLASS_HIERARCHY, {'className': cls.name}); |
| 538 cls.supertypeLoadState = STATE_DONE; | 542 cls.supertypeLoadState = STATE_DONE; |
| 539 cls.hasIncompleteHierarchy = true; | 543 cls.hasIncompleteHierarchy = true; |
| 540 cls.allSupertypesAndSelf = commonElements | 544 cls.allSupertypesAndSelf = commonElements |
| 541 .objectClass.allSupertypesAndSelf | 545 .objectClass.allSupertypesAndSelf |
| 542 .extendClass(cls.computeType(resolution)); | 546 .extendClass(cls.computeType(resolution)); |
| 543 cls.supertype = cls.allSupertypes.head; | 547 cls.supertype = cls.allSupertypes.head; |
| 544 assert(invariant(from, cls.supertype != null, | 548 assert(invariant(from, cls.supertype != null, |
| 545 message: 'Missing supertype on cyclic class $cls.')); | 549 message: 'Missing supertype on cyclic class $cls.')); |
| 546 cls.interfaces = const Link<DartType>(); | 550 cls.interfaces = const Link<ResolutionDartType>(); |
| 547 return; | 551 return; |
| 548 } | 552 } |
| 549 cls.supertypeLoadState = STATE_STARTED; | 553 cls.supertypeLoadState = STATE_STARTED; |
| 550 reporter.withCurrentElement(cls, () { | 554 reporter.withCurrentElement(cls, () { |
| 551 // TODO(ahe): Cache the node in cls. | 555 // TODO(ahe): Cache the node in cls. |
| 552 cls | 556 cls |
| 553 .parseNode(parsingContext) | 557 .parseNode(parsingContext) |
| 554 .accept(new ClassSupertypeResolver(resolution, cls)); | 558 .accept(new ClassSupertypeResolver(resolution, cls)); |
| 555 if (cls.supertypeLoadState != STATE_DONE) { | 559 if (cls.supertypeLoadState != STATE_DONE) { |
| 556 cls.supertypeLoadState = STATE_DONE; | 560 cls.supertypeLoadState = STATE_DONE; |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 break; | 1095 break; |
| 1092 default: | 1096 default: |
| 1093 reporter.reportErrorMessage( | 1097 reporter.reportErrorMessage( |
| 1094 node, MessageKind.INVALID_METADATA); | 1098 node, MessageKind.INVALID_METADATA); |
| 1095 constant = new ErroneousConstantExpression(); | 1099 constant = new ErroneousConstantExpression(); |
| 1096 break; | 1100 break; |
| 1097 } | 1101 } |
| 1098 annotation.constant = constant; | 1102 annotation.constant = constant; |
| 1099 | 1103 |
| 1100 constantCompiler.evaluate(annotation.constant); | 1104 constantCompiler.evaluate(annotation.constant); |
| 1101 // TODO(johnniwinther): Register the relation between the annotati
on | 1105 // TODO(johnniwinther): Register the relation between the |
| 1102 // and the annotated element instead. This will allow the backend
to | 1106 // annotation and the annotated element instead. This will allow |
| 1103 // retrieve the backend constant and only register metadata on the | 1107 // the backend to retrieve the backend constant and only register |
| 1104 // elements for which it is needed. (Issue 17732). | 1108 // metadata on the elements for which it is needed. (Issue 17732). |
| 1105 annotation.resolutionState = STATE_DONE; | 1109 annotation.resolutionState = STATE_DONE; |
| 1106 })); | 1110 })); |
| 1107 } | 1111 } |
| 1108 | 1112 |
| 1109 List<MetadataAnnotation> resolveMetadata( | 1113 List<MetadataAnnotation> resolveMetadata( |
| 1110 Element element, VariableDefinitions node) { | 1114 Element element, VariableDefinitions node) { |
| 1111 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; | 1115 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; |
| 1112 for (Metadata annotation in node.metadata.nodes) { | 1116 for (Metadata annotation in node.metadata.nodes) { |
| 1113 ParameterMetadataAnnotation metadataAnnotation = | 1117 ParameterMetadataAnnotation metadataAnnotation = |
| 1114 new ParameterMetadataAnnotation(annotation); | 1118 new ParameterMetadataAnnotation(annotation); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1134 TreeElements get treeElements { | 1138 TreeElements get treeElements { |
| 1135 assert(invariant(this, _treeElements != null, | 1139 assert(invariant(this, _treeElements != null, |
| 1136 message: "TreeElements have not been computed for $this.")); | 1140 message: "TreeElements have not been computed for $this.")); |
| 1137 return _treeElements; | 1141 return _treeElements; |
| 1138 } | 1142 } |
| 1139 | 1143 |
| 1140 void reuseElement() { | 1144 void reuseElement() { |
| 1141 _treeElements = null; | 1145 _treeElements = null; |
| 1142 } | 1146 } |
| 1143 } | 1147 } |
| OLD | NEW |