| 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 |