| 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 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 abstract class TreeElements { | 7 abstract class TreeElements { |
| 8 AnalyzableElement get analyzedElement; | 8 AnalyzableElement get analyzedElement; |
| 9 Iterable<Node> get superUses; | 9 Iterable<Node> get superUses; |
| 10 | 10 |
| (...skipping 1531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1542 functionNode, | 1542 functionNode, |
| 1543 className, | 1543 className, |
| 1544 constructorSelector); | 1544 constructorSelector); |
| 1545 registry.registerImplicitSuperCall(calledConstructor); | 1545 registry.registerImplicitSuperCall(calledConstructor); |
| 1546 registry.registerStaticUse(calledConstructor); | 1546 registry.registerStaticUse(calledConstructor); |
| 1547 } | 1547 } |
| 1548 } | 1548 } |
| 1549 | 1549 |
| 1550 void verifyThatConstructorMatchesCall( | 1550 void verifyThatConstructorMatchesCall( |
| 1551 FunctionElement caller, | 1551 FunctionElement caller, |
| 1552 FunctionElement lookedupConstructor, | 1552 ConstructorElementX lookedupConstructor, |
| 1553 Selector call, | 1553 Selector call, |
| 1554 bool isImplicitSuperCall, | 1554 bool isImplicitSuperCall, |
| 1555 Node diagnosticNode, | 1555 Node diagnosticNode, |
| 1556 String className, | 1556 String className, |
| 1557 Selector constructorSelector) { | 1557 Selector constructorSelector) { |
| 1558 if (lookedupConstructor == null | 1558 if (lookedupConstructor == null |
| 1559 || !lookedupConstructor.isGenerativeConstructor) { | 1559 || !lookedupConstructor.isGenerativeConstructor) { |
| 1560 String fullConstructorName = Elements.constructorNameForDiagnostics( | 1560 String fullConstructorName = Elements.constructorNameForDiagnostics( |
| 1561 className, | 1561 className, |
| 1562 constructorSelector.name); | 1562 constructorSelector.name); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1577 visitor.compiler.reportError( | 1577 visitor.compiler.reportError( |
| 1578 diagnosticNode, MessageKind.CONST_CALLS_NON_CONST); | 1578 diagnosticNode, MessageKind.CONST_CALLS_NON_CONST); |
| 1579 } | 1579 } |
| 1580 } | 1580 } |
| 1581 } | 1581 } |
| 1582 | 1582 |
| 1583 /** | 1583 /** |
| 1584 * Resolve all initializers of this constructor. In the case of a redirecting | 1584 * Resolve all initializers of this constructor. In the case of a redirecting |
| 1585 * constructor, the resolved constructor's function element is returned. | 1585 * constructor, the resolved constructor's function element is returned. |
| 1586 */ | 1586 */ |
| 1587 FunctionElement resolveInitializers(FunctionElement constructor, | 1587 ConstructorElement resolveInitializers(ConstructorElementX constructor, |
| 1588 FunctionExpression functionNode) { | 1588 FunctionExpression functionNode) { |
| 1589 // Keep track of all "this.param" parameters specified for constructor so | 1589 // Keep track of all "this.param" parameters specified for constructor so |
| 1590 // that we can ensure that fields are initialized only once. | 1590 // that we can ensure that fields are initialized only once. |
| 1591 FunctionSignature functionParameters = constructor.functionSignature; | 1591 FunctionSignature functionParameters = constructor.functionSignature; |
| 1592 functionParameters.forEachParameter((ParameterElement element) { | 1592 functionParameters.forEachParameter((ParameterElement element) { |
| 1593 if (element.isInitializingFormal) { | 1593 if (element.isInitializingFormal) { |
| 1594 InitializingFormalElement initializingFormal = element; | 1594 InitializingFormalElement initializingFormal = element; |
| 1595 checkForDuplicateInitializers(initializingFormal.fieldElement, | 1595 checkForDuplicateInitializers(initializingFormal.fieldElement, |
| 1596 element.initializer); | 1596 element.initializer); |
| 1597 } | 1597 } |
| 1598 }); | 1598 }); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1623 } else if (Initializers.isConstructorRedirect(call)) { | 1623 } else if (Initializers.isConstructorRedirect(call)) { |
| 1624 // Check that there is no body (Language specification 7.5.1). If the | 1624 // Check that there is no body (Language specification 7.5.1). If the |
| 1625 // constructor is also const, we already reported an error in | 1625 // constructor is also const, we already reported an error in |
| 1626 // [resolveMethodElement]. | 1626 // [resolveMethodElement]. |
| 1627 if (functionNode.hasBody() && !constructor.isConst) { | 1627 if (functionNode.hasBody() && !constructor.isConst) { |
| 1628 error(functionNode, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY); | 1628 error(functionNode, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY); |
| 1629 } | 1629 } |
| 1630 // Check that there are no other initializers. | 1630 // Check that there are no other initializers. |
| 1631 if (!initializers.tail.isEmpty) { | 1631 if (!initializers.tail.isEmpty) { |
| 1632 error(call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER); | 1632 error(call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER); |
| 1633 } else { |
| 1634 constructor.isRedirectingGenerative = true; |
| 1633 } | 1635 } |
| 1634 // Check that there are no field initializing parameters. | 1636 // Check that there are no field initializing parameters. |
| 1635 Compiler compiler = visitor.compiler; | 1637 Compiler compiler = visitor.compiler; |
| 1636 FunctionSignature signature = constructor.functionSignature; | 1638 FunctionSignature signature = constructor.functionSignature; |
| 1637 signature.forEachParameter((ParameterElement parameter) { | 1639 signature.forEachParameter((ParameterElement parameter) { |
| 1638 if (parameter.isInitializingFormal) { | 1640 if (parameter.isInitializingFormal) { |
| 1639 Node node = parameter.node; | 1641 Node node = parameter.node; |
| 1640 error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED); | 1642 error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED); |
| 1641 } | 1643 } |
| 1642 }); | 1644 }); |
| (...skipping 1502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3145 Node expression = node.expression; | 3147 Node expression = node.expression; |
| 3146 if (expression != null) { | 3148 if (expression != null) { |
| 3147 if (enclosingElement.isGenerativeConstructor) { | 3149 if (enclosingElement.isGenerativeConstructor) { |
| 3148 // It is a compile-time error if a return statement of the form | 3150 // It is a compile-time error if a return statement of the form |
| 3149 // `return e;` appears in a generative constructor. (Dart Language | 3151 // `return e;` appears in a generative constructor. (Dart Language |
| 3150 // Specification 13.12.) | 3152 // Specification 13.12.) |
| 3151 compiler.reportError(expression, | 3153 compiler.reportError(expression, |
| 3152 MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR); | 3154 MessageKind.CANNOT_RETURN_FROM_CONSTRUCTOR); |
| 3153 } else if (!node.isArrowBody && currentAsyncMarker.isYielding) { | 3155 } else if (!node.isArrowBody && currentAsyncMarker.isYielding) { |
| 3154 compiler.reportError( | 3156 compiler.reportError( |
| 3155 node, | 3157 node, |
| 3156 MessageKind.RETURN_IN_GENERATOR, | 3158 MessageKind.RETURN_IN_GENERATOR, |
| 3157 {'modifier': currentAsyncMarker}); | 3159 {'modifier': currentAsyncMarker}); |
| 3158 } | 3160 } |
| 3159 } | 3161 } |
| 3160 visit(node.expression); | 3162 visit(node.expression); |
| 3161 } | 3163 } |
| 3162 | 3164 |
| 3163 visitYield(Yield node) { | 3165 visitYield(Yield node) { |
| 3164 compiler.streamClass.ensureResolved(compiler); | 3166 compiler.streamClass.ensureResolved(compiler); |
| 3165 compiler.iterableClass.ensureResolved(compiler); | 3167 compiler.iterableClass.ensureResolved(compiler); |
| 3166 visit(node.expression); | 3168 visit(node.expression); |
| (...skipping 1656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4823 ConstructorResolver(Compiler compiler, this.resolver, | 4825 ConstructorResolver(Compiler compiler, this.resolver, |
| 4824 {bool this.inConstContext: false}) | 4826 {bool this.inConstContext: false}) |
| 4825 : super(compiler); | 4827 : super(compiler); |
| 4826 | 4828 |
| 4827 ResolutionRegistry get registry => resolver.registry; | 4829 ResolutionRegistry get registry => resolver.registry; |
| 4828 | 4830 |
| 4829 visitNode(Node node) { | 4831 visitNode(Node node) { |
| 4830 throw 'not supported'; | 4832 throw 'not supported'; |
| 4831 } | 4833 } |
| 4832 | 4834 |
| 4833 failOrReturnErroneousConstructorElement( | 4835 ErroneousConstructorElementX failOrReturnErroneousConstructorElement( |
| 4834 Element enclosing, Node diagnosticNode, | 4836 Spannable diagnosticNode, |
| 4835 String targetName, MessageKind kind, | 4837 Element enclosing, |
| 4836 Map arguments) { | 4838 String name, |
| 4837 if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { | 4839 MessageKind kind, |
| 4840 Map arguments, |
| 4841 {bool isError: false, |
| 4842 bool missingConstructor: false}) { |
| 4843 if (missingConstructor) { |
| 4838 registry.registerThrowNoSuchMethod(); | 4844 registry.registerThrowNoSuchMethod(); |
| 4839 } else { | 4845 } else { |
| 4840 registry.registerThrowRuntimeError(); | 4846 registry.registerThrowRuntimeError(); |
| 4841 } | 4847 } |
| 4842 if (inConstContext) { | 4848 if (isError || inConstContext) { |
| 4843 compiler.reportError(diagnosticNode, kind, arguments); | 4849 compiler.reportError(diagnosticNode, kind, arguments); |
| 4844 } else { | 4850 } else { |
| 4845 compiler.reportWarning(diagnosticNode, kind, arguments); | 4851 compiler.reportWarning(diagnosticNode, kind, arguments); |
| 4846 } | 4852 } |
| 4847 return new ErroneousConstructorElementX( | 4853 return new ErroneousConstructorElementX( |
| 4848 kind, arguments, targetName, enclosing); | 4854 kind, arguments, name, enclosing); |
| 4849 } | 4855 } |
| 4850 | 4856 |
| 4851 FunctionElement resolveConstructor(ClassElement cls, | 4857 FunctionElement resolveConstructor(ClassElement cls, |
| 4852 Node diagnosticNode, | 4858 Node diagnosticNode, |
| 4853 String constructorName) { | 4859 String constructorName) { |
| 4854 cls.ensureResolved(compiler); | 4860 cls.ensureResolved(compiler); |
| 4855 Element result = cls.lookupConstructor(constructorName); | 4861 Element result = cls.lookupConstructor(constructorName); |
| 4856 if (result == null) { | 4862 if (result == null) { |
| 4857 String fullConstructorName = Elements.constructorNameForDiagnostics( | 4863 String fullConstructorName = Elements.constructorNameForDiagnostics( |
| 4858 cls.name, | 4864 cls.name, |
| 4859 constructorName); | 4865 constructorName); |
| 4860 return failOrReturnErroneousConstructorElement( | 4866 return failOrReturnErroneousConstructorElement( |
| 4861 cls, | |
| 4862 diagnosticNode, | 4867 diagnosticNode, |
| 4863 fullConstructorName, | 4868 cls, constructorName, |
| 4864 MessageKind.CANNOT_FIND_CONSTRUCTOR, | 4869 MessageKind.CANNOT_FIND_CONSTRUCTOR, |
| 4865 {'constructorName': fullConstructorName}); | 4870 {'constructorName': fullConstructorName}, |
| 4871 missingConstructor: true); |
| 4866 } else if (inConstContext && !result.isConst) { | 4872 } else if (inConstContext && !result.isConst) { |
| 4867 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); | 4873 error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); |
| 4868 } | 4874 } |
| 4869 return result; | 4875 return result; |
| 4870 } | 4876 } |
| 4871 | 4877 |
| 4872 Element visitNewExpression(NewExpression node) { | 4878 Element visitNewExpression(NewExpression node) { |
| 4873 inConstContext = node.isConst; | 4879 inConstContext = node.isConst; |
| 4874 Node selector = node.send.selector; | 4880 Node selector = node.send.selector; |
| 4875 Element element = visit(selector); | 4881 Element element = visit(selector); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4888 // Find the unnamed constructor if the reference resolved to a | 4894 // Find the unnamed constructor if the reference resolved to a |
| 4889 // class. | 4895 // class. |
| 4890 if (!Elements.isUnresolved(element) && !element.isConstructor) { | 4896 if (!Elements.isUnresolved(element) && !element.isConstructor) { |
| 4891 if (element.isClass) { | 4897 if (element.isClass) { |
| 4892 ClassElement cls = element; | 4898 ClassElement cls = element; |
| 4893 cls.ensureResolved(compiler); | 4899 cls.ensureResolved(compiler); |
| 4894 // The unnamed constructor may not exist, so [e] may become unresolved. | 4900 // The unnamed constructor may not exist, so [e] may become unresolved. |
| 4895 element = resolveConstructor(cls, diagnosticNode, ''); | 4901 element = resolveConstructor(cls, diagnosticNode, ''); |
| 4896 } else { | 4902 } else { |
| 4897 element = failOrReturnErroneousConstructorElement( | 4903 element = failOrReturnErroneousConstructorElement( |
| 4898 element, diagnosticNode, element.name, MessageKind.NOT_A_TYPE, | 4904 diagnosticNode, |
| 4899 {'node': diagnosticNode}); | 4905 element, element.name, |
| 4906 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}); |
| 4900 } | 4907 } |
| 4901 } else if (element.isErroneous && element is! ErroneousElementX) { | 4908 } else if (element.isErroneous && element is! ErroneousElementX) { |
| 4909 // Parser error. The error has already been reported. |
| 4902 element = new ErroneousConstructorElementX( | 4910 element = new ErroneousConstructorElementX( |
| 4903 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}, | 4911 MessageKind.NOT_A_TYPE, {'node': diagnosticNode}, |
| 4904 element.name, element); | 4912 element.name, element); |
| 4905 registry.registerThrowRuntimeError(); | 4913 registry.registerThrowRuntimeError(); |
| 4906 } | 4914 } |
| 4907 | 4915 |
| 4908 if (type == null) { | 4916 if (type == null) { |
| 4909 if (Elements.isUnresolved(element)) { | 4917 if (Elements.isUnresolved(element)) { |
| 4910 type = const DynamicType(); | 4918 type = const DynamicType(); |
| 4911 } else { | 4919 } else { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4938 if (element.isClass) { | 4946 if (element.isClass) { |
| 4939 ClassElement cls = element; | 4947 ClassElement cls = element; |
| 4940 cls.ensureResolved(compiler); | 4948 cls.ensureResolved(compiler); |
| 4941 return resolveConstructor(cls, name, name.source); | 4949 return resolveConstructor(cls, name, name.source); |
| 4942 } else if (element.isPrefix) { | 4950 } else if (element.isPrefix) { |
| 4943 PrefixElement prefix = element; | 4951 PrefixElement prefix = element; |
| 4944 element = prefix.lookupLocalMember(name.source); | 4952 element = prefix.lookupLocalMember(name.source); |
| 4945 element = Elements.unwrap(element, compiler, node); | 4953 element = Elements.unwrap(element, compiler, node); |
| 4946 if (element == null) { | 4954 if (element == null) { |
| 4947 return failOrReturnErroneousConstructorElement( | 4955 return failOrReturnErroneousConstructorElement( |
| 4948 resolver.enclosingElement, name, | 4956 name, |
| 4949 name.source, | 4957 resolver.enclosingElement, name.source, |
| 4950 MessageKind.CANNOT_RESOLVE, | 4958 MessageKind.CANNOT_RESOLVE, {'name': name}); |
| 4951 {'name': name}); | |
| 4952 } else if (!element.isClass) { | 4959 } else if (!element.isClass) { |
| 4953 error(node, MessageKind.NOT_A_TYPE, {'node': name}); | 4960 return failOrReturnErroneousConstructorElement( |
| 4961 name, |
| 4962 resolver.enclosingElement, name.source, |
| 4963 MessageKind.NOT_A_TYPE, {'node': name}, |
| 4964 isError: true); |
| 4954 } | 4965 } |
| 4955 } else { | 4966 } else { |
| 4956 internalError(node.receiver, 'unexpected element $element'); | 4967 internalError(node.receiver, 'unexpected element $element'); |
| 4957 } | 4968 } |
| 4958 return element; | 4969 return element; |
| 4959 } | 4970 } |
| 4960 | 4971 |
| 4961 Element visitIdentifier(Identifier node) { | 4972 Element visitIdentifier(Identifier node) { |
| 4962 String name = node.source; | 4973 String name = node.source; |
| 4963 Element element = resolver.reportLookupErrorIfAny( | 4974 Element element = resolver.reportLookupErrorIfAny( |
| 4964 lookupInScope(compiler, node, resolver.scope, name), node, name); | 4975 lookupInScope(compiler, node, resolver.scope, name), node, name); |
| 4965 registry.useElement(node, element); | 4976 registry.useElement(node, element); |
| 4966 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. | 4977 // TODO(johnniwinther): Change errors to warnings, cf. 11.11.1. |
| 4967 if (element == null) { | 4978 if (element == null) { |
| 4968 return failOrReturnErroneousConstructorElement( | 4979 return failOrReturnErroneousConstructorElement( |
| 4969 resolver.enclosingElement, node, name, | 4980 node, |
| 4981 resolver.enclosingElement, name, |
| 4970 MessageKind.CANNOT_RESOLVE, | 4982 MessageKind.CANNOT_RESOLVE, |
| 4971 {'name': name}); | 4983 {'name': name}); |
| 4972 } else if (element.isErroneous) { | 4984 } else if (element.isErroneous) { |
| 4973 return element; | 4985 return element; |
| 4974 } else if (element.isTypedef) { | 4986 } else if (element.isTypedef) { |
| 4975 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, | 4987 element = failOrReturnErroneousConstructorElement( |
| 4976 {'typedefName': name}); | 4988 node, |
| 4977 element = new ErroneousConstructorElementX( | 4989 resolver.enclosingElement, name, |
| 4978 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, | 4990 MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name}, |
| 4979 {'typedefName': name}, name, resolver.enclosingElement); | 4991 isError: true); |
| 4980 registry.registerThrowRuntimeError(); | |
| 4981 } else if (element.isTypeVariable) { | 4992 } else if (element.isTypeVariable) { |
| 4982 error(node, MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, | 4993 element = failOrReturnErroneousConstructorElement( |
| 4983 {'typeVariableName': name}); | 4994 node, |
| 4984 element = new ErroneousConstructorElementX( | 4995 resolver.enclosingElement, name, |
| 4985 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, | 4996 MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE, |
| 4986 {'typeVariableName': name}, name, resolver.enclosingElement); | 4997 {'typeVariableName': name}, |
| 4987 registry.registerThrowRuntimeError(); | 4998 isError: true); |
| 4988 } else if (!element.isClass && !element.isPrefix) { | 4999 } else if (!element.isClass && !element.isPrefix) { |
| 4989 error(node, MessageKind.NOT_A_TYPE, {'node': name}); | 5000 element = failOrReturnErroneousConstructorElement( |
| 4990 element = new ErroneousConstructorElementX( | 5001 node, |
| 4991 MessageKind.NOT_A_TYPE, {'node': name}, name, | 5002 resolver.enclosingElement, name, |
| 4992 resolver.enclosingElement); | 5003 MessageKind.NOT_A_TYPE, {'node': name}, |
| 4993 registry.registerThrowRuntimeError(); | 5004 isError: true); |
| 4994 } | 5005 } |
| 4995 return element; | 5006 return element; |
| 4996 } | 5007 } |
| 4997 | 5008 |
| 4998 /// Assumed to be called by [resolveRedirectingFactory]. | 5009 /// Assumed to be called by [resolveRedirectingFactory]. |
| 4999 Element visitRedirectingFactoryBody(RedirectingFactoryBody node) { | 5010 Element visitRedirectingFactoryBody(RedirectingFactoryBody node) { |
| 5000 Node constructorReference = node.constructorReference; | 5011 Node constructorReference = node.constructorReference; |
| 5001 return finishConstructorReference(visit(constructorReference), | 5012 return finishConstructorReference(visit(constructorReference), |
| 5002 constructorReference, node); | 5013 constructorReference, node); |
| 5003 } | 5014 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5066 } | 5077 } |
| 5067 | 5078 |
| 5068 /// The result for the resolution of the `assert` method. | 5079 /// The result for the resolution of the `assert` method. |
| 5069 class AssertResult implements ResolutionResult { | 5080 class AssertResult implements ResolutionResult { |
| 5070 const AssertResult(); | 5081 const AssertResult(); |
| 5071 | 5082 |
| 5072 Element get element => null; | 5083 Element get element => null; |
| 5073 | 5084 |
| 5074 String toString() => 'AssertResult()'; | 5085 String toString() => 'AssertResult()'; |
| 5075 } | 5086 } |
| OLD | NEW |