| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.constructors; | 5 library dart2js.resolution.constructors; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/resolution.dart' show Resolution; | 8 import '../common/resolution.dart' show Resolution; |
| 9 import '../constants/constructors.dart' | 9 import '../constants/constructors.dart' |
| 10 show | 10 show |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 if (isConst) { | 132 if (isConst) { |
| 133 if (result.isConstant && field != null) { | 133 if (result.isConstant && field != null) { |
| 134 // TODO(johnniwinther): Report error if `result.constant` is `null`. | 134 // TODO(johnniwinther): Report error if `result.constant` is `null`. |
| 135 fieldInitializers[field] = result.constant; | 135 fieldInitializers[field] = result.constant; |
| 136 } else { | 136 } else { |
| 137 isValidAsConstant = false; | 137 isValidAsConstant = false; |
| 138 } | 138 } |
| 139 } | 139 } |
| 140 } | 140 } |
| 141 | 141 |
| 142 InterfaceType getSuperOrThisLookupTarget(Node diagnosticNode, | 142 ResolutionInterfaceType getSuperOrThisLookupTarget(Node diagnosticNode, |
| 143 {bool isSuperCall}) { | 143 {bool isSuperCall}) { |
| 144 if (isSuperCall) { | 144 if (isSuperCall) { |
| 145 // Calculate correct lookup target and constructor name. | 145 // Calculate correct lookup target and constructor name. |
| 146 if (constructor.enclosingClass.isObject) { | 146 if (constructor.enclosingClass.isObject) { |
| 147 reporter.reportErrorMessage( | 147 reporter.reportErrorMessage( |
| 148 diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT); | 148 diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT); |
| 149 isValidAsConstant = false; | 149 isValidAsConstant = false; |
| 150 } else { | 150 } else { |
| 151 return constructor.enclosingClass.supertype; | 151 return constructor.enclosingClass.supertype; |
| 152 } | 152 } |
| 153 } | 153 } |
| 154 return constructor.enclosingClass.thisType; | 154 return constructor.enclosingClass.thisType; |
| 155 } | 155 } |
| 156 | 156 |
| 157 ResolutionResult resolveSuperOrThisForSend(Send node) { | 157 ResolutionResult resolveSuperOrThisForSend(Send node) { |
| 158 // Resolve the selector and the arguments. | 158 // Resolve the selector and the arguments. |
| 159 ArgumentsResult argumentsResult = visitor.inStaticContext(() { | 159 ArgumentsResult argumentsResult = visitor.inStaticContext(() { |
| 160 // TODO(johnniwinther): Remove this when [SendStructure] is used directly. | 160 // TODO(johnniwinther): Remove this when [SendStructure] is used directly. |
| 161 visitor.resolveSelector(node, null); | 161 visitor.resolveSelector(node, null); |
| 162 return visitor.resolveArguments(node.argumentsNode); | 162 return visitor.resolveArguments(node.argumentsNode); |
| 163 }, inConstantInitializer: isConst); | 163 }, inConstantInitializer: isConst); |
| 164 | 164 |
| 165 bool isSuperCall = Initializers.isSuperConstructorCall(node); | 165 bool isSuperCall = Initializers.isSuperConstructorCall(node); |
| 166 InterfaceType targetType = | 166 ResolutionInterfaceType targetType = |
| 167 getSuperOrThisLookupTarget(node, isSuperCall: isSuperCall); | 167 getSuperOrThisLookupTarget(node, isSuperCall: isSuperCall); |
| 168 ClassElement lookupTarget = targetType.element; | 168 ClassElement lookupTarget = targetType.element; |
| 169 String constructorName = | 169 String constructorName = |
| 170 visitor.getRedirectingThisOrSuperConstructorName(node).text; | 170 visitor.getRedirectingThisOrSuperConstructorName(node).text; |
| 171 ConstructorElement foundConstructor = | 171 ConstructorElement foundConstructor = |
| 172 findConstructor(constructor.library, lookupTarget, constructorName); | 172 findConstructor(constructor.library, lookupTarget, constructorName); |
| 173 | 173 |
| 174 final String className = lookupTarget.name; | 174 final String className = lookupTarget.name; |
| 175 CallStructure callStructure = argumentsResult.callStructure; | 175 CallStructure callStructure = argumentsResult.callStructure; |
| 176 ConstructorElement calledConstructor = verifyThatConstructorMatchesCall( | 176 ConstructorElement calledConstructor = verifyThatConstructorMatchesCall( |
| (...skipping 26 matching lines...) Expand all Loading... |
| 203 } | 203 } |
| 204 | 204 |
| 205 ConstructedConstantExpression resolveImplicitSuperConstructorSend() { | 205 ConstructedConstantExpression resolveImplicitSuperConstructorSend() { |
| 206 // If the class has a super resolve the implicit super call. | 206 // If the class has a super resolve the implicit super call. |
| 207 ClassElement classElement = constructor.enclosingClass; | 207 ClassElement classElement = constructor.enclosingClass; |
| 208 ClassElement superClass = classElement.superclass; | 208 ClassElement superClass = classElement.superclass; |
| 209 if (!classElement.isObject) { | 209 if (!classElement.isObject) { |
| 210 assert(superClass != null); | 210 assert(superClass != null); |
| 211 assert(superClass.isResolved); | 211 assert(superClass.isResolved); |
| 212 | 212 |
| 213 InterfaceType targetType = | 213 ResolutionInterfaceType targetType = |
| 214 getSuperOrThisLookupTarget(functionNode, isSuperCall: true); | 214 getSuperOrThisLookupTarget(functionNode, isSuperCall: true); |
| 215 ClassElement lookupTarget = targetType.element; | 215 ClassElement lookupTarget = targetType.element; |
| 216 ConstructorElement calledConstructor = | 216 ConstructorElement calledConstructor = |
| 217 findConstructor(constructor.library, lookupTarget, ''); | 217 findConstructor(constructor.library, lookupTarget, ''); |
| 218 | 218 |
| 219 final String className = lookupTarget.name; | 219 final String className = lookupTarget.name; |
| 220 CallStructure callStructure = CallStructure.NO_ARGS; | 220 CallStructure callStructure = CallStructure.NO_ARGS; |
| 221 ConstructorElement result = verifyThatConstructorMatchesCall( | 221 ConstructorElement result = verifyThatConstructorMatchesCall( |
| 222 functionNode, calledConstructor, callStructure, className, | 222 functionNode, calledConstructor, callStructure, className, |
| 223 isImplicitSuperCall: true); | 223 isImplicitSuperCall: true); |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 | 481 |
| 482 Element get context => resolver.enclosingElement; | 482 Element get context => resolver.enclosingElement; |
| 483 | 483 |
| 484 visitNode(Node node) { | 484 visitNode(Node node) { |
| 485 throw 'not supported'; | 485 throw 'not supported'; |
| 486 } | 486 } |
| 487 | 487 |
| 488 ConstructorResult reportAndCreateErroneousConstructorElement( | 488 ConstructorResult reportAndCreateErroneousConstructorElement( |
| 489 Spannable diagnosticNode, | 489 Spannable diagnosticNode, |
| 490 ConstructorResultKind resultKind, | 490 ConstructorResultKind resultKind, |
| 491 DartType type, | 491 ResolutionDartType type, |
| 492 String name, | 492 String name, |
| 493 MessageKind kind, | 493 MessageKind kind, |
| 494 Map arguments, | 494 Map arguments, |
| 495 {bool isError: false, | 495 {bool isError: false, |
| 496 bool missingConstructor: false, | 496 bool missingConstructor: false, |
| 497 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { | 497 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { |
| 498 if (missingConstructor) { | 498 if (missingConstructor) { |
| 499 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); | 499 registry.registerFeature(Feature.THROW_NO_SUCH_METHOD); |
| 500 } else { | 500 } else { |
| 501 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 501 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 502 } | 502 } |
| 503 DiagnosticMessage message = | 503 DiagnosticMessage message = |
| 504 reporter.createMessage(diagnosticNode, kind, arguments); | 504 reporter.createMessage(diagnosticNode, kind, arguments); |
| 505 if (isError || inConstContext) { | 505 if (isError || inConstContext) { |
| 506 reporter.reportError(message, infos); | 506 reporter.reportError(message, infos); |
| 507 } else { | 507 } else { |
| 508 reporter.reportWarning(message, infos); | 508 reporter.reportWarning(message, infos); |
| 509 } | 509 } |
| 510 ErroneousElement error = | 510 ErroneousElement error = |
| 511 new ErroneousConstructorElementX(kind, arguments, name, context); | 511 new ErroneousConstructorElementX(kind, arguments, name, context); |
| 512 if (type == null) { | 512 if (type == null) { |
| 513 type = new MalformedType(error, null); | 513 type = new MalformedType(error, null); |
| 514 } | 514 } |
| 515 return new ConstructorResult.forError(resultKind, error, type); | 515 return new ConstructorResult.forError(resultKind, error, type); |
| 516 } | 516 } |
| 517 | 517 |
| 518 ConstructorResult resolveConstructor(PrefixElement prefix, InterfaceType type, | 518 ConstructorResult resolveConstructor( |
| 519 Node diagnosticNode, String constructorName) { | 519 PrefixElement prefix, |
| 520 ResolutionInterfaceType type, |
| 521 Node diagnosticNode, |
| 522 String constructorName) { |
| 520 ClassElement cls = type.element; | 523 ClassElement cls = type.element; |
| 521 cls.ensureResolved(resolution); | 524 cls.ensureResolved(resolution); |
| 522 ConstructorElement constructor = | 525 ConstructorElement constructor = |
| 523 findConstructor(context.library, cls, constructorName); | 526 findConstructor(context.library, cls, constructorName); |
| 524 if (constructor == null) { | 527 if (constructor == null) { |
| 525 MessageKind kind = constructorName.isEmpty | 528 MessageKind kind = constructorName.isEmpty |
| 526 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR | 529 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR |
| 527 : MessageKind.CANNOT_FIND_CONSTRUCTOR; | 530 : MessageKind.CANNOT_FIND_CONSTRUCTOR; |
| 528 return reportAndCreateErroneousConstructorElement( | 531 return reportAndCreateErroneousConstructorElement( |
| 529 diagnosticNode, | 532 diagnosticNode, |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 {'node': diagnosticNode}); | 612 {'node': diagnosticNode}); |
| 610 } | 613 } |
| 611 } | 614 } |
| 612 resolver.registry.setType(expression, result.type); | 615 resolver.registry.setType(expression, result.type); |
| 613 return result; | 616 return result; |
| 614 } | 617 } |
| 615 | 618 |
| 616 ConstructorResult visitTypeAnnotation(TypeAnnotation node) { | 619 ConstructorResult visitTypeAnnotation(TypeAnnotation node) { |
| 617 // This is not really resolving a type-annotation, but the name of the | 620 // This is not really resolving a type-annotation, but the name of the |
| 618 // constructor. Therefore we allow deferred types. | 621 // constructor. Therefore we allow deferred types. |
| 619 DartType type = resolver.resolveTypeAnnotation(node, | 622 ResolutionDartType type = resolver.resolveTypeAnnotation(node, |
| 620 malformedIsError: inConstContext, | 623 malformedIsError: inConstContext, |
| 621 deferredIsMalformed: false, | 624 deferredIsMalformed: false, |
| 622 registerCheckedModeCheck: false); | 625 registerCheckedModeCheck: false); |
| 623 Send send = node.typeName.asSend(); | 626 Send send = node.typeName.asSend(); |
| 624 PrefixElement prefix; | 627 PrefixElement prefix; |
| 625 if (send != null) { | 628 if (send != null) { |
| 626 // The type name is of the form [: prefix . identifier :]. | 629 // The type name is of the form [: prefix . identifier :]. |
| 627 String name = send.receiver.asIdentifier().source; | 630 String name = send.receiver.asIdentifier().source; |
| 628 Element element = lookupInScope(reporter, send, resolver.scope, name); | 631 Element element = lookupInScope(reporter, send, resolver.scope, name); |
| 629 if (element != null && element.isPrefix) { | 632 if (element != null && element.isPrefix) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 if (error is! ErroneousElementX) { | 743 if (error is! ErroneousElementX) { |
| 741 // Parser error. The error has already been reported. | 744 // Parser error. The error has already been reported. |
| 742 error = new ErroneousConstructorElementX( | 745 error = new ErroneousConstructorElementX( |
| 743 MessageKind.NOT_A_TYPE, {'node': node}, error.name, error); | 746 MessageKind.NOT_A_TYPE, {'node': node}, error.name, error); |
| 744 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 747 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 745 } | 748 } |
| 746 return new ConstructorResult.forError(ConstructorResultKind.INVALID_TYPE, | 749 return new ConstructorResult.forError(ConstructorResultKind.INVALID_TYPE, |
| 747 error, new MalformedType(error, null)); | 750 error, new MalformedType(error, null)); |
| 748 } | 751 } |
| 749 | 752 |
| 750 ConstructorResult constructorResultForType(Node node, DartType type, | 753 ConstructorResult constructorResultForType(Node node, ResolutionDartType type, |
| 751 {PrefixElement prefix}) { | 754 {PrefixElement prefix}) { |
| 752 String name = type.name; | 755 String name = type.name; |
| 753 if (type.isTypeVariable) { | 756 if (type.isTypeVariable) { |
| 754 return reportAndCreateErroneousConstructorElement( | 757 return reportAndCreateErroneousConstructorElement( |
| 755 node, | 758 node, |
| 756 ConstructorResultKind.INVALID_TYPE, | 759 ConstructorResultKind.INVALID_TYPE, |
| 757 type, | 760 type, |
| 758 name, | 761 name, |
| 759 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, | 762 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, |
| 760 {'typeVariableName': name}); | 763 {'typeVariableName': name}); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 /// The kind of the found constructor. | 812 /// The kind of the found constructor. |
| 810 final ConstructorResultKind kind; | 813 final ConstructorResultKind kind; |
| 811 | 814 |
| 812 /// The currently found element. Since [ConstructorResult] is used for partial | 815 /// The currently found element. Since [ConstructorResult] is used for partial |
| 813 /// results, this might be a [PrefixElement], a [ClassElement], a | 816 /// results, this might be a [PrefixElement], a [ClassElement], a |
| 814 /// [ConstructorElement] or in the negative cases an [ErroneousElement]. | 817 /// [ConstructorElement] or in the negative cases an [ErroneousElement]. |
| 815 final Element element; | 818 final Element element; |
| 816 | 819 |
| 817 /// The type of the new expression. For instance `Foo<String>` in | 820 /// The type of the new expression. For instance `Foo<String>` in |
| 818 /// `new prefix.Foo<String>.constructorName()`. | 821 /// `new prefix.Foo<String>.constructorName()`. |
| 819 final DartType type; | 822 final ResolutionDartType type; |
| 820 | 823 |
| 821 /// Creates a fully resolved constructor access where [element] is resolved | 824 /// Creates a fully resolved constructor access where [element] is resolved |
| 822 /// to a constructor and [type] to an interface type. | 825 /// to a constructor and [type] to an interface type. |
| 823 ConstructorResult(this.kind, this.prefix, ConstructorElement this.element, | 826 ConstructorResult(this.kind, this.prefix, ConstructorElement this.element, |
| 824 InterfaceType this.type); | 827 ResolutionInterfaceType this.type); |
| 825 | 828 |
| 826 /// Creates a fully resolved constructor access where [element] is an | 829 /// Creates a fully resolved constructor access where [element] is an |
| 827 /// [ErroneousElement]. | 830 /// [ErroneousElement]. |
| 828 // TODO(johnniwinther): Do we still need the prefix for cases like | 831 // TODO(johnniwinther): Do we still need the prefix for cases like |
| 829 // `new deferred.Class.unresolvedConstructor()` ? | 832 // `new deferred.Class.unresolvedConstructor()` ? |
| 830 ConstructorResult.forError( | 833 ConstructorResult.forError( |
| 831 this.kind, ErroneousElement this.element, this.type) | 834 this.kind, ErroneousElement this.element, this.type) |
| 832 : prefix = null; | 835 : prefix = null; |
| 833 | 836 |
| 834 /// Creates a constructor access that is partially resolved to a prefix. For | 837 /// Creates a constructor access that is partially resolved to a prefix. For |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 // constructors. | 882 // constructors. |
| 880 return null; | 883 return null; |
| 881 } | 884 } |
| 882 // TODO(johnniwinther): Use [Name] for lookup. | 885 // TODO(johnniwinther): Use [Name] for lookup. |
| 883 ConstructorElement constructor = cls.lookupConstructor(constructorName); | 886 ConstructorElement constructor = cls.lookupConstructor(constructorName); |
| 884 if (constructor != null) { | 887 if (constructor != null) { |
| 885 constructor = constructor.declaration; | 888 constructor = constructor.declaration; |
| 886 } | 889 } |
| 887 return constructor; | 890 return constructor; |
| 888 } | 891 } |
| OLD | NEW |