| 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 import 'dart:collection'; | 6 import 'dart:collection'; |
| 7 | 7 |
| 8 import 'package:async_helper/async_helper.dart'; | 8 import 'package:async_helper/async_helper.dart'; |
| 9 import 'package:expect/expect.dart'; | 9 import 'package:expect/expect.dart'; |
| 10 import 'package:compiler/src/constants/expressions.dart'; | 10 import 'package:compiler/src/constants/expressions.dart'; |
| 11 import 'package:compiler/src/dart_types.dart'; | 11 import 'package:compiler/src/dart_types.dart'; |
| 12 import 'package:compiler/src/elements/modelx.dart'; | 12 import 'package:compiler/src/elements/modelx.dart'; |
| 13 import 'package:compiler/src/resolution/constructors.dart'; | 13 import 'package:compiler/src/resolution/constructors.dart'; |
| 14 import 'package:compiler/src/resolution/members.dart'; | 14 import 'package:compiler/src/resolution/members.dart'; |
| 15 import 'package:compiler/src/resolution/registry.dart'; | 15 import 'package:compiler/src/resolution/registry.dart'; |
| 16 import 'package:compiler/src/resolution/resolution_result.dart'; | 16 import 'package:compiler/src/resolution/resolution_result.dart'; |
| 17 import 'package:compiler/src/resolution/scope.dart'; | 17 import 'package:compiler/src/resolution/scope.dart'; |
| 18 import 'package:compiler/src/resolution/tree_elements.dart'; | 18 import 'package:compiler/src/resolution/tree_elements.dart'; |
| 19 | 19 |
| 20 import 'compiler_helper.dart'; | 20 import 'compiler_helper.dart'; |
| 21 import 'link_helper.dart'; | 21 import 'link_helper.dart'; |
| 22 import 'parser_helper.dart'; | 22 import 'parser_helper.dart'; |
| 23 | 23 |
| 24 Node buildIdentifier(String name) => new Identifier(scan(name)); | 24 Node buildIdentifier(String name) => new Identifier(scan(name)); |
| 25 | 25 |
| 26 Node buildInitialization(String name) => | 26 Node buildInitialization(String name) => parseBodyCode('$name = 1', |
| 27 parseBodyCode('$name = 1', | 27 (parser, tokens) => parser.parseOptionallyInitializedIdentifier(tokens)); |
| 28 (parser, tokens) => parser.parseOptionallyInitializedIdentifier(tokens)); | |
| 29 | 28 |
| 30 createLocals(List variables) { | 29 createLocals(List variables) { |
| 31 var locals = <Node>[]; | 30 var locals = <Node>[]; |
| 32 for (final variable in variables) { | 31 for (final variable in variables) { |
| 33 String name = variable[0]; | 32 String name = variable[0]; |
| 34 bool init = variable[1]; | 33 bool init = variable[1]; |
| 35 if (init) { | 34 if (init) { |
| 36 locals.add(buildInitialization(name)); | 35 locals.add(buildInitialization(name)); |
| 37 } else { | 36 } else { |
| 38 locals.add(buildIdentifier(name)); | 37 locals.add(buildIdentifier(name)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 57 final VariableElement variableElement = result.element; | 56 final VariableElement variableElement = result.element; |
| 58 MethodScope scope = visitor.scope; | 57 MethodScope scope = visitor.scope; |
| 59 Expect.equals(variableElement, scope.elements[name]); | 58 Expect.equals(variableElement, scope.elements[name]); |
| 60 } | 59 } |
| 61 return compiler; | 60 return compiler; |
| 62 }); | 61 }); |
| 63 } | 62 } |
| 64 | 63 |
| 65 main() { | 64 main() { |
| 66 asyncTest(() => Future.forEach([ | 65 asyncTest(() => Future.forEach([ |
| 67 testLocalsOne, | 66 testLocalsOne, |
| 68 testLocalsTwo, | 67 testLocalsTwo, |
| 69 testLocalsThree, | 68 testLocalsThree, |
| 70 testLocalsFour, | 69 testLocalsFour, |
| 71 testLocalsFive, | 70 testLocalsFive, |
| 72 testParametersOne, | 71 testParametersOne, |
| 73 testFor, | 72 testFor, |
| 74 testTypeAnnotation, | 73 testTypeAnnotation, |
| 75 testSuperclass, | 74 testSuperclass, |
| 76 // testVarSuperclass, // The parser crashes with 'class Foo extends var'. | 75 // testVarSuperclass, // The parser crashes with 'class Foo extends var'
. |
| 77 // testOneInterface, // Generates unexpected error message. | 76 // testOneInterface, // Generates unexpected error message. |
| 78 // testTwoInterfaces, // Generates unexpected error message. | 77 // testTwoInterfaces, // Generates unexpected error message. |
| 79 testFunctionExpression, | 78 testFunctionExpression, |
| 80 testNewExpression, | 79 testNewExpression, |
| 81 testTopLevelFields, | 80 testTopLevelFields, |
| 82 testClassHierarchy, | 81 testClassHierarchy, |
| 83 testEnumDeclaration, | 82 testEnumDeclaration, |
| 84 testInitializers, | 83 testInitializers, |
| 85 testThis, | 84 testThis, |
| 86 testSuperCalls, | 85 testSuperCalls, |
| 87 testSwitch, | 86 testSwitch, |
| 88 testTypeVariables, | 87 testTypeVariables, |
| 89 testToString, | 88 testToString, |
| 90 testIndexedOperator, | 89 testIndexedOperator, |
| 91 testIncrementsAndDecrements, | 90 testIncrementsAndDecrements, |
| 92 testOverrideHashCodeCheck, | 91 testOverrideHashCodeCheck, |
| 93 testSupertypeOrder, | 92 testSupertypeOrder, |
| 94 testConstConstructorAndNonFinalFields, | 93 testConstConstructorAndNonFinalFields, |
| 95 testCantAssignMethods, | 94 testCantAssignMethods, |
| 96 testCantAssignFinalAndConsts, | 95 testCantAssignFinalAndConsts, |
| 97 testAwaitHint, | 96 testAwaitHint, |
| 98 testConstantExpressions, | 97 testConstantExpressions, |
| 99 ], (f) => f())); | 98 ], (f) => f())); |
| 100 } | 99 } |
| 101 | 100 |
| 102 Future testSupertypeOrder() { | 101 Future testSupertypeOrder() { |
| 103 return Future.wait([ | 102 return Future.wait([ |
| 104 MockCompiler.create((MockCompiler compiler) { | 103 MockCompiler.create((MockCompiler compiler) { |
| 105 compiler.parseScript(""" | 104 compiler.parseScript(""" |
| 106 class I1 {} | 105 class I1 {} |
| 107 class I2 {} | 106 class I2 {} |
| 108 class J1 extends K1 {} | 107 class J1 extends K1 {} |
| 109 class J2 implements K2 {} | 108 class J2 implements K2 {} |
| 110 class K1 {} | 109 class K1 {} |
| 111 class K2 {} | 110 class K2 {} |
| 112 class L1 {} | 111 class L1 {} |
| 113 class A implements I1, I2 {} | 112 class A implements I1, I2 {} |
| 114 class B extends A implements J1, J2 {} | 113 class B extends A implements J1, J2 {} |
| 115 class C extends B implements L1 {} | 114 class C extends B implements L1 {} |
| 116 """); | 115 """); |
| 117 compiler.resolveStatement("C c;"); | 116 compiler.resolveStatement("C c;"); |
| 118 ClassElement classA = compiler.mainApp.find("A"); | 117 ClassElement classA = compiler.mainApp.find("A"); |
| 119 ClassElement classB = compiler.mainApp.find("B"); | 118 ClassElement classB = compiler.mainApp.find("B"); |
| 120 ClassElement classC = compiler.mainApp.find("C"); | 119 ClassElement classC = compiler.mainApp.find("C"); |
| 121 Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString()); | 120 Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString()); |
| 122 Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]', | 121 Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]', |
| 123 classB.allSupertypes.toString()); | 122 classB.allSupertypes.toString()); |
| 124 Expect.equals('[ B, L1, A, J2, J1, I2, I1, K2, K1, Object ]', | 123 Expect.equals('[ B, L1, A, J2, J1, I2, I1, K2, K1, Object ]', |
| 125 classC.allSupertypes.toString()); | 124 classC.allSupertypes.toString()); |
| 126 }), | 125 }), |
| 127 MockCompiler.create((MockCompiler compiler) { | 126 MockCompiler.create((MockCompiler compiler) { |
| 128 compiler.parseScript(""" | 127 compiler.parseScript(""" |
| 129 class X<T> {} | 128 class X<T> {} |
| 130 class Foo extends X<Foo> {} | 129 class Foo extends X<Foo> {} |
| 131 class Bar extends Foo implements X<Bar> {} | 130 class Bar extends Foo implements X<Bar> {} |
| 132 """); | 131 """); |
| 133 compiler.resolveStatement("Bar bar;"); | 132 compiler.resolveStatement("Bar bar;"); |
| 134 ClassElement classBar = compiler.mainApp.find("Bar"); | 133 ClassElement classBar = compiler.mainApp.find("Bar"); |
| 135 DiagnosticCollector collector = compiler.diagnosticCollector; | 134 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 136 Expect.equals(0, collector.warnings.length); | 135 Expect.equals(0, collector.warnings.length); |
| 137 Expect.equals(1, collector.errors.length); | 136 Expect.equals(1, collector.errors.length); |
| 138 Expect.equals(MessageKind.MULTI_INHERITANCE, | 137 Expect.equals( |
| 139 collector.errors.first.message.kind); | 138 MessageKind.MULTI_INHERITANCE, collector.errors.first.message.kind); |
| 140 Expect.equals(0, collector.crashes.length); | 139 Expect.equals(0, collector.crashes.length); |
| 141 }), | 140 }), |
| 142 ]); | 141 ]); |
| 143 } | 142 } |
| 144 | 143 |
| 145 Future testTypeVariables() { | 144 Future testTypeVariables() { |
| 146 matchResolvedTypes(visitor, text, name, expectedElements) { | 145 matchResolvedTypes(visitor, text, name, expectedElements) { |
| 147 VariableDefinitions definition = parseStatement(text); | 146 VariableDefinitions definition = parseStatement(text); |
| 148 visitor.visit(definition.type); | 147 visitor.visit(definition.type); |
| 149 InterfaceType type = visitor.registry.mapping.getType(definition.type); | 148 InterfaceType type = visitor.registry.mapping.getType(definition.type); |
| 150 Expect.equals(definition.type.typeArguments.slowLength(), | 149 Expect.equals( |
| 151 type.typeArguments.length); | 150 definition.type.typeArguments.slowLength(), type.typeArguments.length); |
| 152 int index = 0; | 151 int index = 0; |
| 153 for (DartType argument in type.typeArguments) { | 152 for (DartType argument in type.typeArguments) { |
| 154 Expect.equals(true, index < expectedElements.length); | 153 Expect.equals(true, index < expectedElements.length); |
| 155 Expect.equals(expectedElements[index], argument.element); | 154 Expect.equals(expectedElements[index], argument.element); |
| 156 index++; | 155 index++; |
| 157 } | 156 } |
| 158 Expect.equals(index, expectedElements.length); | 157 Expect.equals(index, expectedElements.length); |
| 159 } | 158 } |
| 160 | 159 |
| 161 return Future.wait([ | 160 return Future.wait([ |
| 162 MockCompiler.create((MockCompiler compiler) { | 161 MockCompiler.create((MockCompiler compiler) { |
| 163 ResolverVisitor visitor = compiler.resolverVisitor(); | 162 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 164 compiler.parseScript('class Foo<T, U> {}'); | 163 compiler.parseScript('class Foo<T, U> {}'); |
| 165 ClassElement foo = compiler.mainApp.find('Foo'); | 164 ClassElement foo = compiler.mainApp.find('Foo'); |
| 166 matchResolvedTypes(visitor, 'Foo<int, String> x;', 'Foo', | 165 matchResolvedTypes(visitor, 'Foo<int, String> x;', 'Foo', |
| 167 [compiler.coreClasses.intClass, | 166 [compiler.coreClasses.intClass, compiler.coreClasses.stringClass]); |
| 168 compiler.coreClasses.stringClass]); | 167 matchResolvedTypes(visitor, 'Foo<Foo, Foo> x;', 'Foo', [foo, foo]); |
| 169 matchResolvedTypes(visitor, 'Foo<Foo, Foo> x;', 'Foo', | |
| 170 [foo, foo]); | |
| 171 }), | 168 }), |
| 172 | |
| 173 MockCompiler.create((MockCompiler compiler) { | 169 MockCompiler.create((MockCompiler compiler) { |
| 174 compiler.parseScript('class Foo<T, U> {}'); | 170 compiler.parseScript('class Foo<T, U> {}'); |
| 175 compiler.resolveStatement('Foo<notype, int> x;'); | 171 compiler.resolveStatement('Foo<notype, int> x;'); |
| 176 DiagnosticCollector collector = compiler.diagnosticCollector; | 172 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 177 Expect.equals(1, collector.warnings.length); | 173 Expect.equals(1, collector.warnings.length); |
| 178 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, | 174 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, |
| 179 collector.warnings.first.message.kind); | 175 collector.warnings.first.message.kind); |
| 180 Expect.equals(0, collector.errors.length); | 176 Expect.equals(0, collector.errors.length); |
| 181 }), | 177 }), |
| 182 | |
| 183 MockCompiler.create((MockCompiler compiler) { | 178 MockCompiler.create((MockCompiler compiler) { |
| 184 compiler.parseScript('class Foo<T, U> {}'); | 179 compiler.parseScript('class Foo<T, U> {}'); |
| 185 compiler.resolveStatement('var x = new Foo<notype, int>();'); | 180 compiler.resolveStatement('var x = new Foo<notype, int>();'); |
| 186 DiagnosticCollector collector = compiler.diagnosticCollector; | 181 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 187 Expect.equals(1, collector.warnings.length); | 182 Expect.equals(1, collector.warnings.length); |
| 188 Expect.equals(0, collector.errors.length); | 183 Expect.equals(0, collector.errors.length); |
| 189 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, | 184 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, |
| 190 collector.warnings.first.message.kind); | 185 collector.warnings.first.message.kind); |
| 191 }), | 186 }), |
| 192 | |
| 193 MockCompiler.create((MockCompiler compiler) { | 187 MockCompiler.create((MockCompiler compiler) { |
| 194 compiler.parseScript('class Foo<T> {' | 188 compiler.parseScript('class Foo<T> {' |
| 195 ' Foo<T> t;' | 189 ' Foo<T> t;' |
| 196 ' foo(Foo<T> f) {}' | 190 ' foo(Foo<T> f) {}' |
| 197 ' bar() { g(Foo<T> f) {}; g(); }' | 191 ' bar() { g(Foo<T> f) {}; g(); }' |
| 198 '}'); | 192 '}'); |
| 199 ClassElement foo = compiler.mainApp.find('Foo'); | 193 ClassElement foo = compiler.mainApp.find('Foo'); |
| 200 foo.ensureResolved(compiler.resolution); | 194 foo.ensureResolved(compiler.resolution); |
| 201 MemberElement tMember = foo.lookupLocalMember('t'); | 195 MemberElement tMember = foo.lookupLocalMember('t'); |
| 202 tMember.computeType(compiler.resolution); | 196 tMember.computeType(compiler.resolution); |
| 203 MemberElement fooMember = foo.lookupLocalMember('foo'); | 197 MemberElement fooMember = foo.lookupLocalMember('foo'); |
| 204 fooMember.computeType(compiler.resolution); | 198 fooMember.computeType(compiler.resolution); |
| 205 compiler.resolver.resolve(foo.lookupLocalMember('bar')); | 199 compiler.resolver.resolve(foo.lookupLocalMember('bar')); |
| 206 DiagnosticCollector collector = compiler.diagnosticCollector; | 200 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 207 Expect.equals(0, collector.warnings.length); | 201 Expect.equals(0, collector.warnings.length); |
| 208 Expect.equals(0, collector.errors.length); | 202 Expect.equals(0, collector.errors.length); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 219 | 213 |
| 220 ClassElement classB = compiler.mainApp.find("B"); | 214 ClassElement classB = compiler.mainApp.find("B"); |
| 221 FunctionElement fooB = classB.lookupLocalMember("foo"); | 215 FunctionElement fooB = classB.lookupLocalMember("foo"); |
| 222 ClassElement classA = compiler.mainApp.find("A"); | 216 ClassElement classA = compiler.mainApp.find("A"); |
| 223 FunctionElement fooA = classA.lookupLocalMember("foo"); | 217 FunctionElement fooA = classA.lookupLocalMember("foo"); |
| 224 | 218 |
| 225 ResolverVisitor visitor = new ResolverVisitor( | 219 ResolverVisitor visitor = new ResolverVisitor( |
| 226 compiler.resolution, | 220 compiler.resolution, |
| 227 fooB, | 221 fooB, |
| 228 new ResolutionRegistry( | 222 new ResolutionRegistry( |
| 229 compiler.backend, | 223 compiler.backend, new CollectingTreeElements(fooB)), |
| 230 new CollectingTreeElements(fooB)), | |
| 231 scope: new MockTypeVariablesScope(classB.buildScope())); | 224 scope: new MockTypeVariablesScope(classB.buildScope())); |
| 232 FunctionExpression node = | 225 FunctionExpression node = |
| 233 (fooB as FunctionElementX).parseNode(compiler.parsingContext); | 226 (fooB as FunctionElementX).parseNode(compiler.parsingContext); |
| 234 visitor.visit(node.body); | 227 visitor.visit(node.body); |
| 235 Map mapping = map(visitor); | 228 Map mapping = map(visitor); |
| 236 | 229 |
| 237 Send superCall = node.body.asReturn().expression; | 230 Send superCall = node.body.asReturn().expression; |
| 238 FunctionElement called = mapping[superCall]; | 231 FunctionElement called = mapping[superCall]; |
| 239 Expect.isNotNull(called); | 232 Expect.isNotNull(called); |
| 240 Expect.equals(fooA, called); | 233 Expect.equals(fooA, called); |
| 241 }); | 234 }); |
| 242 } | 235 } |
| 243 | 236 |
| 244 Future testSwitch() { | 237 Future testSwitch() { |
| 245 return MockCompiler.create((MockCompiler compiler) { | 238 return MockCompiler.create((MockCompiler compiler) { |
| 246 compiler.parseScript("class Foo { foo() {" | 239 compiler.parseScript("class Foo { foo() {" |
| 247 "switch (null) { case '': break; case 2: break; } } }"); | 240 "switch (null) { case '': break; case 2: break; } } }"); |
| 248 compiler.resolveStatement("Foo foo;"); | 241 compiler.resolveStatement("Foo foo;"); |
| 249 ClassElement fooElement = compiler.mainApp.find("Foo"); | 242 ClassElement fooElement = compiler.mainApp.find("Foo"); |
| 250 FunctionElement funElement = fooElement.lookupLocalMember("foo"); | 243 FunctionElement funElement = fooElement.lookupLocalMember("foo"); |
| 251 compiler.processQueue(compiler.enqueuer.resolution, funElement); | 244 compiler.processQueue(compiler.enqueuer.resolution, funElement); |
| 252 DiagnosticCollector collector = compiler.diagnosticCollector; | 245 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 253 Expect.equals(0, collector.warnings.length); | 246 Expect.equals(0, collector.warnings.length); |
| 254 Expect.equals(1, collector.errors.length); | 247 Expect.equals(1, collector.errors.length); |
| 255 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL, | 248 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL, |
| 256 collector.errors.first.message.kind); | 249 collector.errors.first.message.kind); |
| 257 Expect.equals(2, collector.infos.length); | 250 Expect.equals(2, collector.infos.length); |
| 258 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, | 251 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, |
| 259 collector.infos.first.message.kind); | 252 collector.infos.first.message.kind); |
| 260 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, | 253 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, |
| 261 collector.infos.elementAt(1).message.kind); | 254 collector.infos.elementAt(1).message.kind); |
| 262 }); | 255 }); |
| 263 } | 256 } |
| 264 | 257 |
| 265 Future testThis() { | 258 Future testThis() { |
| 266 return Future.wait([ | 259 return Future.wait([ |
| 267 MockCompiler.create((MockCompiler compiler) { | 260 MockCompiler.create((MockCompiler compiler) { |
| 268 compiler.parseScript("class Foo { foo() { return this; } }"); | 261 compiler.parseScript("class Foo { foo() { return this; } }"); |
| 269 compiler.resolveStatement("Foo foo;"); | 262 compiler.resolveStatement("Foo foo;"); |
| 270 ClassElement fooElement = compiler.mainApp.find("Foo"); | 263 ClassElement fooElement = compiler.mainApp.find("Foo"); |
| 271 FunctionElement funElement = fooElement.lookupLocalMember("foo"); | 264 FunctionElement funElement = fooElement.lookupLocalMember("foo"); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 283 DiagnosticCollector collector = compiler.diagnosticCollector; | 276 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 284 Expect.equals(0, mapping.length); | 277 Expect.equals(0, mapping.length); |
| 285 Expect.equals(0, collector.warnings.length); | 278 Expect.equals(0, collector.warnings.length); |
| 286 }), | 279 }), |
| 287 MockCompiler.create((MockCompiler compiler) { | 280 MockCompiler.create((MockCompiler compiler) { |
| 288 compiler.resolveStatement("main() { return this; }"); | 281 compiler.resolveStatement("main() { return this; }"); |
| 289 DiagnosticCollector collector = compiler.diagnosticCollector; | 282 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 290 Expect.equals(0, collector.warnings.length); | 283 Expect.equals(0, collector.warnings.length); |
| 291 Expect.equals(1, collector.errors.length); | 284 Expect.equals(1, collector.errors.length); |
| 292 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, | 285 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, |
| 293 collector.errors.first.message.kind); | 286 collector.errors.first.message.kind); |
| 294 }), | 287 }), |
| 295 MockCompiler.create((MockCompiler compiler) { | 288 MockCompiler.create((MockCompiler compiler) { |
| 296 compiler.parseScript("class Foo { static foo() { return this; } }"); | 289 compiler.parseScript("class Foo { static foo() { return this; } }"); |
| 297 compiler.resolveStatement("Foo foo;"); | 290 compiler.resolveStatement("Foo foo;"); |
| 298 ClassElement fooElement = compiler.mainApp.find("Foo"); | 291 ClassElement fooElement = compiler.mainApp.find("Foo"); |
| 299 FunctionElement funElement = fooElement.lookupLocalMember("foo"); | 292 FunctionElement funElement = fooElement.lookupLocalMember("foo"); |
| 300 ResolverVisitor visitor = new ResolverVisitor( | 293 ResolverVisitor visitor = new ResolverVisitor( |
| 301 compiler.resolution, | 294 compiler.resolution, |
| 302 funElement, | 295 funElement, |
| 303 new ResolutionRegistry( | 296 new ResolutionRegistry( |
| 304 compiler.backend, new CollectingTreeElements(funElement)), | 297 compiler.backend, new CollectingTreeElements(funElement)), |
| 305 scope: new MockTypeVariablesScope(fooElement.buildScope())); | 298 scope: new MockTypeVariablesScope(fooElement.buildScope())); |
| 306 FunctionExpression function = | 299 FunctionExpression function = |
| 307 (funElement as FunctionElementX).parseNode(compiler.parsingContext); | 300 (funElement as FunctionElementX).parseNode(compiler.parsingContext); |
| 308 visitor.visit(function.body); | 301 visitor.visit(function.body); |
| 309 DiagnosticCollector collector = compiler.diagnosticCollector; | 302 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 310 Expect.equals(0, collector.warnings.length); | 303 Expect.equals(0, collector.warnings.length); |
| 311 Expect.equals(1, collector.errors.length); | 304 Expect.equals(1, collector.errors.length); |
| 312 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, | 305 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, |
| 313 collector.errors.first.message.kind); | 306 collector.errors.first.message.kind); |
| 314 }), | 307 }), |
| 315 ]); | 308 ]); |
| 316 } | 309 } |
| 317 | 310 |
| 318 Future testLocalsOne() { | 311 Future testLocalsOne() { |
| 319 return Future.forEach([ | 312 return Future.forEach([ |
| 320 () => testLocals([["foo", false]]), | 313 () => testLocals([ |
| 321 () => testLocals([["foo", false], ["bar", false]]), | 314 ["foo", false] |
| 322 () => testLocals([["foo", false], ["bar", false], ["foobar", false]]), | 315 ]), |
| 323 | 316 () => testLocals([ |
| 324 () => testLocals([["foo", true]]), | 317 ["foo", false], |
| 325 () => testLocals([["foo", false], ["bar", true]]), | 318 ["bar", false] |
| 326 () => testLocals([["foo", true], ["bar", true]]), | 319 ]), |
| 327 | 320 () => testLocals([ |
| 328 () => testLocals([["foo", false], ["bar", false], ["foobar", true]]), | 321 ["foo", false], |
| 329 () => testLocals([["foo", false], ["bar", true], ["foobar", true]]), | 322 ["bar", false], |
| 330 () => testLocals([["foo", true], ["bar", true], ["foobar", true]]), | 323 ["foobar", false] |
| 331 | 324 ]), |
| 332 () => testLocals([["foo", false], ["foo", false]]) | 325 () => testLocals([ |
| 333 .then((MockCompiler compiler) { | 326 ["foo", true] |
| 334 DiagnosticCollector collector = compiler.diagnosticCollector; | 327 ]), |
| 335 Expect.equals(1, collector.errors.length); | 328 () => testLocals([ |
| 336 Expect.equals( | 329 ["foo", false], |
| 337 new Message( | 330 ["bar", true] |
| 338 MessageTemplate.TEMPLATES[MessageKind.DUPLICATE_DEFINITION], | 331 ]), |
| 339 {'name': 'foo'}, false), | 332 () => testLocals([ |
| 340 collector.errors.first.message); | 333 ["foo", true], |
| 341 })], (f) => f()); | 334 ["bar", true] |
| 335 ]), |
| 336 () => testLocals([ |
| 337 ["foo", false], |
| 338 ["bar", false], |
| 339 ["foobar", true] |
| 340 ]), |
| 341 () => testLocals([ |
| 342 ["foo", false], |
| 343 ["bar", true], |
| 344 ["foobar", true] |
| 345 ]), |
| 346 () => testLocals([ |
| 347 ["foo", true], |
| 348 ["bar", true], |
| 349 ["foobar", true] |
| 350 ]), |
| 351 () => testLocals([ |
| 352 ["foo", false], |
| 353 ["foo", false] |
| 354 ]).then((MockCompiler compiler) { |
| 355 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 356 Expect.equals(1, collector.errors.length); |
| 357 Expect.equals( |
| 358 new Message( |
| 359 MessageTemplate.TEMPLATES[MessageKind.DUPLICATE_DEFINITION], |
| 360 {'name': 'foo'}, |
| 361 false), |
| 362 collector.errors.first.message); |
| 363 }) |
| 364 ], (f) => f()); |
| 342 } | 365 } |
| 343 | 366 |
| 344 | |
| 345 Future testLocalsTwo() { | 367 Future testLocalsTwo() { |
| 346 return MockCompiler.create((MockCompiler compiler) { | 368 return MockCompiler.create((MockCompiler compiler) { |
| 347 ResolverVisitor visitor = compiler.resolverVisitor(); | 369 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 348 Node tree = parseStatement("if (true) { var a = 1; var b = 2; }"); | 370 Node tree = parseStatement("if (true) { var a = 1; var b = 2; }"); |
| 349 ResolutionResult result = visitor.visit(tree); | 371 ResolutionResult result = visitor.visit(tree); |
| 350 Expect.equals(const NoneResult(), result); | 372 Expect.equals(const NoneResult(), result); |
| 351 MethodScope scope = visitor.scope; | 373 MethodScope scope = visitor.scope; |
| 352 Expect.equals(0, scope.elements.length); | 374 Expect.equals(0, scope.elements.length); |
| 353 Expect.equals(2, map(visitor).length); | 375 Expect.equals(2, map(visitor).length); |
| 354 | 376 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 ResolutionResult result = visitor.visit(tree); | 415 ResolutionResult result = visitor.visit(tree); |
| 394 Expect.equals(const NoneResult(), result); | 416 Expect.equals(const NoneResult(), result); |
| 395 MethodScope scope = visitor.scope; | 417 MethodScope scope = visitor.scope; |
| 396 Expect.equals(0, scope.elements.length); | 418 Expect.equals(0, scope.elements.length); |
| 397 Expect.equals(4, map(visitor).length); | 419 Expect.equals(4, map(visitor).length); |
| 398 | 420 |
| 399 Block thenPart = tree.thenPart; | 421 Block thenPart = tree.thenPart; |
| 400 List statements1 = thenPart.statements.nodes.toList(); | 422 List statements1 = thenPart.statements.nodes.toList(); |
| 401 Node def1 = statements1[0].definitions.nodes.head; | 423 Node def1 = statements1[0].definitions.nodes.head; |
| 402 Node id1 = statements1[1].expression; | 424 Node id1 = statements1[1].expression; |
| 403 Expect.equals(visitor.registry.mapping[def1], | 425 Expect.equals( |
| 404 visitor.registry.mapping[id1]); | 426 visitor.registry.mapping[def1], visitor.registry.mapping[id1]); |
| 405 | 427 |
| 406 Block elsePart = tree.elsePart; | 428 Block elsePart = tree.elsePart; |
| 407 List statements2 = elsePart.statements.nodes.toList(); | 429 List statements2 = elsePart.statements.nodes.toList(); |
| 408 Node def2 = statements2[0].definitions.nodes.head; | 430 Node def2 = statements2[0].definitions.nodes.head; |
| 409 Node id2 = statements2[1].expression; | 431 Node id2 = statements2[1].expression; |
| 410 Expect.equals(visitor.registry.mapping[def2], | 432 Expect.equals( |
| 411 visitor.registry.mapping[id2]); | 433 visitor.registry.mapping[def2], visitor.registry.mapping[id2]); |
| 412 | 434 |
| 413 Expect.notEquals(visitor.registry.mapping[def1], | 435 Expect.notEquals( |
| 414 visitor.registry.mapping[def2]); | 436 visitor.registry.mapping[def1], visitor.registry.mapping[def2]); |
| 415 Expect.notEquals(visitor.registry.mapping[id1], | 437 Expect.notEquals( |
| 416 visitor.registry.mapping[id2]); | 438 visitor.registry.mapping[id1], visitor.registry.mapping[id2]); |
| 417 }); | 439 }); |
| 418 } | 440 } |
| 419 | 441 |
| 420 Future testParametersOne() { | 442 Future testParametersOne() { |
| 421 return MockCompiler.create((MockCompiler compiler) { | 443 return MockCompiler.create((MockCompiler compiler) { |
| 422 ResolverVisitor visitor = compiler.resolverVisitor(); | 444 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 423 FunctionExpression tree = | 445 FunctionExpression tree = |
| 424 parseFunction("void foo(int a) { return a; }", compiler); | 446 parseFunction("void foo(int a) { return a; }", compiler); |
| 425 visitor.visit(tree); | 447 visitor.visit(tree); |
| 426 | 448 |
| 427 // Check that an element has been created for the parameter. | 449 // Check that an element has been created for the parameter. |
| 428 VariableDefinitions vardef = tree.parameters.nodes.head; | 450 VariableDefinitions vardef = tree.parameters.nodes.head; |
| 429 Node param = vardef.definitions.nodes.head; | 451 Node param = vardef.definitions.nodes.head; |
| 430 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[param].kind); | 452 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[param].kind); |
| 431 | 453 |
| 432 // Check that 'a' in 'return a' is resolved to the parameter. | 454 // Check that 'a' in 'return a' is resolved to the parameter. |
| 433 Block body = tree.body; | 455 Block body = tree.body; |
| 434 Return ret = body.statements.nodes.head; | 456 Return ret = body.statements.nodes.head; |
| 435 Send use = ret.expression; | 457 Send use = ret.expression; |
| 436 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[use].kind); | 458 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[use].kind); |
| 437 Expect.equals(visitor.registry.mapping[param], | 459 Expect.equals( |
| 438 visitor.registry.mapping[use]); | 460 visitor.registry.mapping[param], visitor.registry.mapping[use]); |
| 439 }); | 461 }); |
| 440 } | 462 } |
| 441 | 463 |
| 442 Future testFor() { | 464 Future testFor() { |
| 443 return MockCompiler.create((MockCompiler compiler) { | 465 return MockCompiler.create((MockCompiler compiler) { |
| 444 ResolverVisitor visitor = compiler.resolverVisitor(); | 466 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 445 For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }"); | 467 For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }"); |
| 446 visitor.visit(tree); | 468 visitor.visit(tree); |
| 447 | 469 |
| 448 MethodScope scope = visitor.scope; | 470 MethodScope scope = visitor.scope; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 481 }); | 503 }); |
| 482 } | 504 } |
| 483 | 505 |
| 484 checkIdentifier(Element expected, Node node, Element actual) { | 506 checkIdentifier(Element expected, Node node, Element actual) { |
| 485 Expect.isTrue(node is Identifier, node.toDebugString()); | 507 Expect.isTrue(node is Identifier, node.toDebugString()); |
| 486 Expect.equals(expected, actual); | 508 Expect.equals(expected, actual); |
| 487 } | 509 } |
| 488 | 510 |
| 489 checkSend(Element expected, Node node, Element actual) { | 511 checkSend(Element expected, Node node, Element actual) { |
| 490 Expect.isTrue(node is Send, node.toDebugString()); | 512 Expect.isTrue(node is Send, node.toDebugString()); |
| 491 Expect.isTrue(node is !SendSet, node.toDebugString()); | 513 Expect.isTrue(node is! SendSet, node.toDebugString()); |
| 492 Expect.equals(expected, actual); | 514 Expect.equals(expected, actual); |
| 493 } | 515 } |
| 494 | 516 |
| 495 checkSendSet(Element expected, Node node, Element actual) { | 517 checkSendSet(Element expected, Node node, Element actual) { |
| 496 Expect.isTrue(node is SendSet, node.toDebugString()); | 518 Expect.isTrue(node is SendSet, node.toDebugString()); |
| 497 Expect.equals(expected, actual); | 519 Expect.equals(expected, actual); |
| 498 } | 520 } |
| 499 | 521 |
| 500 Future testTypeAnnotation() { | 522 Future testTypeAnnotation() { |
| 501 return MockCompiler.create((MockCompiler compiler) { | 523 return MockCompiler.create((MockCompiler compiler) { |
| 502 String statement = "Foo bar;"; | 524 String statement = "Foo bar;"; |
| 503 | 525 |
| 504 // Test that we get a warning when Foo is not defined. | 526 // Test that we get a warning when Foo is not defined. |
| 505 Map mapping = compiler.resolveStatement(statement).map; | 527 Map mapping = compiler.resolveStatement(statement).map; |
| 506 | 528 |
| 507 Expect.equals(1, mapping.length); // Only [bar] has an element. | 529 Expect.equals(1, mapping.length); // Only [bar] has an element. |
| 508 DiagnosticCollector collector = compiler.diagnosticCollector; | 530 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 509 Expect.equals(1, collector.warnings.length); | 531 Expect.equals(1, collector.warnings.length); |
| 510 | 532 |
| 511 Expect.equals( | 533 Expect.equals( |
| 512 new Message( | 534 new Message(MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE], |
| 513 MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE], | |
| 514 {'typeName': 'Foo'}, false), | 535 {'typeName': 'Foo'}, false), |
| 515 collector.warnings.first.message); | 536 collector.warnings.first.message); |
| 516 collector.clear(); | 537 collector.clear(); |
| 517 | 538 |
| 518 // Test that there is no warning after defining Foo. | 539 // Test that there is no warning after defining Foo. |
| 519 compiler.parseScript("class Foo {}"); | 540 compiler.parseScript("class Foo {}"); |
| 520 mapping = compiler.resolveStatement(statement).map; | 541 mapping = compiler.resolveStatement(statement).map; |
| 521 Expect.equals(1, mapping.length); | 542 Expect.equals(1, mapping.length); |
| 522 Expect.equals(0, collector.warnings.length); | 543 Expect.equals(0, collector.warnings.length); |
| 523 | 544 |
| 524 // Test that 'var' does not create a warning. | 545 // Test that 'var' does not create a warning. |
| 525 mapping = compiler.resolveStatement("var foo;").map; | 546 mapping = compiler.resolveStatement("var foo;").map; |
| 526 Expect.equals(1, mapping.length); | 547 Expect.equals(1, mapping.length); |
| 527 Expect.equals(0, collector.warnings.length); | 548 Expect.equals(0, collector.warnings.length); |
| 528 }); | 549 }); |
| 529 } | 550 } |
| 530 | 551 |
| 531 Future testSuperclass() { | 552 Future testSuperclass() { |
| 532 return Future.wait([ | 553 return Future.wait([ |
| 533 MockCompiler.create((MockCompiler compiler) { | 554 MockCompiler.create((MockCompiler compiler) { |
| 534 compiler.parseScript("class Foo extends Bar {}"); | 555 compiler.parseScript("class Foo extends Bar {}"); |
| 535 compiler.resolveStatement("Foo bar;"); | 556 compiler.resolveStatement("Foo bar;"); |
| 536 DiagnosticCollector collector = compiler.diagnosticCollector; | 557 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 537 Expect.equals(1, collector.errors.length); | 558 Expect.equals(1, collector.errors.length); |
| 538 var cannotResolveBar = new Message( | 559 var cannotResolveBar = new Message( |
| 539 MessageTemplate.TEMPLATES[MessageKind.CANNOT_EXTEND_MALFORMED], | 560 MessageTemplate.TEMPLATES[MessageKind.CANNOT_EXTEND_MALFORMED], |
| 540 {'className': 'Foo', 'malformedType': 'Bar'}, false); | 561 {'className': 'Foo', 'malformedType': 'Bar'}, |
| 562 false); |
| 541 Expect.equals(cannotResolveBar, collector.errors.first.message); | 563 Expect.equals(cannotResolveBar, collector.errors.first.message); |
| 542 collector.clear(); | 564 collector.clear(); |
| 543 }), | 565 }), |
| 544 MockCompiler.create((MockCompiler compiler) { | 566 MockCompiler.create((MockCompiler compiler) { |
| 545 compiler.parseScript("class Foo extends Bar {}"); | 567 compiler.parseScript("class Foo extends Bar {}"); |
| 546 compiler.parseScript("class Bar {}"); | 568 compiler.parseScript("class Bar {}"); |
| 547 Map mapping = compiler.resolveStatement("Foo bar;").map; | 569 Map mapping = compiler.resolveStatement("Foo bar;").map; |
| 548 Expect.equals(1, mapping.length); | 570 Expect.equals(1, mapping.length); |
| 549 | 571 |
| 550 ClassElement fooElement = compiler.mainApp.find('Foo'); | 572 ClassElement fooElement = compiler.mainApp.find('Foo'); |
| 551 ClassElement barElement = compiler.mainApp.find('Bar'); | 573 ClassElement barElement = compiler.mainApp.find('Bar'); |
| 552 Expect.equals(barElement.computeType(compiler.resolution), | 574 Expect.equals( |
| 553 fooElement.supertype); | 575 barElement.computeType(compiler.resolution), fooElement.supertype); |
| 554 Expect.isTrue(fooElement.interfaces.isEmpty); | 576 Expect.isTrue(fooElement.interfaces.isEmpty); |
| 555 Expect.isTrue(barElement.interfaces.isEmpty); | 577 Expect.isTrue(barElement.interfaces.isEmpty); |
| 556 }), | 578 }), |
| 557 ]); | 579 ]); |
| 558 } | 580 } |
| 559 | 581 |
| 560 Future testVarSuperclass() { | 582 Future testVarSuperclass() { |
| 561 return MockCompiler.create((MockCompiler compiler) { | 583 return MockCompiler.create((MockCompiler compiler) { |
| 562 compiler.parseScript("class Foo extends var {}"); | 584 compiler.parseScript("class Foo extends var {}"); |
| 563 compiler.resolveStatement("Foo bar;"); | 585 compiler.resolveStatement("Foo bar;"); |
| 564 DiagnosticCollector collector = compiler.diagnosticCollector; | 586 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 565 Expect.equals(1, collector.errors.length); | 587 Expect.equals(1, collector.errors.length); |
| 566 Expect.equals( | 588 Expect.equals( |
| 567 new Message( | 589 new Message(MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE], |
| 568 MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE], | |
| 569 {'typeName': 'var'}, false), | 590 {'typeName': 'var'}, false), |
| 570 collector.errors.first.message); | 591 collector.errors.first.message); |
| 571 collector.clear(); | 592 collector.clear(); |
| 572 }); | 593 }); |
| 573 } | 594 } |
| 574 | 595 |
| 575 Future testOneInterface() { | 596 Future testOneInterface() { |
| 576 return MockCompiler.create((MockCompiler compiler) { | 597 return MockCompiler.create((MockCompiler compiler) { |
| 577 compiler.parseScript("class Foo implements Bar {}"); | 598 compiler.parseScript("class Foo implements Bar {}"); |
| 578 compiler.resolveStatement("Foo bar;"); | 599 compiler.resolveStatement("Foo bar;"); |
| 579 DiagnosticCollector collector = compiler.diagnosticCollector; | 600 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 580 Expect.equals(1, collector.errors.length); | 601 Expect.equals(1, collector.errors.length); |
| 581 Expect.equals( | 602 Expect.equals( |
| 582 new Message( | 603 new Message(MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE], |
| 583 MessageTemplate.TEMPLATES[MessageKind.CANNOT_RESOLVE_TYPE], | |
| 584 {'typeName': 'bar'}, false), | 604 {'typeName': 'bar'}, false), |
| 585 collector.errors.first.message); | 605 collector.errors.first.message); |
| 586 collector.clear(); | 606 collector.clear(); |
| 587 | 607 |
| 588 // Add the abstract class to the world and make sure everything is setup | 608 // Add the abstract class to the world and make sure everything is setup |
| 589 // correctly. | 609 // correctly. |
| 590 compiler.parseScript("abstract class Bar {}"); | 610 compiler.parseScript("abstract class Bar {}"); |
| 591 | 611 |
| 592 ResolverVisitor visitor = new ResolverVisitor( | 612 ResolverVisitor visitor = new ResolverVisitor( |
| 593 compiler.resolution, | 613 compiler.resolution, |
| 594 null, | 614 null, |
| 595 new ResolutionRegistry( | 615 new ResolutionRegistry( |
| 596 compiler.backend, | 616 compiler.backend, new CollectingTreeElements(null))); |
| 597 new CollectingTreeElements(null))); | |
| 598 compiler.resolveStatement("Foo bar;"); | 617 compiler.resolveStatement("Foo bar;"); |
| 599 | 618 |
| 600 ClassElement fooElement = compiler.mainApp.find('Foo'); | 619 ClassElement fooElement = compiler.mainApp.find('Foo'); |
| 601 ClassElement barElement = compiler.mainApp.find('Bar'); | 620 ClassElement barElement = compiler.mainApp.find('Bar'); |
| 602 | 621 |
| 603 Expect.equals(null, barElement.supertype); | 622 Expect.equals(null, barElement.supertype); |
| 604 Expect.isTrue(barElement.interfaces.isEmpty); | 623 Expect.isTrue(barElement.interfaces.isEmpty); |
| 605 | 624 |
| 606 Expect.equals(barElement.computeType(compiler.resolution), | 625 Expect.equals(barElement.computeType(compiler.resolution), |
| 607 fooElement.interfaces.head); | 626 fooElement.interfaces.head); |
| 608 Expect.equals(1, length(fooElement.interfaces)); | 627 Expect.equals(1, length(fooElement.interfaces)); |
| 609 }); | 628 }); |
| 610 } | 629 } |
| 611 | 630 |
| 612 Future testTwoInterfaces() { | 631 Future testTwoInterfaces() { |
| 613 return MockCompiler.create((MockCompiler compiler) { | 632 return MockCompiler.create((MockCompiler compiler) { |
| 614 compiler.parseScript( | 633 compiler.parseScript("""abstract class I1 {} |
| 615 """abstract class I1 {} | |
| 616 abstract class I2 {} | 634 abstract class I2 {} |
| 617 class C implements I1, I2 {}"""); | 635 class C implements I1, I2 {}"""); |
| 618 compiler.resolveStatement("Foo bar;"); | 636 compiler.resolveStatement("Foo bar;"); |
| 619 | 637 |
| 620 ClassElement c = compiler.mainApp.find('C'); | 638 ClassElement c = compiler.mainApp.find('C'); |
| 621 ClassElement i1 = compiler.mainApp.find('I1'); | 639 ClassElement i1 = compiler.mainApp.find('I1'); |
| 622 ClassElement i2 = compiler.mainApp.find('I2'); | 640 ClassElement i2 = compiler.mainApp.find('I2'); |
| 623 | 641 |
| 624 Expect.equals(2, length(c.interfaces)); | 642 Expect.equals(2, length(c.interfaces)); |
| 625 Expect.equals(i1.computeType(compiler.resolution), at(c.interfaces, 0)); | 643 Expect.equals(i1.computeType(compiler.resolution), at(c.interfaces, 0)); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 VariableDefinitions bNode = | 706 VariableDefinitions bNode = |
| 689 bElement.variables.parseNode(bElement, compiler.parsingContext); | 707 bElement.variables.parseNode(bElement, compiler.parsingContext); |
| 690 VariableDefinitions cNode = | 708 VariableDefinitions cNode = |
| 691 cElement.variables.parseNode(cElement, compiler.parsingContext); | 709 cElement.variables.parseNode(cElement, compiler.parsingContext); |
| 692 Expect.equals(bNode, cNode); | 710 Expect.equals(bNode, cNode); |
| 693 Expect.isNull(bNode.type); | 711 Expect.isNull(bNode.type); |
| 694 Expect.isTrue(bNode.modifiers.isVar); | 712 Expect.isTrue(bNode.modifiers.isVar); |
| 695 }); | 713 }); |
| 696 } | 714 } |
| 697 | 715 |
| 698 Future resolveConstructor( | 716 Future resolveConstructor(String script, String statement, String className, |
| 699 String script, String statement, String className, | |
| 700 String constructor, int expectedElementCount, | 717 String constructor, int expectedElementCount, |
| 701 {List expectedWarnings: const [], | 718 {List expectedWarnings: const [], |
| 702 List expectedErrors: const [], | 719 List expectedErrors: const [], |
| 703 List expectedInfos: const [], | 720 List expectedInfos: const [], |
| 704 Map<String, String> corelib}) { | 721 Map<String, String> corelib}) { |
| 705 MockCompiler compiler = new MockCompiler.internal(coreSource: corelib); | 722 MockCompiler compiler = new MockCompiler.internal(coreSource: corelib); |
| 706 return compiler.init().then((_) { | 723 return compiler.init().then((_) { |
| 707 compiler.parseScript(script); | 724 compiler.parseScript(script); |
| 708 compiler.resolveStatement(statement); | 725 compiler.resolveStatement(statement); |
| 709 ClassElement classElement = compiler.mainApp.find(className); | 726 ClassElement classElement = compiler.mainApp.find(className); |
| 710 Element element; | 727 Element element; |
| 711 element = classElement.lookupConstructor(constructor); | 728 element = classElement.lookupConstructor(constructor); |
| 712 FunctionExpression tree = (element as FunctionElement).node; | 729 FunctionExpression tree = (element as FunctionElement).node; |
| 713 ResolverVisitor visitor = new ResolverVisitor( | 730 ResolverVisitor visitor = new ResolverVisitor( |
| 714 compiler.resolution, | 731 compiler.resolution, |
| 715 element, | 732 element, |
| 716 new ResolutionRegistry( | 733 new ResolutionRegistry( |
| 717 compiler.backend, | 734 compiler.backend, new CollectingTreeElements(element)), |
| 718 new CollectingTreeElements(element)), | |
| 719 scope: classElement.buildScope()); | 735 scope: classElement.buildScope()); |
| 720 new InitializerResolver(visitor, element, tree).resolveInitializers(); | 736 new InitializerResolver(visitor, element, tree).resolveInitializers(); |
| 721 visitor.visit(tree.body); | 737 visitor.visit(tree.body); |
| 722 Expect.equals(expectedElementCount, map(visitor).length, | 738 Expect.equals(expectedElementCount, map(visitor).length, |
| 723 "${map(visitor).values} for '$statement' in context of `$script`"); | 739 "${map(visitor).values} for '$statement' in context of `$script`"); |
| 724 | 740 |
| 725 DiagnosticCollector collector = compiler.diagnosticCollector; | 741 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 726 compareWarningKinds(script, expectedWarnings, collector.warnings); | 742 compareWarningKinds(script, expectedWarnings, collector.warnings); |
| 727 compareWarningKinds(script, expectedErrors, collector.errors); | 743 compareWarningKinds(script, expectedErrors, collector.errors); |
| 728 compareWarningKinds(script, expectedInfos, collector.infos); | 744 compareWarningKinds(script, expectedInfos, collector.infos); |
| 729 }); | 745 }); |
| 730 } | 746 } |
| 731 | 747 |
| 732 Future testClassHierarchy() { | 748 Future testClassHierarchy() { |
| 733 final MAIN = "main"; | 749 final MAIN = "main"; |
| 734 return Future.wait([ | 750 return Future.wait([ |
| 735 MockCompiler.create((MockCompiler compiler) { | 751 MockCompiler.create((MockCompiler compiler) { |
| 736 compiler.parseScript("""class A extends A {} | 752 compiler.parseScript("""class A extends A {} |
| 737 main() { return new A(); }"""); | 753 main() { return new A(); }"""); |
| 738 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 754 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 739 compiler.resolver.resolve(mainElement); | 755 compiler.resolver.resolve(mainElement); |
| 740 DiagnosticCollector collector = compiler.diagnosticCollector; | 756 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 741 Expect.equals(0, collector.warnings.length); | 757 Expect.equals(0, collector.warnings.length); |
| 742 Expect.equals(1, collector.errors.length); | 758 Expect.equals(1, collector.errors.length); |
| 743 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, | 759 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 744 collector.errors.first.message.kind); | 760 collector.errors.first.message.kind); |
| 745 }), | 761 }), |
| 746 MockCompiler.create((MockCompiler compiler) { | 762 MockCompiler.create((MockCompiler compiler) { |
| 747 compiler.parseScript("""class A extends B {} | 763 compiler.parseScript("""class A extends B {} |
| 748 class B extends A {} | 764 class B extends A {} |
| 749 main() { return new A(); }"""); | 765 main() { return new A(); }"""); |
| 750 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 766 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 751 compiler.resolver.resolve(mainElement); | 767 compiler.resolver.resolve(mainElement); |
| 752 DiagnosticCollector collector = compiler.diagnosticCollector; | 768 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 753 Expect.equals(0, collector.warnings.length); | 769 Expect.equals(0, collector.warnings.length); |
| 754 Expect.equals(2, collector.errors.length); | 770 Expect.equals(2, collector.errors.length); |
| 755 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, | 771 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 756 collector.errors.first.message.kind); | 772 collector.errors.first.message.kind); |
| 757 Expect.equals(MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR, | 773 Expect.equals(MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR, |
| 758 collector.errors.elementAt(1).message.kind); | 774 collector.errors.elementAt(1).message.kind); |
| 759 }), | 775 }), |
| 760 MockCompiler.create((MockCompiler compiler) { | 776 MockCompiler.create((MockCompiler compiler) { |
| 761 compiler.parseScript("""abstract class A extends B {} | 777 compiler.parseScript("""abstract class A extends B {} |
| 762 abstract class B extends A {} | 778 abstract class B extends A {} |
| 763 class C implements A {} | 779 class C implements A {} |
| 764 main() { return new C(); }"""); | 780 main() { return new C(); }"""); |
| 765 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 781 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 766 compiler.resolver.resolve(mainElement); | 782 compiler.resolver.resolve(mainElement); |
| 767 DiagnosticCollector collector = compiler.diagnosticCollector; | 783 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 768 Expect.equals(0, collector.warnings.length); | 784 Expect.equals(0, collector.warnings.length); |
| 769 Expect.equals(1, collector.errors.length); | 785 Expect.equals(1, collector.errors.length); |
| 770 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, | 786 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 771 collector.errors.first.message.kind); | 787 collector.errors.first.message.kind); |
| 772 }), | 788 }), |
| 773 MockCompiler.create((MockCompiler compiler) { | 789 MockCompiler.create((MockCompiler compiler) { |
| 774 compiler.parseScript("""class A extends B {} | 790 compiler.parseScript("""class A extends B {} |
| 775 class B extends C {} | 791 class B extends C {} |
| 776 class C {} | 792 class C {} |
| 777 main() { return new A(); }"""); | 793 main() { return new A(); }"""); |
| 778 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 794 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 779 compiler.resolver.resolve(mainElement); | 795 compiler.resolver.resolve(mainElement); |
| 780 DiagnosticCollector collector = compiler.diagnosticCollector; | 796 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 781 Expect.equals(0, collector.warnings.length); | 797 Expect.equals(0, collector.warnings.length); |
| 782 Expect.equals(0, collector.errors.length); | 798 Expect.equals(0, collector.errors.length); |
| 783 ClassElement aElement = compiler.mainApp.find("A"); | 799 ClassElement aElement = compiler.mainApp.find("A"); |
| 784 Link<DartType> supertypes = aElement.allSupertypes; | 800 Link<DartType> supertypes = aElement.allSupertypes; |
| 785 Expect.equals(<String>['B', 'C', 'Object'].toString(), | 801 Expect.equals(<String>['B', 'C', 'Object'].toString(), |
| 786 asSortedStrings(supertypes).toString()); | 802 asSortedStrings(supertypes).toString()); |
| 787 }), | 803 }), |
| 788 MockCompiler.create((MockCompiler compiler) { | 804 MockCompiler.create((MockCompiler compiler) { |
| 789 compiler.parseScript("""class A<T> {} | 805 compiler.parseScript("""class A<T> {} |
| 790 class B<Z,W> extends A<int> | 806 class B<Z,W> extends A<int> |
| 791 implements I<Z,List<W>> {} | 807 implements I<Z,List<W>> {} |
| 792 class I<X,Y> {} | 808 class I<X,Y> {} |
| 793 class C extends B<bool,String> {} | 809 class C extends B<bool,String> {} |
| 794 main() { return new C(); }"""); | 810 main() { return new C(); }"""); |
| 795 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 811 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 796 compiler.resolver.resolve(mainElement); | 812 compiler.resolver.resolve(mainElement); |
| 797 DiagnosticCollector collector = compiler.diagnosticCollector; | 813 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 798 Expect.equals(0, collector.warnings.length); | 814 Expect.equals(0, collector.warnings.length); |
| 799 Expect.equals(0, collector.errors.length); | 815 Expect.equals(0, collector.errors.length); |
| 800 ClassElement aElement = compiler.mainApp.find("C"); | 816 ClassElement aElement = compiler.mainApp.find("C"); |
| 801 Link<DartType> supertypes = aElement.allSupertypes; | 817 Link<DartType> supertypes = aElement.allSupertypes; |
| 802 // Object is once per inheritance path, that is from both A and I. | 818 // Object is once per inheritance path, that is from both A and I. |
| 803 Expect.equals(<String>['A<int>', 'B<bool, String>', | 819 Expect.equals( |
| 804 'I<bool, List<String>>', 'Object'].toString(), | 820 <String>[ |
| 805 asSortedStrings(supertypes).toString()); | 821 'A<int>', |
| 822 'B<bool, String>', |
| 823 'I<bool, List<String>>', |
| 824 'Object' |
| 825 ].toString(), |
| 826 asSortedStrings(supertypes).toString()); |
| 806 }), | 827 }), |
| 807 MockCompiler.create((MockCompiler compiler) { | 828 MockCompiler.create((MockCompiler compiler) { |
| 808 compiler.parseScript("""class A<T> {} | 829 compiler.parseScript("""class A<T> {} |
| 809 class D extends A<E> {} | 830 class D extends A<E> {} |
| 810 class E extends D {} | 831 class E extends D {} |
| 811 main() { return new E(); }"""); | 832 main() { return new E(); }"""); |
| 812 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 833 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 813 compiler.resolver.resolve(mainElement); | 834 compiler.resolver.resolve(mainElement); |
| 814 DiagnosticCollector collector = compiler.diagnosticCollector; | 835 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 815 Expect.equals(0, collector.warnings.length); | 836 Expect.equals(0, collector.warnings.length); |
| 816 Expect.equals(0, collector.errors.length); | 837 Expect.equals(0, collector.errors.length); |
| 817 ClassElement aElement = compiler.mainApp.find("E"); | 838 ClassElement aElement = compiler.mainApp.find("E"); |
| 818 Link<DartType> supertypes = aElement.allSupertypes; | 839 Link<DartType> supertypes = aElement.allSupertypes; |
| 819 Expect.equals(<String>['A<E>', 'D', 'Object'].toString(), | 840 Expect.equals(<String>['A<E>', 'D', 'Object'].toString(), |
| 820 asSortedStrings(supertypes).toString()); | 841 asSortedStrings(supertypes).toString()); |
| 821 }), | 842 }), |
| 822 MockCompiler.create((MockCompiler compiler) { | 843 MockCompiler.create((MockCompiler compiler) { |
| 823 compiler.parseScript("""class A<T> {} | 844 compiler.parseScript("""class A<T> {} |
| 824 class D extends A<int> implements A<double> {} | 845 class D extends A<int> implements A<double> {} |
| 825 main() { return new D(); }"""); | 846 main() { return new D(); }"""); |
| 826 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 847 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 827 compiler.resolver.resolve(mainElement); | 848 compiler.resolver.resolve(mainElement); |
| 828 DiagnosticCollector collector = compiler.diagnosticCollector; | 849 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 829 Expect.equals(0, collector.warnings.length); | 850 Expect.equals(0, collector.warnings.length); |
| 830 Expect.equals(1, collector.errors.length); | 851 Expect.equals(1, collector.errors.length); |
| 831 Expect.equals(MessageKind.MULTI_INHERITANCE, | 852 Expect.equals( |
| 832 collector.errors.first.message.kind); | 853 MessageKind.MULTI_INHERITANCE, collector.errors.first.message.kind); |
| 833 Expect.equals(0, collector.crashes.length); | 854 Expect.equals(0, collector.crashes.length); |
| 834 }), | 855 }), |
| 835 ]); | 856 ]); |
| 836 } | 857 } |
| 837 | 858 |
| 838 Future testEnumDeclaration() { | 859 Future testEnumDeclaration() { |
| 839 final MAIN = "main"; | 860 final MAIN = "main"; |
| 840 return Future.wait([ | 861 return Future.wait([ |
| 841 MockCompiler.create((MockCompiler compiler) { | 862 MockCompiler.create((MockCompiler compiler) { |
| 842 compiler.parseScript("""enum Enum {} | 863 compiler.parseScript("""enum Enum {} |
| 843 main() { Enum e; }"""); | 864 main() { Enum e; }"""); |
| 844 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 865 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 845 compiler.resolver.resolve(mainElement); | 866 compiler.resolver.resolve(mainElement); |
| 846 DiagnosticCollector collector = compiler.diagnosticCollector; | 867 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 847 Expect.equals(0, collector.warnings.length, | 868 Expect.equals(0, collector.warnings.length, |
| 848 'Unexpected warnings: ${collector.warnings}'); | 869 'Unexpected warnings: ${collector.warnings}'); |
| 849 Expect.equals(1, collector.errors.length, | 870 Expect.equals( |
| 850 'Unexpected errors: ${collector.errors}'); | 871 1, collector.errors.length, 'Unexpected errors: ${collector.errors}'); |
| 851 }), | 872 }), |
| 852 | |
| 853 MockCompiler.create((MockCompiler compiler) { | 873 MockCompiler.create((MockCompiler compiler) { |
| 854 compiler.parseScript("""enum Enum { A } | 874 compiler.parseScript("""enum Enum { A } |
| 855 main() { Enum e = Enum.A; }"""); | 875 main() { Enum e = Enum.A; }"""); |
| 856 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 876 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 857 compiler.resolver.resolve(mainElement); | 877 compiler.resolver.resolve(mainElement); |
| 858 DiagnosticCollector collector = compiler.diagnosticCollector; | 878 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 859 Expect.equals(0, collector.warnings.length, | 879 Expect.equals(0, collector.warnings.length, |
| 860 'Unexpected warnings: ${collector.warnings}'); | 880 'Unexpected warnings: ${collector.warnings}'); |
| 861 Expect.equals(0, collector.errors.length, | 881 Expect.equals( |
| 862 'Unexpected errors: ${collector.errors}'); | 882 0, collector.errors.length, 'Unexpected errors: ${collector.errors}'); |
| 863 }), | 883 }), |
| 864 | |
| 865 MockCompiler.create((MockCompiler compiler) { | 884 MockCompiler.create((MockCompiler compiler) { |
| 866 compiler.parseScript("""enum Enum { A } | 885 compiler.parseScript("""enum Enum { A } |
| 867 main() { Enum e = Enum.B; }"""); | 886 main() { Enum e = Enum.B; }"""); |
| 868 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 887 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 869 compiler.resolver.resolve(mainElement); | 888 compiler.resolver.resolve(mainElement); |
| 870 DiagnosticCollector collector = compiler.diagnosticCollector; | 889 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 871 Expect.equals(1, collector.warnings.length, | 890 Expect.equals(1, collector.warnings.length, |
| 872 'Unexpected warnings: ${collector.warnings}'); | 891 'Unexpected warnings: ${collector.warnings}'); |
| 873 Expect.equals(MessageKind.UNDEFINED_GETTER, | 892 Expect.equals( |
| 874 collector.warnings.first.message.kind); | 893 MessageKind.UNDEFINED_GETTER, collector.warnings.first.message.kind); |
| 875 Expect.equals(0, collector.errors.length, | 894 Expect.equals( |
| 876 'Unexpected errors: ${collector.errors}'); | 895 0, collector.errors.length, 'Unexpected errors: ${collector.errors}'); |
| 877 }), | 896 }), |
| 878 | |
| 879 MockCompiler.create((MockCompiler compiler) { | 897 MockCompiler.create((MockCompiler compiler) { |
| 880 compiler.parseScript("""enum Enum { A } | 898 compiler.parseScript("""enum Enum { A } |
| 881 main() { List values = Enum.values; }"""); | 899 main() { List values = Enum.values; }"""); |
| 882 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 900 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 883 compiler.resolver.resolve(mainElement); | 901 compiler.resolver.resolve(mainElement); |
| 884 DiagnosticCollector collector = compiler.diagnosticCollector; | 902 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 885 Expect.equals(0, collector.warnings.length, | 903 Expect.equals(0, collector.warnings.length, |
| 886 'Unexpected warnings: ${collector.warnings}'); | 904 'Unexpected warnings: ${collector.warnings}'); |
| 887 Expect.equals(0, collector.errors.length, | 905 Expect.equals( |
| 888 'Unexpected errors: ${collector.errors}'); | 906 0, collector.errors.length, 'Unexpected errors: ${collector.errors}'); |
| 889 }), | 907 }), |
| 890 | |
| 891 MockCompiler.create((MockCompiler compiler) { | 908 MockCompiler.create((MockCompiler compiler) { |
| 892 compiler.parseScript("""enum Enum { A } | 909 compiler.parseScript("""enum Enum { A } |
| 893 main() { new Enum(0, ''); }"""); | 910 main() { new Enum(0, ''); }"""); |
| 894 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 911 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 895 compiler.resolver.resolve(mainElement); | 912 compiler.resolver.resolve(mainElement); |
| 896 DiagnosticCollector collector = compiler.diagnosticCollector; | 913 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 897 Expect.equals(0, collector.warnings.length, | 914 Expect.equals(0, collector.warnings.length, |
| 898 'Unexpected warnings: ${collector.warnings}'); | 915 'Unexpected warnings: ${collector.warnings}'); |
| 899 Expect.equals(1, collector.errors.length, | 916 Expect.equals( |
| 900 'Unexpected errors: ${collector.errors}'); | 917 1, collector.errors.length, 'Unexpected errors: ${collector.errors}'); |
| 901 Expect.equals(MessageKind.CANNOT_INSTANTIATE_ENUM, | 918 Expect.equals(MessageKind.CANNOT_INSTANTIATE_ENUM, |
| 902 collector.errors.first.message.kind); | 919 collector.errors.first.message.kind); |
| 903 }), | 920 }), |
| 904 | |
| 905 MockCompiler.create((MockCompiler compiler) { | 921 MockCompiler.create((MockCompiler compiler) { |
| 906 compiler.parseScript("""enum Enum { A } | 922 compiler.parseScript("""enum Enum { A } |
| 907 main() { const Enum(0, ''); }"""); | 923 main() { const Enum(0, ''); }"""); |
| 908 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 924 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 909 compiler.resolver.resolve(mainElement); | 925 compiler.resolver.resolve(mainElement); |
| 910 DiagnosticCollector collector = compiler.diagnosticCollector; | 926 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 911 Expect.equals(0, collector.warnings.length, | 927 Expect.equals(0, collector.warnings.length, |
| 912 'Unexpected warnings: ${collector.warnings}'); | 928 'Unexpected warnings: ${collector.warnings}'); |
| 913 Expect.equals(1, collector.errors.length, | 929 Expect.equals( |
| 914 'Unexpected errors: ${collector.errors}'); | 930 1, collector.errors.length, 'Unexpected errors: ${collector.errors}'); |
| 915 Expect.equals(MessageKind.CANNOT_INSTANTIATE_ENUM, | 931 Expect.equals(MessageKind.CANNOT_INSTANTIATE_ENUM, |
| 916 collector.errors.first.message.kind); | 932 collector.errors.first.message.kind); |
| 917 }), | 933 }), |
| 918 ]); | 934 ]); |
| 919 } | 935 } |
| 920 | 936 |
| 921 Future testInitializers() { | 937 Future testInitializers() { |
| 922 return Future.forEach([ | 938 return Future.forEach([ |
| 923 () { | 939 () { |
| 924 String script = | 940 String script = """class A { |
| 925 """class A { | |
| 926 int foo; int bar; | 941 int foo; int bar; |
| 927 A() : this.foo = 1, bar = 2; | 942 A() : this.foo = 1, bar = 2; |
| 928 }"""; | 943 }"""; |
| 929 return resolveConstructor(script, "A a = new A();", "A", "", 2); | 944 return resolveConstructor(script, "A a = new A();", "A", "", 2); |
| 930 }, | 945 }, |
| 931 () { | 946 () { |
| 932 String script = | 947 String script = """class A { |
| 933 """class A { | |
| 934 int foo; A a; | 948 int foo; A a; |
| 935 A() : a.foo = 1; | 949 A() : a.foo = 1; |
| 936 }"""; | 950 }"""; |
| 937 return resolveConstructor(script, "A a = new A();", "A", "", 0, | 951 return resolveConstructor(script, "A a = new A();", "A", "", 0, |
| 938 expectedWarnings: [], | 952 expectedWarnings: [], |
| 939 expectedErrors: [MessageKind.INVALID_RECEIVER_IN_INITIALIZER]); | 953 expectedErrors: [MessageKind.INVALID_RECEIVER_IN_INITIALIZER]); |
| 940 }, | 954 }, |
| 941 () { | 955 () { |
| 942 String script = | 956 String script = """class A { |
| 943 """class A { | |
| 944 int foo; | 957 int foo; |
| 945 A() : this.foo = 1, this.foo = 2; | 958 A() : this.foo = 1, this.foo = 2; |
| 946 }"""; | 959 }"""; |
| 947 return resolveConstructor(script, "A a = new A();", "A", "", 2, | 960 return resolveConstructor(script, "A a = new A();", "A", "", 2, |
| 948 expectedInfos: [MessageKind.ALREADY_INITIALIZED], | 961 expectedInfos: [MessageKind.ALREADY_INITIALIZED], |
| 949 expectedErrors: [MessageKind.DUPLICATE_INITIALIZER]); | 962 expectedErrors: [MessageKind.DUPLICATE_INITIALIZER]); |
| 950 }, | 963 }, |
| 951 () { | 964 () { |
| 952 String script = | 965 String script = """class A { |
| 953 """class A { | |
| 954 A() : this.foo = 1; | 966 A() : this.foo = 1; |
| 955 }"""; | 967 }"""; |
| 956 return resolveConstructor(script, "A a = new A();", "A", "", 1, | 968 return resolveConstructor(script, "A a = new A();", "A", "", 1, |
| 957 expectedWarnings: [], | 969 expectedWarnings: [], expectedErrors: [MessageKind.CANNOT_RESOLVE]); |
| 958 expectedErrors: [MessageKind.CANNOT_RESOLVE]); | |
| 959 }, | 970 }, |
| 960 () { | 971 () { |
| 961 String script = | 972 String script = """class A { |
| 962 """class A { | |
| 963 int foo; | 973 int foo; |
| 964 int bar; | 974 int bar; |
| 965 A() : this.foo = bar; | 975 A() : this.foo = bar; |
| 966 }"""; | 976 }"""; |
| 967 return resolveConstructor(script, "A a = new A();", "A", "", 2, | 977 return resolveConstructor(script, "A a = new A();", "A", "", 2, |
| 968 expectedWarnings: [], | 978 expectedWarnings: [], |
| 969 expectedErrors: [MessageKind.NO_INSTANCE_AVAILABLE]); | 979 expectedErrors: [MessageKind.NO_INSTANCE_AVAILABLE]); |
| 970 }, | 980 }, |
| 971 () { | 981 () { |
| 972 String script = | 982 String script = """class A { |
| 973 """class A { | |
| 974 int foo() => 42; | 983 int foo() => 42; |
| 975 A() : foo(); | 984 A() : foo(); |
| 976 }"""; | 985 }"""; |
| 977 return resolveConstructor(script, "A a = new A();", "A", "", 0, | 986 return resolveConstructor(script, "A a = new A();", "A", "", 0, |
| 978 expectedWarnings: [], | 987 expectedWarnings: [], |
| 979 expectedErrors: [MessageKind.CONSTRUCTOR_CALL_EXPECTED]); | 988 expectedErrors: [MessageKind.CONSTRUCTOR_CALL_EXPECTED]); |
| 980 }, | 989 }, |
| 981 () { | 990 () { |
| 982 String script = | 991 String script = """class A { |
| 983 """class A { | |
| 984 int i; | 992 int i; |
| 985 A.a() : this.b(0); | 993 A.a() : this.b(0); |
| 986 A.b(int i); | 994 A.b(int i); |
| 987 }"""; | 995 }"""; |
| 988 return resolveConstructor(script, "A a = new A.a();", "A", "a", 1); | 996 return resolveConstructor(script, "A a = new A.a();", "A", "a", 1); |
| 989 }, | 997 }, |
| 990 () { | 998 () { |
| 991 String script = | 999 String script = """class A { |
| 992 """class A { | |
| 993 int i; | 1000 int i; |
| 994 A.a() : i = 42, this(0); | 1001 A.a() : i = 42, this(0); |
| 995 A(int i); | 1002 A(int i); |
| 996 }"""; | 1003 }"""; |
| 997 return resolveConstructor(script, "A a = new A.a();", "A", "a", 2, | 1004 return resolveConstructor(script, "A a = new A.a();", "A", "a", 2, |
| 998 expectedWarnings: [], | 1005 expectedWarnings: [], |
| 999 expectedErrors: | 1006 expectedErrors: [ |
| 1000 [MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER]); | 1007 MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER |
| 1008 ]); |
| 1001 }, | 1009 }, |
| 1002 () { | 1010 () { |
| 1003 String script = | 1011 String script = """class A { |
| 1004 """class A { | |
| 1005 int i; | 1012 int i; |
| 1006 A(i); | 1013 A(i); |
| 1007 } | 1014 } |
| 1008 class B extends A { | 1015 class B extends A { |
| 1009 B() : super(0); | 1016 B() : super(0); |
| 1010 }"""; | 1017 }"""; |
| 1011 return resolveConstructor(script, "B a = new B();", "B", "", 1); | 1018 return resolveConstructor(script, "B a = new B();", "B", "", 1); |
| 1012 }, | 1019 }, |
| 1013 () { | 1020 () { |
| 1014 String script = | 1021 String script = """class A { |
| 1015 """class A { | |
| 1016 int i; | 1022 int i; |
| 1017 A(i); | 1023 A(i); |
| 1018 } | 1024 } |
| 1019 class B extends A { | 1025 class B extends A { |
| 1020 B() : super(0), super(1); | 1026 B() : super(0), super(1); |
| 1021 }"""; | 1027 }"""; |
| 1022 return resolveConstructor(script, "B b = new B();", "B", "", 2, | 1028 return resolveConstructor(script, "B b = new B();", "B", "", 2, |
| 1023 expectedWarnings: [], | 1029 expectedWarnings: [], |
| 1024 expectedErrors: [MessageKind.DUPLICATE_SUPER_INITIALIZER]); | 1030 expectedErrors: [MessageKind.DUPLICATE_SUPER_INITIALIZER]); |
| 1025 }, | 1031 }, |
| 1026 () { | 1032 () { |
| 1027 String script = ""; | 1033 String script = ""; |
| 1028 final INVALID_OBJECT = | 1034 final INVALID_OBJECT = const { |
| 1029 const { 'Object': 'class Object { Object() : super(); }' }; | 1035 'Object': 'class Object { Object() : super(); }' |
| 1030 return resolveConstructor(script, | 1036 }; |
| 1031 "Object o = new Object();", "Object", "", 1, | 1037 return resolveConstructor( |
| 1038 script, "Object o = new Object();", "Object", "", 1, |
| 1032 expectedWarnings: [], | 1039 expectedWarnings: [], |
| 1033 expectedErrors: [MessageKind.SUPER_INITIALIZER_IN_OBJECT], | 1040 expectedErrors: [MessageKind.SUPER_INITIALIZER_IN_OBJECT], |
| 1034 corelib: INVALID_OBJECT); | 1041 corelib: INVALID_OBJECT); |
| 1035 }, | 1042 }, |
| 1036 ], (f) => f()); | 1043 ], (f) => f()); |
| 1037 } | 1044 } |
| 1038 | 1045 |
| 1039 Future testConstantExpressions() { | 1046 Future testConstantExpressions() { |
| 1040 const Map<String, List<String>> testedConstants = const { | 1047 const Map<String, List<String>> testedConstants = const { |
| 1041 'null': const ['null'], | 1048 'null': const ['null'], |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1057 r'"a${0}b${1}"': const ['"a"', '0', '"b"', '1', '""', r'"a${0}b${1}"'], | 1064 r'"a${0}b${1}"': const ['"a"', '0', '"b"', '1', '""', r'"a${0}b${1}"'], |
| 1058 'true || false': const ['true', 'false', 'true || false'], | 1065 'true || false': const ['true', 'false', 'true || false'], |
| 1059 'true && false': const ['true', 'false', 'true && false'], | 1066 'true && false': const ['true', 'false', 'true && false'], |
| 1060 '!true': const ['true', '!true'], | 1067 '!true': const ['true', '!true'], |
| 1061 'const []': const ['const []'], | 1068 'const []': const ['const []'], |
| 1062 'const <int>[]': const ['const <int>[]'], | 1069 'const <int>[]': const ['const <int>[]'], |
| 1063 'const [0, 1, 2]': const ['0', '1', '2', 'const [0, 1, 2]'], | 1070 'const [0, 1, 2]': const ['0', '1', '2', 'const [0, 1, 2]'], |
| 1064 'const <int>[0, 1, 2]': const ['0', '1', '2', 'const <int>[0, 1, 2]'], | 1071 'const <int>[0, 1, 2]': const ['0', '1', '2', 'const <int>[0, 1, 2]'], |
| 1065 'const {}': const ['const {}'], | 1072 'const {}': const ['const {}'], |
| 1066 'const <String, int>{}': const ['const <String, int>{}'], | 1073 'const <String, int>{}': const ['const <String, int>{}'], |
| 1067 'const {"a": 0, "b": 1, "c": 2}': | 1074 'const {"a": 0, "b": 1, "c": 2}': const [ |
| 1068 const ['"a"', '0', '"b"', '1', '"c"', '2', | 1075 '"a"', |
| 1069 'const {"a": 0, "b": 1, "c": 2}'], | 1076 '0', |
| 1070 'const <String, int>{"a": 0, "b": 1, "c": 2}': | 1077 '"b"', |
| 1071 const ['"a"', '0', '"b"', '1', '"c"', '2', | 1078 '1', |
| 1072 'const <String, int>{"a": 0, "b": 1, "c": 2}'], | 1079 '"c"', |
| 1080 '2', |
| 1081 'const {"a": 0, "b": 1, "c": 2}' |
| 1082 ], |
| 1083 'const <String, int>{"a": 0, "b": 1, "c": 2}': const [ |
| 1084 '"a"', |
| 1085 '0', |
| 1086 '"b"', |
| 1087 '1', |
| 1088 '"c"', |
| 1089 '2', |
| 1090 'const <String, int>{"a": 0, "b": 1, "c": 2}' |
| 1091 ], |
| 1073 }; | 1092 }; |
| 1074 return Future.forEach(testedConstants.keys, (String constant) { | 1093 return Future.forEach(testedConstants.keys, (String constant) { |
| 1075 return MockCompiler.create((MockCompiler compiler) { | 1094 return MockCompiler.create((MockCompiler compiler) { |
| 1076 CollectingTreeElements elements = | 1095 CollectingTreeElements elements = |
| 1077 compiler.resolveStatement("main() => $constant;"); | 1096 compiler.resolveStatement("main() => $constant;"); |
| 1078 List<String> expectedConstants = testedConstants[constant]; | 1097 List<String> expectedConstants = testedConstants[constant]; |
| 1079 DiagnosticCollector collector = compiler.diagnosticCollector; | 1098 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 1080 Expect.equals(0, collector.warnings.length); | 1099 Expect.equals(0, collector.warnings.length); |
| 1081 Expect.equals(0, collector.errors.length); | 1100 Expect.equals(0, collector.errors.length); |
| 1082 List<ConstantExpression> constants = elements.constants; | 1101 List<ConstantExpression> constants = elements.constants; |
| 1083 String constantsText = | 1102 String constantsText = |
| 1084 '[${constants.map((c) => c.toDartText()).join(', ')}]'; | 1103 '[${constants.map((c) => c.toDartText()).join(', ')}]'; |
| 1085 Expect.equals(expectedConstants.length, constants.length, | 1104 Expect.equals( |
| 1105 expectedConstants.length, |
| 1106 constants.length, |
| 1086 "Expected ${expectedConstants.length} constants for `${constant}` " | 1107 "Expected ${expectedConstants.length} constants for `${constant}` " |
| 1087 "found $constantsText."); | 1108 "found $constantsText."); |
| 1088 for (int index = 0; index < expectedConstants.length; index++) { | 1109 for (int index = 0; index < expectedConstants.length; index++) { |
| 1089 Expect.equals(expectedConstants[index], constants[index].toDartText(), | 1110 Expect.equals( |
| 1111 expectedConstants[index], |
| 1112 constants[index].toDartText(), |
| 1090 "Expected ${expectedConstants} for `$constant`, " | 1113 "Expected ${expectedConstants} for `$constant`, " |
| 1091 "found $constantsText."); | 1114 "found $constantsText."); |
| 1092 } | 1115 } |
| 1093 }); | 1116 }); |
| 1094 }); | 1117 }); |
| 1095 } | 1118 } |
| 1096 | 1119 |
| 1097 map(ResolverVisitor visitor) { | 1120 map(ResolverVisitor visitor) { |
| 1098 CollectingTreeElements elements = visitor.registry.mapping; | 1121 CollectingTreeElements elements = visitor.registry.mapping; |
| 1099 return elements.map; | 1122 return elements.map; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1114 compiler.diagnosticHandler = createHandler(compiler, source); | 1137 compiler.diagnosticHandler = createHandler(compiler, source); |
| 1115 return compiler.run(uri).then((_) { | 1138 return compiler.run(uri).then((_) { |
| 1116 return compiler; | 1139 return compiler; |
| 1117 }); | 1140 }); |
| 1118 } | 1141 } |
| 1119 | 1142 |
| 1120 checkMemberResolved(compiler, className, memberName) { | 1143 checkMemberResolved(compiler, className, memberName) { |
| 1121 ClassElement cls = findElement(compiler, className); | 1144 ClassElement cls = findElement(compiler, className); |
| 1122 Element memberElement = cls.lookupLocalMember(memberName); | 1145 Element memberElement = cls.lookupLocalMember(memberName); |
| 1123 Expect.isNotNull(memberElement); | 1146 Expect.isNotNull(memberElement); |
| 1124 Expect.isTrue( | 1147 Expect.isTrue(compiler.enqueuer.resolution.hasBeenProcessed(memberElement)); |
| 1125 compiler.enqueuer.resolution.hasBeenProcessed(memberElement)); | |
| 1126 } | 1148 } |
| 1127 | 1149 |
| 1128 testToString() { | 1150 testToString() { |
| 1129 final script = r"class C { toString() => 'C'; } main() { '${new C()}'; }"; | 1151 final script = r"class C { toString() => 'C'; } main() { '${new C()}'; }"; |
| 1130 asyncTest(() => compileScript(script).then((compiler) { | 1152 asyncTest(() => compileScript(script).then((compiler) { |
| 1131 checkMemberResolved(compiler, 'C', 'toString'); | 1153 checkMemberResolved(compiler, 'C', 'toString'); |
| 1132 })); | 1154 })); |
| 1133 } | 1155 } |
| 1134 | 1156 |
| 1135 operatorName(op, isUnary) { | 1157 operatorName(op, isUnary) { |
| 1136 return Elements.constructOperatorName(op, isUnary); | 1158 return Elements.constructOperatorName(op, isUnary); |
| 1137 } | 1159 } |
| 1138 | 1160 |
| 1139 testIndexedOperator() { | 1161 testIndexedOperator() { |
| 1140 final script = r""" | 1162 final script = r""" |
| 1141 class C { | 1163 class C { |
| 1142 operator[](ix) => ix; | 1164 operator[](ix) => ix; |
| 1143 operator[]=(ix, v) {} | 1165 operator[]=(ix, v) {} |
| 1144 } | 1166 } |
| 1145 main() { var c = new C(); c[0]++; }"""; | 1167 main() { var c = new C(); c[0]++; }"""; |
| 1146 asyncTest(() => compileScript(script).then((compiler) { | 1168 asyncTest(() => compileScript(script).then((compiler) { |
| 1147 checkMemberResolved(compiler, 'C', operatorName('[]', false)); | 1169 checkMemberResolved(compiler, 'C', operatorName('[]', false)); |
| 1148 checkMemberResolved(compiler, 'C', operatorName('[]=', false)); | 1170 checkMemberResolved(compiler, 'C', operatorName('[]=', false)); |
| 1149 })); | 1171 })); |
| 1150 } | 1172 } |
| 1151 | 1173 |
| 1152 testIncrementsAndDecrements() { | 1174 testIncrementsAndDecrements() { |
| 1153 final script = r""" | 1175 final script = r""" |
| 1154 class A { operator+(o)=>null; } | 1176 class A { operator+(o)=>null; } |
| 1155 class B { operator+(o)=>null; } | 1177 class B { operator+(o)=>null; } |
| 1156 class C { operator-(o)=>null; } | 1178 class C { operator-(o)=>null; } |
| 1157 class D { operator-(o)=>null; } | 1179 class D { operator-(o)=>null; } |
| 1158 main() { | 1180 main() { |
| 1159 var a = new A(); | 1181 var a = new A(); |
| 1160 a++; | 1182 a++; |
| 1161 var b = new B(); | 1183 var b = new B(); |
| 1162 ++b; | 1184 ++b; |
| 1163 var c = new C(); | 1185 var c = new C(); |
| 1164 c--; | 1186 c--; |
| 1165 var d = new D(); | 1187 var d = new D(); |
| 1166 --d; | 1188 --d; |
| 1167 }"""; | 1189 }"""; |
| 1168 asyncTest(() => compileScript(script).then((compiler) { | 1190 asyncTest(() => compileScript(script).then((compiler) { |
| 1169 checkMemberResolved(compiler, 'A', operatorName('+', false)); | 1191 checkMemberResolved(compiler, 'A', operatorName('+', false)); |
| 1170 checkMemberResolved(compiler, 'B', operatorName('+', false)); | 1192 checkMemberResolved(compiler, 'B', operatorName('+', false)); |
| 1171 checkMemberResolved(compiler, 'C', operatorName('-', false)); | 1193 checkMemberResolved(compiler, 'C', operatorName('-', false)); |
| 1172 checkMemberResolved(compiler, 'D', operatorName('-', false)); | 1194 checkMemberResolved(compiler, 'D', operatorName('-', false)); |
| 1173 })); | 1195 })); |
| 1174 } | 1196 } |
| 1175 | 1197 |
| 1176 testOverrideHashCodeCheck() { | 1198 testOverrideHashCodeCheck() { |
| 1177 final script = r""" | 1199 final script = r""" |
| 1178 class A { | 1200 class A { |
| 1179 operator==(other) => true; | 1201 operator==(other) => true; |
| 1180 } | 1202 } |
| 1181 class B { | 1203 class B { |
| 1182 operator==(other) => true; | 1204 operator==(other) => true; |
| 1183 get hashCode => 0; | 1205 get hashCode => 0; |
| 1184 } | 1206 } |
| 1185 main() { | 1207 main() { |
| 1186 new A() == new B(); | 1208 new A() == new B(); |
| 1187 }"""; | 1209 }"""; |
| 1188 asyncTest(() => compileScript(script).then((compiler) { | 1210 asyncTest(() => compileScript(script).then((compiler) { |
| 1189 DiagnosticCollector collector = compiler.diagnosticCollector; | 1211 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 1190 Expect.equals(0, collector.warnings.length); | 1212 Expect.equals(0, collector.warnings.length); |
| 1191 Expect.equals(0, collector.infos.length); | 1213 Expect.equals(0, collector.infos.length); |
| 1192 Expect.equals(1, collector.hints.length); | 1214 Expect.equals(1, collector.hints.length); |
| 1193 Expect.equals(MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, | 1215 Expect.equals(MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, |
| 1194 collector.hints.first.message.kind); | 1216 collector.hints.first.message.kind); |
| 1195 Expect.equals(0, collector.errors.length); | 1217 Expect.equals(0, collector.errors.length); |
| 1196 })); | 1218 })); |
| 1197 } | 1219 } |
| 1198 | 1220 |
| 1199 testConstConstructorAndNonFinalFields() { | 1221 testConstConstructorAndNonFinalFields() { |
| 1200 void expect(compiler, List errors, List infos) { | 1222 void expect(compiler, List errors, List infos) { |
| 1201 DiagnosticCollector collector = compiler.diagnosticCollector; | 1223 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 1202 Expect.equals(errors.length, collector.errors.length); | 1224 Expect.equals(errors.length, collector.errors.length); |
| 1203 for (int i = 0 ; i < errors.length ; i++) { | 1225 for (int i = 0; i < errors.length; i++) { |
| 1204 Expect.equals(errors[i], collector.errors.elementAt(i).message.kind); | 1226 Expect.equals(errors[i], collector.errors.elementAt(i).message.kind); |
| 1205 } | 1227 } |
| 1206 Expect.equals(0, collector.warnings.length); | 1228 Expect.equals(0, collector.warnings.length); |
| 1207 Expect.equals(infos.length, collector.infos.length); | 1229 Expect.equals(infos.length, collector.infos.length); |
| 1208 for (int i = 0 ; i < infos.length ; i++) { | 1230 for (int i = 0; i < infos.length; i++) { |
| 1209 Expect.equals(infos[i], collector.infos.elementAt(i).message.kind); | 1231 Expect.equals(infos[i], collector.infos.elementAt(i).message.kind); |
| 1210 } | 1232 } |
| 1211 } | 1233 } |
| 1212 | 1234 |
| 1213 final script1 = r""" | 1235 final script1 = r""" |
| 1214 class A { | 1236 class A { |
| 1215 var a; | 1237 var a; |
| 1216 const A(this.a); | 1238 const A(this.a); |
| 1217 } | 1239 } |
| 1218 main() { | 1240 main() { |
| 1219 new A(0); | 1241 new A(0); |
| 1220 }"""; | 1242 }"""; |
| 1221 asyncTest(() => compileScript(script1).then((compiler) { | 1243 asyncTest(() => compileScript(script1).then((compiler) { |
| 1222 expect(compiler, | 1244 expect(compiler, [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS], |
| 1223 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS], | 1245 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD]); |
| 1224 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD]); | 1246 })); |
| 1225 })); | |
| 1226 | 1247 |
| 1227 final script2 = r""" | 1248 final script2 = r""" |
| 1228 class A { | 1249 class A { |
| 1229 var a; | 1250 var a; |
| 1230 var b; | 1251 var b; |
| 1231 const A(this.a, this.b); | 1252 const A(this.a, this.b); |
| 1232 const A.named(this.a, this.b); | 1253 const A.named(this.a, this.b); |
| 1233 } | 1254 } |
| 1234 main() { | 1255 main() { |
| 1235 new A(0, 1); | 1256 new A(0, 1); |
| 1236 }"""; | 1257 }"""; |
| 1237 asyncTest(() => compileScript(script2).then((compiler) { | 1258 asyncTest(() => compileScript(script2).then((compiler) { |
| 1238 expect(compiler, | 1259 expect(compiler, [ |
| 1239 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS], | 1260 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS |
| 1240 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, | 1261 ], [ |
| 1241 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, | 1262 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, |
| 1242 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD, | 1263 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, |
| 1243 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD]); | 1264 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD, |
| 1244 })); | 1265 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD |
| 1266 ]); |
| 1267 })); |
| 1245 } | 1268 } |
| 1246 | 1269 |
| 1247 testCantAssignMethods() { | 1270 testCantAssignMethods() { |
| 1248 // Can't override local functions | 1271 // Can't override local functions |
| 1249 checkWarningOn(''' | 1272 checkWarningOn( |
| 1273 ''' |
| 1250 main() { | 1274 main() { |
| 1251 mname() { mname = 2; }; | 1275 mname() { mname = 2; }; |
| 1252 mname(); | 1276 mname(); |
| 1253 } | 1277 } |
| 1254 ''', [MessageKind.ASSIGNING_METHOD]); | 1278 ''', |
| 1279 [MessageKind.ASSIGNING_METHOD]); |
| 1255 | 1280 |
| 1256 checkWarningOn(''' | 1281 checkWarningOn( |
| 1282 ''' |
| 1257 main() { | 1283 main() { |
| 1258 mname() { }; | 1284 mname() { }; |
| 1259 mname = 3; | 1285 mname = 3; |
| 1260 } | 1286 } |
| 1261 ''', [MessageKind.ASSIGNING_METHOD]); | 1287 ''', |
| 1288 [MessageKind.ASSIGNING_METHOD]); |
| 1262 | 1289 |
| 1263 // Can't override top-level functions | 1290 // Can't override top-level functions |
| 1264 checkWarningOn(''' | 1291 checkWarningOn( |
| 1292 ''' |
| 1265 m() {} | 1293 m() {} |
| 1266 main() { m = 4; } | 1294 main() { m = 4; } |
| 1267 ''', [MessageKind.ASSIGNING_METHOD, | 1295 ''', |
| 1268 // TODO(johnniwinther): Avoid duplicate warnings. | 1296 [ |
| 1269 MessageKind.NOT_ASSIGNABLE]); | 1297 MessageKind.ASSIGNING_METHOD, |
| 1298 // TODO(johnniwinther): Avoid duplicate warnings. |
| 1299 MessageKind.NOT_ASSIGNABLE |
| 1300 ]); |
| 1270 | 1301 |
| 1271 // Can't override instance methods | 1302 // Can't override instance methods |
| 1272 checkWarningOn(''' | 1303 checkWarningOn( |
| 1304 ''' |
| 1273 main() { new B().bar(); } | 1305 main() { new B().bar(); } |
| 1274 class B { | 1306 class B { |
| 1275 mname() {} | 1307 mname() {} |
| 1276 bar() { | 1308 bar() { |
| 1277 mname = () => null; | 1309 mname = () => null; |
| 1278 } | 1310 } |
| 1279 } | 1311 } |
| 1280 ''', [MessageKind.UNDEFINED_SETTER]); | 1312 ''', |
| 1281 checkWarningOn(''' | 1313 [MessageKind.UNDEFINED_SETTER]); |
| 1314 checkWarningOn( |
| 1315 ''' |
| 1282 main() { new B().bar(); } | 1316 main() { new B().bar(); } |
| 1283 class B { | 1317 class B { |
| 1284 mname() {} | 1318 mname() {} |
| 1285 bar() { | 1319 bar() { |
| 1286 this.mname = () => null; | 1320 this.mname = () => null; |
| 1287 } | 1321 } |
| 1288 } | 1322 } |
| 1289 ''', [MessageKind.UNDEFINED_SETTER]); | 1323 ''', |
| 1324 [MessageKind.UNDEFINED_SETTER]); |
| 1290 | 1325 |
| 1291 // Can't override super methods | 1326 // Can't override super methods |
| 1292 checkWarningOn(''' | 1327 checkWarningOn( |
| 1328 ''' |
| 1293 main() { new B().bar(); } | 1329 main() { new B().bar(); } |
| 1294 class A { | 1330 class A { |
| 1295 mname() {} | 1331 mname() {} |
| 1296 } | 1332 } |
| 1297 class B extends A { | 1333 class B extends A { |
| 1298 bar() { | 1334 bar() { |
| 1299 super.mname = () => 6; | 1335 super.mname = () => 6; |
| 1300 } | 1336 } |
| 1301 } | 1337 } |
| 1302 ''', [MessageKind.ASSIGNING_METHOD_IN_SUPER, | 1338 ''', |
| 1303 // TODO(johnniwinther): Avoid duplicate warnings. | 1339 [ |
| 1304 MessageKind.UNDEFINED_SETTER]); | 1340 MessageKind.ASSIGNING_METHOD_IN_SUPER, |
| 1341 // TODO(johnniwinther): Avoid duplicate warnings. |
| 1342 MessageKind.UNDEFINED_SETTER |
| 1343 ]); |
| 1305 | 1344 |
| 1306 // But index operators should be OK | 1345 // But index operators should be OK |
| 1307 checkWarningOn(''' | 1346 checkWarningOn( |
| 1347 ''' |
| 1308 main() { new B().bar(); } | 1348 main() { new B().bar(); } |
| 1309 class B { | 1349 class B { |
| 1310 operator[]=(x, y) {} | 1350 operator[]=(x, y) {} |
| 1311 bar() { | 1351 bar() { |
| 1312 this[1] = 3; // This is OK | 1352 this[1] = 3; // This is OK |
| 1313 } | 1353 } |
| 1314 } | 1354 } |
| 1315 ''', []); | 1355 ''', |
| 1316 checkWarningOn(''' | 1356 []); |
| 1357 checkWarningOn( |
| 1358 ''' |
| 1317 main() { new B().bar(); } | 1359 main() { new B().bar(); } |
| 1318 class A { | 1360 class A { |
| 1319 operator[]=(x, y) {} | 1361 operator[]=(x, y) {} |
| 1320 } | 1362 } |
| 1321 class B extends A { | 1363 class B extends A { |
| 1322 bar() { | 1364 bar() { |
| 1323 super[1] = 3; // This is OK | 1365 super[1] = 3; // This is OK |
| 1324 } | 1366 } |
| 1325 } | 1367 } |
| 1326 ''', []); | 1368 ''', |
| 1369 []); |
| 1327 } | 1370 } |
| 1328 | 1371 |
| 1329 testCantAssignFinalAndConsts() { | 1372 testCantAssignFinalAndConsts() { |
| 1330 // Can't write final or const locals. | 1373 // Can't write final or const locals. |
| 1331 checkWarningOn(''' | 1374 checkWarningOn( |
| 1375 ''' |
| 1332 main() { | 1376 main() { |
| 1333 final x = 1; | 1377 final x = 1; |
| 1334 x = 2; | 1378 x = 2; |
| 1335 } | 1379 } |
| 1336 ''', [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); | 1380 ''', |
| 1337 checkWarningOn(''' | 1381 [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); |
| 1382 checkWarningOn( |
| 1383 ''' |
| 1338 main() { | 1384 main() { |
| 1339 const x = 1; | 1385 const x = 1; |
| 1340 x = 2; | 1386 x = 2; |
| 1341 } | 1387 } |
| 1342 ''', [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); | 1388 ''', |
| 1343 checkWarningOn(''' | 1389 [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); |
| 1390 checkWarningOn( |
| 1391 ''' |
| 1344 final x = 1; | 1392 final x = 1; |
| 1345 main() { x = 3; } | 1393 main() { x = 3; } |
| 1346 ''', [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); | 1394 ''', |
| 1395 [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); |
| 1347 | 1396 |
| 1348 checkWarningOn(''' | 1397 checkWarningOn( |
| 1398 ''' |
| 1349 const x = 1; | 1399 const x = 1; |
| 1350 main() { x = 3; } | 1400 main() { x = 3; } |
| 1351 ''', [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); | 1401 ''', |
| 1402 [MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER]); |
| 1352 | 1403 |
| 1353 // Detect assignments to final fields: | 1404 // Detect assignments to final fields: |
| 1354 checkWarningOn(''' | 1405 checkWarningOn( |
| 1406 ''' |
| 1355 main() => new B().m(); | 1407 main() => new B().m(); |
| 1356 class B { | 1408 class B { |
| 1357 final x = 1; | 1409 final x = 1; |
| 1358 m() { x = 2; } | 1410 m() { x = 2; } |
| 1359 } | 1411 } |
| 1360 ''', [MessageKind.UNDEFINED_SETTER]); | 1412 ''', |
| 1413 [MessageKind.UNDEFINED_SETTER]); |
| 1361 | 1414 |
| 1362 // ... even if 'this' is explicit: | 1415 // ... even if 'this' is explicit: |
| 1363 checkWarningOn(''' | 1416 checkWarningOn( |
| 1417 ''' |
| 1364 main() => new B().m(); | 1418 main() => new B().m(); |
| 1365 class B { | 1419 class B { |
| 1366 final x = 1; | 1420 final x = 1; |
| 1367 m() { this.x = 2; } | 1421 m() { this.x = 2; } |
| 1368 } | 1422 } |
| 1369 ''', [MessageKind.UNDEFINED_SETTER]); | 1423 ''', |
| 1424 [MessageKind.UNDEFINED_SETTER]); |
| 1370 | 1425 |
| 1371 // ... and in super class: | 1426 // ... and in super class: |
| 1372 checkWarningOn(''' | 1427 checkWarningOn( |
| 1428 ''' |
| 1373 main() => new B().m(); | 1429 main() => new B().m(); |
| 1374 class A { | 1430 class A { |
| 1375 final x = 1; | 1431 final x = 1; |
| 1376 } | 1432 } |
| 1377 class B extends A { | 1433 class B extends A { |
| 1378 m() { super.x = 2; } | 1434 m() { super.x = 2; } |
| 1379 } | 1435 } |
| 1380 ''', [MessageKind.ASSIGNING_FINAL_FIELD_IN_SUPER, | 1436 ''', |
| 1381 // TODO(johnniwinther): Avoid duplicate warnings. | 1437 [ |
| 1382 MessageKind.UNDEFINED_SETTER]); | 1438 MessageKind.ASSIGNING_FINAL_FIELD_IN_SUPER, |
| 1439 // TODO(johnniwinther): Avoid duplicate warnings. |
| 1440 MessageKind.UNDEFINED_SETTER |
| 1441 ]); |
| 1383 | 1442 |
| 1384 // But non-final fields are OK: | 1443 // But non-final fields are OK: |
| 1385 checkWarningOn(''' | 1444 checkWarningOn( |
| 1445 ''' |
| 1386 main() => new B().m(); | 1446 main() => new B().m(); |
| 1387 class A { | 1447 class A { |
| 1388 int x = 1; | 1448 int x = 1; |
| 1389 } | 1449 } |
| 1390 class B extends A { | 1450 class B extends A { |
| 1391 m() { super.x = 2; } | 1451 m() { super.x = 2; } |
| 1392 } | 1452 } |
| 1393 ''', []); | 1453 ''', |
| 1454 []); |
| 1394 | 1455 |
| 1395 // Check getter without setter. | 1456 // Check getter without setter. |
| 1396 checkWarningOn(''' | 1457 checkWarningOn( |
| 1458 ''' |
| 1397 main() => new B().m(); | 1459 main() => new B().m(); |
| 1398 class A { | 1460 class A { |
| 1399 get x => 1; | 1461 get x => 1; |
| 1400 } | 1462 } |
| 1401 class B extends A { | 1463 class B extends A { |
| 1402 m() { super.x = 2; } | 1464 m() { super.x = 2; } |
| 1403 } | 1465 } |
| 1404 ''', [MessageKind.UNDEFINED_SUPER_SETTER, | 1466 ''', |
| 1405 // TODO(johnniwinther): Avoid duplicate warnings. | 1467 [ |
| 1406 MessageKind.UNDEFINED_SETTER]); | 1468 MessageKind.UNDEFINED_SUPER_SETTER, |
| 1469 // TODO(johnniwinther): Avoid duplicate warnings. |
| 1470 MessageKind.UNDEFINED_SETTER |
| 1471 ]); |
| 1407 } | 1472 } |
| 1408 | 1473 |
| 1409 /// Helper to test that [script] produces all the given [warnings]. | 1474 /// Helper to test that [script] produces all the given [warnings]. |
| 1410 checkWarningOn(String script, List<MessageKind> warnings) { | 1475 checkWarningOn(String script, List<MessageKind> warnings) { |
| 1411 Expect.isTrue(warnings.length >= 0 && warnings.length <= 2); | 1476 Expect.isTrue(warnings.length >= 0 && warnings.length <= 2); |
| 1412 asyncTest(() => compileScript(script).then((compiler) { | 1477 asyncTest(() => compileScript(script).then((compiler) { |
| 1413 DiagnosticCollector collector = compiler.diagnosticCollector; | 1478 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 1414 Expect.equals(0, collector.errors.length, | 1479 Expect.equals(0, collector.errors.length, |
| 1415 'Unexpected errors in\n$script\n${collector.errors}'); | 1480 'Unexpected errors in\n$script\n${collector.errors}'); |
| 1416 Expect.equals(warnings.length, collector.warnings.length, | 1481 Expect.equals( |
| 1417 'Unexpected warnings in\n$script\n' | 1482 warnings.length, |
| 1418 'Expected:$warnings\nFound:${collector.warnings}'); | 1483 collector.warnings.length, |
| 1419 for (int i = 0; i < warnings.length; i++) { | 1484 'Unexpected warnings in\n$script\n' |
| 1420 Expect.equals(warnings[i], collector.warnings.elementAt(i).message.kind); | 1485 'Expected:$warnings\nFound:${collector.warnings}'); |
| 1421 } | 1486 for (int i = 0; i < warnings.length; i++) { |
| 1422 })); | 1487 Expect.equals( |
| 1488 warnings[i], collector.warnings.elementAt(i).message.kind); |
| 1489 } |
| 1490 })); |
| 1423 } | 1491 } |
| 1424 | 1492 |
| 1425 testAwaitHint() { | 1493 testAwaitHint() { |
| 1426 check(String script, {String className, String functionName}) { | 1494 check(String script, {String className, String functionName}) { |
| 1427 var prefix = className == null | 1495 var prefix = className == null |
| 1428 ? "Cannot resolve 'await'" | 1496 ? "Cannot resolve 'await'" |
| 1429 : "No member named 'await' in class '$className'"; | 1497 : "No member named 'await' in class '$className'"; |
| 1430 var where = functionName == null | 1498 var where = |
| 1431 ? 'the enclosing function' : "'$functionName'"; | 1499 functionName == null ? 'the enclosing function' : "'$functionName'"; |
| 1432 asyncTest(() => compileScript(script).then((compiler) { | 1500 asyncTest(() => compileScript(script).then((compiler) { |
| 1433 DiagnosticCollector collector = compiler.diagnosticCollector; | 1501 DiagnosticCollector collector = compiler.diagnosticCollector; |
| 1434 Expect.equals(0, collector.errors.length); | 1502 Expect.equals(0, collector.errors.length); |
| 1435 Expect.equals(1, collector.warnings.length); | 1503 Expect.equals(1, collector.warnings.length); |
| 1436 Expect.equals("$prefix.\n" | 1504 Expect.equals( |
| 1437 "Did you mean to add the 'async' marker to $where?", | 1505 "$prefix.\n" |
| 1438 '${collector.warnings.first.message}'); | 1506 "Did you mean to add the 'async' marker to $where?", |
| 1439 })); | 1507 '${collector.warnings.first.message}'); |
| 1508 })); |
| 1440 } | 1509 } |
| 1510 |
| 1441 check('main() { await -3; }', functionName: 'main'); | 1511 check('main() { await -3; }', functionName: 'main'); |
| 1442 check('main() { () => await -3; }'); | 1512 check('main() { () => await -3; }'); |
| 1443 check('foo() => await -3; main() => foo();', functionName: 'foo'); | 1513 check('foo() => await -3; main() => foo();', functionName: 'foo'); |
| 1444 check(''' | 1514 check( |
| 1515 ''' |
| 1445 class A { | 1516 class A { |
| 1446 m() => await - 3; | 1517 m() => await - 3; |
| 1447 } | 1518 } |
| 1448 main() => new A().m(); | 1519 main() => new A().m(); |
| 1449 ''', className: 'A', functionName: 'm'); | 1520 ''', |
| 1450 check(''' | 1521 className: 'A', |
| 1522 functionName: 'm'); |
| 1523 check( |
| 1524 ''' |
| 1451 class A { | 1525 class A { |
| 1452 static m() => await - 3; | 1526 static m() => await - 3; |
| 1453 } | 1527 } |
| 1454 main() => A.m(); | 1528 main() => A.m(); |
| 1455 ''', functionName: 'm'); | 1529 ''', |
| 1456 check(''' | 1530 functionName: 'm'); |
| 1531 check( |
| 1532 ''' |
| 1457 class A { | 1533 class A { |
| 1458 m() => () => await - 3; | 1534 m() => () => await - 3; |
| 1459 } | 1535 } |
| 1460 main() => new A().m(); | 1536 main() => new A().m(); |
| 1461 ''', className: 'A'); | 1537 ''', |
| 1538 className: 'A'); |
| 1462 } | 1539 } |
| OLD | NEW |