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.members; | 5 library dart2js.resolution.members; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/names.dart' show | 8 import '../common/names.dart' show |
9 Selectors; | 9 Selectors; |
10 import '../compiler.dart' show | 10 import '../compiler.dart' show |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 // TODO(karlklose): clean this up (dartbug.com/8870). | 177 // TODO(karlklose): clean this up (dartbug.com/8870). |
178 inCheckContext = compiler.enableTypeAssertions && | 178 inCheckContext = compiler.enableTypeAssertions && |
179 !element.isLibrary && | 179 !element.isLibrary && |
180 !element.isTypedef && | 180 !element.isTypedef && |
181 !element.enclosingElement.isTypedef, | 181 !element.enclosingElement.isTypedef, |
182 inCatchBlock = false, | 182 inCatchBlock = false, |
183 constantState = element.isConst | 183 constantState = element.isConst |
184 ? ConstantState.CONSTANT : ConstantState.NON_CONSTANT, | 184 ? ConstantState.CONSTANT : ConstantState.NON_CONSTANT, |
185 super(compiler, registry); | 185 super(compiler, registry); |
186 | 186 |
| 187 CoreClasses get coreClasses => compiler.coreClasses; |
| 188 |
187 CoreTypes get coreTypes => compiler.coreTypes; | 189 CoreTypes get coreTypes => compiler.coreTypes; |
188 | 190 |
189 AsyncMarker get currentAsyncMarker { | 191 AsyncMarker get currentAsyncMarker { |
190 if (enclosingElement is FunctionElement) { | 192 if (enclosingElement is FunctionElement) { |
191 FunctionElement function = enclosingElement; | 193 FunctionElement function = enclosingElement; |
192 return function.asyncMarker; | 194 return function.asyncMarker; |
193 } | 195 } |
194 return AsyncMarker.SYNC; | 196 return AsyncMarker.SYNC; |
195 } | 197 } |
196 | 198 |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 reporter.reportErrorMessage( | 354 reporter.reportErrorMessage( |
353 node, MessageKind.INVALID_USE_OF_SUPER); | 355 node, MessageKind.INVALID_USE_OF_SUPER); |
354 } | 356 } |
355 return const NoneResult(); | 357 return const NoneResult(); |
356 } else { | 358 } else { |
357 String name = node.source; | 359 String name = node.source; |
358 Element element = lookupInScope(reporter, node, scope, name); | 360 Element element = lookupInScope(reporter, node, scope, name); |
359 if (Elements.isUnresolved(element) && name == 'dynamic') { | 361 if (Elements.isUnresolved(element) && name == 'dynamic') { |
360 // TODO(johnniwinther): Remove this hack when we can return more complex | 362 // TODO(johnniwinther): Remove this hack when we can return more complex |
361 // objects than [Element] from this method. | 363 // objects than [Element] from this method. |
362 element = compiler.typeClass; | 364 element = coreClasses.typeClass; |
363 // Set the type to be `dynamic` to mark that this is a type literal. | 365 // Set the type to be `dynamic` to mark that this is a type literal. |
364 registry.setType(node, const DynamicType()); | 366 registry.setType(node, const DynamicType()); |
365 } | 367 } |
366 element = reportLookupErrorIfAny(element, node, name); | 368 element = reportLookupErrorIfAny(element, node, name); |
367 if (element == null) { | 369 if (element == null) { |
368 if (!inInstanceContext) { | 370 if (!inInstanceContext) { |
369 element = reportCannotResolve(node, name); | 371 element = reportCannotResolve(node, name); |
370 } | 372 } |
371 } else if (element.isMalformed) { | 373 } else if (element.isMalformed) { |
372 // Use the malformed element. | 374 // Use the malformed element. |
(...skipping 1730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2103 /// Handle access to a type literal of the type 'dynamic'. Like `dynamic` or | 2105 /// Handle access to a type literal of the type 'dynamic'. Like `dynamic` or |
2104 /// `dynamic()`. | 2106 /// `dynamic()`. |
2105 ResolutionResult handleDynamicTypeLiteralAccess(Send node) { | 2107 ResolutionResult handleDynamicTypeLiteralAccess(Send node) { |
2106 DartType type = const DynamicType(); | 2108 DartType type = const DynamicType(); |
2107 ConstantExpression constant = new TypeConstantExpression( | 2109 ConstantExpression constant = new TypeConstantExpression( |
2108 // TODO(johnniwinther): Use [type] when evaluation of constants is done | 2110 // TODO(johnniwinther): Use [type] when evaluation of constants is done |
2109 // directly on the constant expressions. | 2111 // directly on the constant expressions. |
2110 node.isCall ? coreTypes.typeType : type); | 2112 node.isCall ? coreTypes.typeType : type); |
2111 AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant); | 2113 AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant); |
2112 return handleConstantTypeLiteralAccess( | 2114 return handleConstantTypeLiteralAccess( |
2113 node, const PublicName('dynamic'), compiler.typeClass, type, semantics); | 2115 node, const PublicName('dynamic'), |
| 2116 coreClasses.typeClass, type, semantics); |
2114 } | 2117 } |
2115 | 2118 |
2116 /// Handle update to a type literal of the type 'dynamic'. Like `dynamic++` or | 2119 /// Handle update to a type literal of the type 'dynamic'. Like `dynamic++` or |
2117 /// `dynamic = 0`. | 2120 /// `dynamic = 0`. |
2118 ResolutionResult handleDynamicTypeLiteralUpdate(SendSet node) { | 2121 ResolutionResult handleDynamicTypeLiteralUpdate(SendSet node) { |
2119 DartType type = const DynamicType(); | 2122 DartType type = const DynamicType(); |
2120 ConstantExpression constant = | 2123 ConstantExpression constant = |
2121 new TypeConstantExpression(const DynamicType()); | 2124 new TypeConstantExpression(const DynamicType()); |
2122 AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant); | 2125 AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant); |
2123 return handleConstantTypeLiteralUpdate( | 2126 return handleConstantTypeLiteralUpdate( |
2124 node, const PublicName('dynamic'), compiler.typeClass, type, semantics); | 2127 node, const PublicName('dynamic'), |
| 2128 coreClasses.typeClass, type, semantics); |
2125 } | 2129 } |
2126 | 2130 |
2127 /// Handle access to a type literal of a class. Like `C` or | 2131 /// Handle access to a type literal of a class. Like `C` or |
2128 /// `C()` where 'C' is class. | 2132 /// `C()` where 'C' is class. |
2129 ResolutionResult handleClassTypeLiteralAccess( | 2133 ResolutionResult handleClassTypeLiteralAccess( |
2130 Send node, | 2134 Send node, |
2131 Name name, | 2135 Name name, |
2132 ClassElement cls) { | 2136 ClassElement cls) { |
2133 cls.ensureResolved(resolution); | 2137 cls.ensureResolved(resolution); |
2134 DartType type = cls.rawType; | 2138 DartType type = cls.rawType; |
(...skipping 1439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3574 node, | 3578 node, |
3575 MessageKind.RETURN_IN_GENERATOR, | 3579 MessageKind.RETURN_IN_GENERATOR, |
3576 {'modifier': currentAsyncMarker}); | 3580 {'modifier': currentAsyncMarker}); |
3577 } | 3581 } |
3578 } | 3582 } |
3579 visit(node.expression); | 3583 visit(node.expression); |
3580 return const NoneResult(); | 3584 return const NoneResult(); |
3581 } | 3585 } |
3582 | 3586 |
3583 ResolutionResult visitYield(Yield node) { | 3587 ResolutionResult visitYield(Yield node) { |
3584 compiler.streamClass.ensureResolved(resolution); | 3588 coreClasses.streamClass.ensureResolved(resolution); |
3585 compiler.iterableClass.ensureResolved(resolution); | 3589 coreClasses.iterableClass.ensureResolved(resolution); |
3586 visit(node.expression); | 3590 visit(node.expression); |
3587 return const NoneResult(); | 3591 return const NoneResult(); |
3588 } | 3592 } |
3589 | 3593 |
3590 ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) { | 3594 ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) { |
3591 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor; | 3595 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor; |
3592 if (!enclosingElement.isFactoryConstructor) { | 3596 if (!enclosingElement.isFactoryConstructor) { |
3593 reporter.reportErrorMessage( | 3597 reporter.reportErrorMessage( |
3594 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); | 3598 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); |
3595 reporter.reportHintMessage( | 3599 reporter.reportHintMessage( |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3699 return const NoneResult(); | 3703 return const NoneResult(); |
3700 } | 3704 } |
3701 | 3705 |
3702 ResolutionResult visitThrow(Throw node) { | 3706 ResolutionResult visitThrow(Throw node) { |
3703 registry.registerThrowExpression(); | 3707 registry.registerThrowExpression(); |
3704 visit(node.expression); | 3708 visit(node.expression); |
3705 return const NoneResult(); | 3709 return const NoneResult(); |
3706 } | 3710 } |
3707 | 3711 |
3708 ResolutionResult visitAwait(Await node) { | 3712 ResolutionResult visitAwait(Await node) { |
3709 compiler.futureClass.ensureResolved(resolution); | 3713 coreClasses.futureClass.ensureResolved(resolution); |
3710 visit(node.expression); | 3714 visit(node.expression); |
3711 return const NoneResult(); | 3715 return const NoneResult(); |
3712 } | 3716 } |
3713 | 3717 |
3714 ResolutionResult visitVariableDefinitions(VariableDefinitions node) { | 3718 ResolutionResult visitVariableDefinitions(VariableDefinitions node) { |
3715 DartType type; | 3719 DartType type; |
3716 if (node.type != null) { | 3720 if (node.type != null) { |
3717 type = resolveTypeAnnotation(node.type); | 3721 type = resolveTypeAnnotation(node.type); |
3718 } else { | 3722 } else { |
3719 type = const DynamicType(); | 3723 type = const DynamicType(); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3850 String nameString = stringConstant.toDartString().slowToString(); | 3854 String nameString = stringConstant.toDartString().slowToString(); |
3851 if (validateSymbol(argumentNode, nameString)) { | 3855 if (validateSymbol(argumentNode, nameString)) { |
3852 registry.registerConstSymbol(nameString); | 3856 registry.registerConstSymbol(nameString); |
3853 } | 3857 } |
3854 } | 3858 } |
3855 } else { | 3859 } else { |
3856 if (!compiler.mirrorUsageAnalyzerTask.hasMirrorUsage( | 3860 if (!compiler.mirrorUsageAnalyzerTask.hasMirrorUsage( |
3857 enclosingElement)) { | 3861 enclosingElement)) { |
3858 reporter.reportHintMessage( | 3862 reporter.reportHintMessage( |
3859 node.newToken, MessageKind.NON_CONST_BLOAT, | 3863 node.newToken, MessageKind.NON_CONST_BLOAT, |
3860 {'name': compiler.symbolClass.name}); | 3864 {'name': coreClasses.symbolClass.name}); |
3861 } | 3865 } |
3862 } | 3866 } |
3863 } else if (isMirrorsUsedConstant) { | 3867 } else if (isMirrorsUsedConstant) { |
3864 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping); | 3868 compiler.mirrorUsageAnalyzerTask.validate(node, registry.mapping); |
3865 } | 3869 } |
3866 if (node.isConst) { | 3870 if (node.isConst) { |
3867 analyzeConstantDeferred(node); | 3871 analyzeConstantDeferred(node); |
3868 | 3872 |
3869 // TODO(johnniwinther): Compute this in the [ConstructorResolver]. | 3873 // TODO(johnniwinther): Compute this in the [ConstructorResolver]. |
3870 // Check that the constructor is not deferred. | 3874 // Check that the constructor is not deferred. |
(...skipping 27 matching lines...) Expand all Loading... |
3898 return const NoneResult(); | 3902 return const NoneResult(); |
3899 } | 3903 } |
3900 | 3904 |
3901 void checkConstMapKeysDontOverrideEquals(Spannable spannable, | 3905 void checkConstMapKeysDontOverrideEquals(Spannable spannable, |
3902 MapConstantValue map) { | 3906 MapConstantValue map) { |
3903 for (ConstantValue key in map.keys) { | 3907 for (ConstantValue key in map.keys) { |
3904 if (!key.isObject) continue; | 3908 if (!key.isObject) continue; |
3905 ObjectConstantValue objectConstant = key; | 3909 ObjectConstantValue objectConstant = key; |
3906 DartType keyType = objectConstant.type; | 3910 DartType keyType = objectConstant.type; |
3907 ClassElement cls = keyType.element; | 3911 ClassElement cls = keyType.element; |
3908 if (cls == compiler.stringClass) continue; | 3912 if (cls == coreClasses.stringClass) continue; |
3909 Element equals = cls.lookupMember('=='); | 3913 Element equals = cls.lookupMember('=='); |
3910 if (equals.enclosingClass != compiler.objectClass) { | 3914 if (equals.enclosingClass != coreClasses.objectClass) { |
3911 reporter.reportErrorMessage( | 3915 reporter.reportErrorMessage( |
3912 spannable, | 3916 spannable, |
3913 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, | 3917 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, |
3914 {'type': keyType}); | 3918 {'type': keyType}); |
3915 } | 3919 } |
3916 } | 3920 } |
3917 } | 3921 } |
3918 | 3922 |
3919 void analyzeConstant(Node node, {enforceConst: true}) { | 3923 void analyzeConstant(Node node, {enforceConst: true}) { |
3920 ConstantExpression constant = | 3924 ConstantExpression constant = |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4383 ResolutionResult visitLiteralMapEntry(LiteralMapEntry node) { | 4387 ResolutionResult visitLiteralMapEntry(LiteralMapEntry node) { |
4384 node.visitChildren(this); | 4388 node.visitChildren(this); |
4385 return const NoneResult(); | 4389 return const NoneResult(); |
4386 } | 4390 } |
4387 | 4391 |
4388 ResolutionResult visitNamedArgument(NamedArgument node) { | 4392 ResolutionResult visitNamedArgument(NamedArgument node) { |
4389 return visit(node.expression); | 4393 return visit(node.expression); |
4390 } | 4394 } |
4391 | 4395 |
4392 DartType typeOfConstant(ConstantValue constant) { | 4396 DartType typeOfConstant(ConstantValue constant) { |
4393 if (constant.isInt) return compiler.intClass.rawType; | 4397 if (constant.isInt) return coreTypes.intType; |
4394 if (constant.isBool) return compiler.boolClass.rawType; | 4398 if (constant.isBool) return coreTypes.boolType; |
4395 if (constant.isDouble) return compiler.doubleClass.rawType; | 4399 if (constant.isDouble) return coreTypes.doubleType; |
4396 if (constant.isString) return compiler.stringClass.rawType; | 4400 if (constant.isString) return coreTypes.stringType; |
4397 if (constant.isNull) return compiler.nullClass.rawType; | 4401 if (constant.isNull) return coreTypes.nullType; |
4398 if (constant.isFunction) return compiler.functionClass.rawType; | 4402 if (constant.isFunction) return coreTypes.functionType; |
4399 assert(constant.isObject); | 4403 assert(constant.isObject); |
4400 ObjectConstantValue objectConstant = constant; | 4404 ObjectConstantValue objectConstant = constant; |
4401 return objectConstant.type; | 4405 return objectConstant.type; |
4402 } | 4406 } |
4403 | 4407 |
4404 bool overridesEquals(DartType type) { | 4408 bool overridesEquals(DartType type) { |
4405 ClassElement cls = type.element; | 4409 ClassElement cls = type.element; |
4406 Element equals = cls.lookupMember('=='); | 4410 Element equals = cls.lookupMember('=='); |
4407 return equals.enclosingClass != compiler.objectClass; | 4411 return equals.enclosingClass != coreClasses.objectClass; |
4408 } | 4412 } |
4409 | 4413 |
4410 void checkCaseExpressions(SwitchStatement node) { | 4414 void checkCaseExpressions(SwitchStatement node) { |
4411 CaseMatch firstCase = null; | 4415 CaseMatch firstCase = null; |
4412 DartType firstCaseType = null; | 4416 DartType firstCaseType = null; |
4413 DiagnosticMessage error; | 4417 DiagnosticMessage error; |
4414 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 4418 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
4415 | 4419 |
4416 for (Link<Node> cases = node.cases.nodes; | 4420 for (Link<Node> cases = node.cases.nodes; |
4417 !cases.isEmpty; | 4421 !cases.isEmpty; |
4418 cases = cases.tail) { | 4422 cases = cases.tail) { |
4419 SwitchCase switchCase = cases.head; | 4423 SwitchCase switchCase = cases.head; |
4420 | 4424 |
4421 for (Node labelOrCase in switchCase.labelsAndCases) { | 4425 for (Node labelOrCase in switchCase.labelsAndCases) { |
4422 CaseMatch caseMatch = labelOrCase.asCaseMatch(); | 4426 CaseMatch caseMatch = labelOrCase.asCaseMatch(); |
4423 if (caseMatch == null) continue; | 4427 if (caseMatch == null) continue; |
4424 | 4428 |
4425 // Analyze the constant. | 4429 // Analyze the constant. |
4426 ConstantExpression constant = | 4430 ConstantExpression constant = |
4427 registry.getConstant(caseMatch.expression); | 4431 registry.getConstant(caseMatch.expression); |
4428 assert(invariant(node, constant != null, | 4432 assert(invariant(node, constant != null, |
4429 message: 'No constant computed for $node')); | 4433 message: 'No constant computed for $node')); |
4430 | 4434 |
4431 ConstantValue value = compiler.constants.getConstantValue(constant); | 4435 ConstantValue value = compiler.constants.getConstantValue(constant); |
4432 DartType caseType = typeOfConstant(value); | 4436 DartType caseType = value.getType(coreTypes);//typeOfConstant(value); |
4433 | 4437 |
4434 if (firstCaseType == null) { | 4438 if (firstCaseType == null) { |
4435 firstCase = caseMatch; | 4439 firstCase = caseMatch; |
4436 firstCaseType = caseType; | 4440 firstCaseType = caseType; |
4437 | 4441 |
4438 // We only report the bad type on the first class element. All others | 4442 // We only report the bad type on the first class element. All others |
4439 // get a "type differs" error. | 4443 // get a "type differs" error. |
4440 if (caseType.element == compiler.doubleClass) { | 4444 if (caseType == coreTypes.doubleType) { |
4441 reporter.reportErrorMessage( | 4445 reporter.reportErrorMessage( |
4442 node, | 4446 node, |
4443 MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS, | 4447 MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS, |
4444 {'type': "double"}); | 4448 {'type': "double"}); |
4445 } else if (caseType.element == compiler.functionClass) { | 4449 } else if (caseType == coreTypes.functionType) { |
4446 reporter.reportErrorMessage( | 4450 reporter.reportErrorMessage( |
4447 node, MessageKind.SWITCH_CASE_FORBIDDEN, | 4451 node, MessageKind.SWITCH_CASE_FORBIDDEN, |
4448 {'type': "Function"}); | 4452 {'type': "Function"}); |
4449 } else if (value.isObject && overridesEquals(caseType)) { | 4453 } else if (value.isObject && overridesEquals(caseType)) { |
4450 reporter.reportErrorMessage( | 4454 reporter.reportErrorMessage( |
4451 firstCase.expression, | 4455 firstCase.expression, |
4452 MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS, | 4456 MessageKind.SWITCH_CASE_VALUE_OVERRIDES_EQUALS, |
4453 {'type': caseType}); | 4457 {'type': caseType}); |
4454 } | 4458 } |
4455 } else { | 4459 } else { |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4668 } | 4672 } |
4669 return const NoneResult(); | 4673 return const NoneResult(); |
4670 } | 4674 } |
4671 } | 4675 } |
4672 | 4676 |
4673 /// Looks up [name] in [scope] and unwraps the result. | 4677 /// Looks up [name] in [scope] and unwraps the result. |
4674 Element lookupInScope(DiagnosticReporter reporter, Node node, | 4678 Element lookupInScope(DiagnosticReporter reporter, Node node, |
4675 Scope scope, String name) { | 4679 Scope scope, String name) { |
4676 return Elements.unwrap(scope.lookup(name), reporter, node); | 4680 return Elements.unwrap(scope.lookup(name), reporter, node); |
4677 } | 4681 } |
OLD | NEW |