| 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 "package:expect/expect.dart"; | 5 import "package:expect/expect.dart"; |
| 6 import 'dart:async'; | 6 import 'dart:async'; |
| 7 import "package:async_helper/async_helper.dart"; | 7 import "package:async_helper/async_helper.dart"; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import "../../../sdk/lib/_internal/compiler/implementation/resolution/resolution
.dart"; | 10 import "../../../sdk/lib/_internal/compiler/implementation/resolution/resolution
.dart"; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 if (init) { | 28 if (init) { |
| 29 locals.add(buildInitialization(name)); | 29 locals.add(buildInitialization(name)); |
| 30 } else { | 30 } else { |
| 31 locals.add(buildIdentifier(name)); | 31 locals.add(buildIdentifier(name)); |
| 32 } | 32 } |
| 33 } | 33 } |
| 34 var definitions = new NodeList(null, new Link.fromList(locals), null, null); | 34 var definitions = new NodeList(null, new Link.fromList(locals), null, null); |
| 35 return new VariableDefinitions(null, Modifiers.EMPTY, definitions); | 35 return new VariableDefinitions(null, Modifiers.EMPTY, definitions); |
| 36 } | 36 } |
| 37 | 37 |
| 38 testLocals(List variables) { | 38 Future testLocals(List variables) { |
| 39 MockCompiler compiler = new MockCompiler(); | 39 return MockCompiler.create((MockCompiler compiler) { |
| 40 ResolverVisitor visitor = compiler.resolverVisitor(); | 40 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 41 Element element = visitor.visit(createLocals(variables)); | 41 Element element = visitor.visit(createLocals(variables)); |
| 42 // A VariableDefinitions does not have an element. | 42 // A VariableDefinitions does not have an element. |
| 43 Expect.equals(null, element); | 43 Expect.equals(null, element); |
| 44 Expect.equals(variables.length, map(visitor).length); | 44 Expect.equals(variables.length, map(visitor).length); |
| 45 | 45 |
| 46 for (final variable in variables) { | 46 for (final variable in variables) { |
| 47 final name = variable[0]; | 47 final name = variable[0]; |
| 48 Identifier id = buildIdentifier(name); | 48 Identifier id = buildIdentifier(name); |
| 49 final VariableElement variableElement = visitor.visit(id); | 49 final VariableElement variableElement = visitor.visit(id); |
| 50 MethodScope scope = visitor.scope; | 50 MethodScope scope = visitor.scope; |
| 51 Expect.equals(variableElement, scope.elements[name]); | 51 Expect.equals(variableElement, scope.elements[name]); |
| 52 } | 52 } |
| 53 return compiler; | 53 return compiler; |
| 54 }); |
| 54 } | 55 } |
| 55 | 56 |
| 56 main() { | 57 main() { |
| 57 testLocalsOne(); | 58 asyncTest(() => Future.forEach([ |
| 58 testLocalsTwo(); | 59 testLocalsOne, |
| 59 testLocalsThree(); | 60 testLocalsTwo, |
| 60 testLocalsFour(); | 61 testLocalsThree, |
| 61 testLocalsFive(); | 62 testLocalsFour, |
| 62 testParametersOne(); | 63 testLocalsFive, |
| 63 testFor(); | 64 testParametersOne, |
| 64 testTypeAnnotation(); | 65 testFor, |
| 65 testSuperclass(); | 66 testTypeAnnotation, |
| 66 // testVarSuperclass(); // The parser crashes with 'class Foo extends var'. | 67 testSuperclass, |
| 67 // testOneInterface(); // Generates unexpected error message. | 68 // testVarSuperclass, // The parser crashes with 'class Foo extends var'. |
| 68 // testTwoInterfaces(); // Generates unexpected error message. | 69 // testOneInterface, // Generates unexpected error message. |
| 69 testFunctionExpression(); | 70 // testTwoInterfaces, // Generates unexpected error message. |
| 70 testNewExpression(); | 71 testFunctionExpression, |
| 71 testTopLevelFields(); | 72 testNewExpression, |
| 72 testClassHierarchy(); | 73 testTopLevelFields, |
| 73 testInitializers(); | 74 testClassHierarchy, |
| 74 testThis(); | 75 testInitializers, |
| 75 testSuperCalls(); | 76 testThis, |
| 76 testSwitch(); | 77 testSuperCalls, |
| 77 testTypeVariables(); | 78 testSwitch, |
| 78 testToString(); | 79 testTypeVariables, |
| 79 testIndexedOperator(); | 80 testToString, |
| 80 testIncrementsAndDecrements(); | 81 testIndexedOperator, |
| 81 testOverrideHashCodeCheck(); | 82 testIncrementsAndDecrements, |
| 82 testSupertypeOrder(); | 83 testOverrideHashCodeCheck, |
| 83 testConstructorArgumentMismatch(); | 84 testSupertypeOrder, |
| 84 testConstConstructorAndNonFinalFields(); | 85 testConstructorArgumentMismatch, |
| 86 testConstConstructorAndNonFinalFields, |
| 87 ], (f) => f())); |
| 85 } | 88 } |
| 86 | 89 |
| 87 testSupertypeOrder() { | 90 Future testSupertypeOrder() { |
| 88 MockCompiler compiler = new MockCompiler(); | 91 return Future.wait([ |
| 89 compiler.parseScript(""" | 92 MockCompiler.create((MockCompiler compiler) { |
| 93 compiler.parseScript(""" |
| 90 class I1 {} | 94 class I1 {} |
| 91 class I2 {} | 95 class I2 {} |
| 92 class J1 extends K1 {} | 96 class J1 extends K1 {} |
| 93 class J2 implements K2 {} | 97 class J2 implements K2 {} |
| 94 class K1 {} | 98 class K1 {} |
| 95 class K2 {} | 99 class K2 {} |
| 96 class L1 {} | 100 class L1 {} |
| 97 class A implements I1, I2 {} | 101 class A implements I1, I2 {} |
| 98 class B extends A implements J1, J2 {} | 102 class B extends A implements J1, J2 {} |
| 99 class C extends B implements L1 {} | 103 class C extends B implements L1 {} |
| 100 """); | 104 """); |
| 101 compiler.resolveStatement("C c;"); | 105 compiler.resolveStatement("C c;"); |
| 102 ClassElement classA = compiler.mainApp.find("A"); | 106 ClassElement classA = compiler.mainApp.find("A"); |
| 103 ClassElement classB = compiler.mainApp.find("B"); | 107 ClassElement classB = compiler.mainApp.find("B"); |
| 104 ClassElement classC = compiler.mainApp.find("C"); | 108 ClassElement classC = compiler.mainApp.find("C"); |
| 105 Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString()); | 109 Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString()); |
| 106 Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]', | 110 Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]', |
| 107 classB.allSupertypes.toString()); | 111 classB.allSupertypes.toString()); |
| 108 Expect.equals('[ B, L1, A, J2, J1, I2, I1, K2, K1, Object ]', | 112 Expect.equals('[ B, L1, A, J2, J1, I2, I1, K2, K1, Object ]', |
| 109 classC.allSupertypes.toString()); | 113 classC.allSupertypes.toString()); |
| 110 | 114 }), |
| 111 compiler = new MockCompiler(); | 115 MockCompiler.create((MockCompiler compiler) { |
| 112 compiler.parseScript(""" | 116 compiler.parseScript(""" |
| 113 class X<T> {} | 117 class X<T> {} |
| 114 class Foo extends X<Foo> {} | 118 class Foo extends X<Foo> {} |
| 115 class Bar extends Foo implements X<Bar> {} | 119 class Bar extends Foo implements X<Bar> {} |
| 116 """); | 120 """); |
| 117 compiler.resolveStatement("Bar bar;"); | 121 compiler.resolveStatement("Bar bar;"); |
| 118 ClassElement classBar = compiler.mainApp.find("Bar"); | 122 ClassElement classBar = compiler.mainApp.find("Bar"); |
| 119 Expect.equals(0, compiler.warnings.length); | 123 Expect.equals(0, compiler.warnings.length); |
| 120 Expect.equals(1, compiler.errors.length); | 124 Expect.equals(1, compiler.errors.length); |
| 121 Expect.equals(MessageKind.MULTI_INHERITANCE, | 125 Expect.equals(MessageKind.MULTI_INHERITANCE, |
| 122 compiler.errors[0].message.kind); | 126 compiler.errors[0].message.kind); |
| 123 Expect.equals(0, compiler.crashes.length); | 127 Expect.equals(0, compiler.crashes.length); |
| 128 }), |
| 129 ]); |
| 124 } | 130 } |
| 125 | 131 |
| 126 testTypeVariables() { | 132 Future testTypeVariables() { |
| 127 matchResolvedTypes(visitor, text, name, expectedElements) { | 133 matchResolvedTypes(visitor, text, name, expectedElements) { |
| 128 VariableDefinitions definition = parseStatement(text); | 134 VariableDefinitions definition = parseStatement(text); |
| 129 visitor.visit(definition.type); | 135 visitor.visit(definition.type); |
| 130 InterfaceType type = visitor.registry.mapping.getType(definition.type); | 136 InterfaceType type = visitor.registry.mapping.getType(definition.type); |
| 131 Expect.equals(definition.type.typeArguments.slowLength(), | 137 Expect.equals(definition.type.typeArguments.slowLength(), |
| 132 length(type.typeArguments)); | 138 length(type.typeArguments)); |
| 133 int index = 0; | 139 int index = 0; |
| 134 Link<DartType> arguments = type.typeArguments; | 140 Link<DartType> arguments = type.typeArguments; |
| 135 while (!arguments.isEmpty) { | 141 while (!arguments.isEmpty) { |
| 136 Expect.equals(true, index < expectedElements.length); | 142 Expect.equals(true, index < expectedElements.length); |
| 137 Expect.equals(expectedElements[index], arguments.head.element); | 143 Expect.equals(expectedElements[index], arguments.head.element); |
| 138 index++; | 144 index++; |
| 139 arguments = arguments.tail; | 145 arguments = arguments.tail; |
| 140 } | 146 } |
| 141 Expect.equals(index, expectedElements.length); | 147 Expect.equals(index, expectedElements.length); |
| 142 } | 148 } |
| 143 | 149 |
| 144 MockCompiler compiler = new MockCompiler(); | 150 return Future.wait([ |
| 145 ResolverVisitor visitor = compiler.resolverVisitor(); | 151 MockCompiler.create((MockCompiler compiler) { |
| 146 compiler.parseScript('class Foo<T, U> {}'); | 152 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 147 ClassElement foo = compiler.mainApp.find('Foo'); | 153 compiler.parseScript('class Foo<T, U> {}'); |
| 148 matchResolvedTypes(visitor, 'Foo<int, String> x;', 'Foo', | 154 ClassElement foo = compiler.mainApp.find('Foo'); |
| 149 [compiler.intClass, compiler.stringClass]); | 155 matchResolvedTypes(visitor, 'Foo<int, String> x;', 'Foo', |
| 150 matchResolvedTypes(visitor, 'Foo<Foo, Foo> x;', 'Foo', | 156 [compiler.intClass, compiler.stringClass]); |
| 151 [foo, foo]); | 157 matchResolvedTypes(visitor, 'Foo<Foo, Foo> x;', 'Foo', |
| 152 | 158 [foo, foo]); |
| 153 compiler = new MockCompiler(); | 159 }), |
| 154 compiler.parseScript('class Foo<T, U> {}'); | 160 |
| 155 compiler.resolveStatement('Foo<notype, int> x;'); | 161 MockCompiler.create((MockCompiler compiler) { |
| 156 Expect.equals(1, compiler.warnings.length); | 162 compiler.parseScript('class Foo<T, U> {}'); |
| 157 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, | 163 compiler.resolveStatement('Foo<notype, int> x;'); |
| 158 compiler.warnings[0].message.kind); | 164 Expect.equals(1, compiler.warnings.length); |
| 159 Expect.equals(0, compiler.errors.length); | 165 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, |
| 160 | 166 compiler.warnings[0].message.kind); |
| 161 compiler = new MockCompiler(); | 167 Expect.equals(0, compiler.errors.length); |
| 162 compiler.parseScript('class Foo<T, U> {}'); | 168 }), |
| 163 compiler.resolveStatement('var x = new Foo<notype, int>();'); | 169 |
| 164 Expect.equals(1, compiler.warnings.length); | 170 MockCompiler.create((MockCompiler compiler) { |
| 165 Expect.equals(0, compiler.errors.length); | 171 compiler.parseScript('class Foo<T, U> {}'); |
| 166 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, | 172 compiler.resolveStatement('var x = new Foo<notype, int>();'); |
| 167 compiler.warnings[0].message.kind); | 173 Expect.equals(1, compiler.warnings.length); |
| 168 | 174 Expect.equals(0, compiler.errors.length); |
| 169 compiler = new MockCompiler(); | 175 Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, |
| 170 compiler.parseScript('class Foo<T> {' | 176 compiler.warnings[0].message.kind); |
| 171 ' Foo<T> t;' | 177 }), |
| 172 ' foo(Foo<T> f) {}' | 178 |
| 173 ' bar() { g(Foo<T> f) {}; g(); }' | 179 MockCompiler.create((MockCompiler compiler) { |
| 174 '}'); | 180 compiler.parseScript('class Foo<T> {' |
| 175 foo = compiler.mainApp.find('Foo'); | 181 ' Foo<T> t;' |
| 176 foo.ensureResolved(compiler); | 182 ' foo(Foo<T> f) {}' |
| 177 foo.lookupLocalMember('t').computeType(compiler);; | 183 ' bar() { g(Foo<T> f) {}; g(); }' |
| 178 foo.lookupLocalMember('foo').computeType(compiler);; | 184 '}'); |
| 179 compiler.resolver.resolve(foo.lookupLocalMember('bar')); | 185 ClassElement foo = compiler.mainApp.find('Foo'); |
| 180 Expect.equals(0, compiler.warnings.length); | 186 foo.ensureResolved(compiler); |
| 181 Expect.equals(0, compiler.errors.length); | 187 foo.lookupLocalMember('t').computeType(compiler);; |
| 182 } | 188 foo.lookupLocalMember('foo').computeType(compiler);; |
| 183 | 189 compiler.resolver.resolve(foo.lookupLocalMember('bar')); |
| 184 testSuperCalls() { | 190 Expect.equals(0, compiler.warnings.length); |
| 185 MockCompiler compiler = new MockCompiler(); | 191 Expect.equals(0, compiler.errors.length); |
| 186 String script = """class A { foo() {} } | 192 }), |
| 187 class B extends A { foo() => super.foo(); }"""; | 193 ]); |
| 188 compiler.parseScript(script); | 194 } |
| 189 compiler.resolveStatement("B b;"); | 195 |
| 190 | 196 Future testSuperCalls() { |
| 191 ClassElement classB = compiler.mainApp.find("B"); | 197 return MockCompiler.create((MockCompiler compiler) { |
| 192 FunctionElement fooB = classB.lookupLocalMember("foo"); | 198 String script = """class A { foo() {} } |
| 193 ClassElement classA = compiler.mainApp.find("A"); | 199 class B extends A { foo() => super.foo(); }"""; |
| 194 FunctionElement fooA = classA.lookupLocalMember("foo"); | 200 compiler.parseScript(script); |
| 195 | 201 compiler.resolveStatement("B b;"); |
| 196 ResolverVisitor visitor = | 202 |
| 197 new ResolverVisitor(compiler, fooB, | 203 ClassElement classB = compiler.mainApp.find("B"); |
| 198 new ResolutionRegistry.internal(compiler, | 204 FunctionElement fooB = classB.lookupLocalMember("foo"); |
| 199 new CollectingTreeElements(fooB))); | 205 ClassElement classA = compiler.mainApp.find("A"); |
| 200 FunctionExpression node = fooB.parseNode(compiler); | 206 FunctionElement fooA = classA.lookupLocalMember("foo"); |
| 201 visitor.visit(node.body); | 207 |
| 202 Map mapping = map(visitor); | 208 ResolverVisitor visitor = |
| 203 | 209 new ResolverVisitor(compiler, fooB, |
| 204 Send superCall = node.body.asReturn().expression; | 210 new ResolutionRegistry.internal(compiler, |
| 205 FunctionElement called = mapping[superCall]; | 211 new CollectingTreeElements(fooB))); |
| 206 Expect.isNotNull(called); | 212 FunctionExpression node = fooB.parseNode(compiler); |
| 207 Expect.equals(fooA, called); | 213 visitor.visit(node.body); |
| 208 } | 214 Map mapping = map(visitor); |
| 209 | 215 |
| 210 testSwitch() { | 216 Send superCall = node.body.asReturn().expression; |
| 211 MockCompiler compiler = new MockCompiler(); | 217 FunctionElement called = mapping[superCall]; |
| 212 compiler.parseScript("class Foo { foo() {" | 218 Expect.isNotNull(called); |
| 213 "switch (null) { case '': break; case 2: break; } } }"); | 219 Expect.equals(fooA, called); |
| 214 compiler.resolveStatement("Foo foo;"); | 220 }); |
| 215 ClassElement fooElement = compiler.mainApp.find("Foo"); | 221 } |
| 216 FunctionElement funElement = fooElement.lookupLocalMember("foo"); | 222 |
| 217 compiler.processQueue(compiler.enqueuer.resolution, funElement); | 223 Future testSwitch() { |
| 218 Expect.equals(0, compiler.warnings.length); | 224 return MockCompiler.create((MockCompiler compiler) { |
| 219 Expect.equals(1, compiler.errors.length); | 225 compiler.parseScript("class Foo { foo() {" |
| 220 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL, | 226 "switch (null) { case '': break; case 2: break; } } }"); |
| 221 compiler.errors[0].message.kind); | 227 compiler.resolveStatement("Foo foo;"); |
| 222 Expect.equals(2, compiler.infos.length); | 228 ClassElement fooElement = compiler.mainApp.find("Foo"); |
| 223 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, | 229 FunctionElement funElement = fooElement.lookupLocalMember("foo"); |
| 224 compiler.infos[0].message.kind); | 230 compiler.processQueue(compiler.enqueuer.resolution, funElement); |
| 225 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, | 231 Expect.equals(0, compiler.warnings.length); |
| 226 compiler.infos[1].message.kind); | 232 Expect.equals(1, compiler.errors.length); |
| 227 } | 233 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL, |
| 228 | 234 compiler.errors[0].message.kind); |
| 229 testThis() { | 235 Expect.equals(2, compiler.infos.length); |
| 230 MockCompiler compiler = new MockCompiler(); | 236 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, |
| 231 compiler.parseScript("class Foo { foo() { return this; } }"); | 237 compiler.infos[0].message.kind); |
| 232 compiler.resolveStatement("Foo foo;"); | 238 Expect.equals(MessageKind.SWITCH_CASE_TYPES_NOT_EQUAL_CASE, |
| 233 ClassElement fooElement = compiler.mainApp.find("Foo"); | 239 compiler.infos[1].message.kind); |
| 234 FunctionElement funElement = fooElement.lookupLocalMember("foo"); | 240 }); |
| 235 ResolverVisitor visitor = | 241 } |
| 236 new ResolverVisitor(compiler, funElement, | 242 |
| 243 Future testThis() { |
| 244 return Future.wait([ |
| 245 MockCompiler.create((MockCompiler compiler) { |
| 246 compiler.parseScript("class Foo { foo() { return this; } }"); |
| 247 compiler.resolveStatement("Foo foo;"); |
| 248 ClassElement fooElement = compiler.mainApp.find("Foo"); |
| 249 FunctionElement funElement = fooElement.lookupLocalMember("foo"); |
| 250 ResolverVisitor visitor = |
| 251 new ResolverVisitor(compiler, funElement, |
| 252 new ResolutionRegistry.internal(compiler, |
| 253 new CollectingTreeElements(funElement))); |
| 254 FunctionExpression function = funElement.parseNode(compiler); |
| 255 visitor.visit(function.body); |
| 256 Map mapping = map(visitor); |
| 257 List<Element> values = mapping.values.toList(); |
| 258 Expect.equals(0, mapping.length); |
| 259 Expect.equals(0, compiler.warnings.length); |
| 260 }), |
| 261 MockCompiler.create((MockCompiler compiler) { |
| 262 compiler.resolveStatement("main() { return this; }"); |
| 263 Expect.equals(0, compiler.warnings.length); |
| 264 Expect.equals(1, compiler.errors.length); |
| 265 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, |
| 266 compiler.errors[0].message.kind); |
| 267 }), |
| 268 MockCompiler.create((MockCompiler compiler) { |
| 269 compiler.parseScript("class Foo { static foo() { return this; } }"); |
| 270 compiler.resolveStatement("Foo foo;"); |
| 271 ClassElement fooElement = compiler.mainApp.find("Foo"); |
| 272 FunctionElement funElement = fooElement.lookupLocalMember("foo"); |
| 273 ResolverVisitor visitor = new ResolverVisitor(compiler, funElement, |
| 237 new ResolutionRegistry.internal(compiler, | 274 new ResolutionRegistry.internal(compiler, |
| 238 new CollectingTreeElements(funElement))); | 275 new CollectingTreeElements(funElement))); |
| 239 FunctionExpression function = funElement.parseNode(compiler); | 276 FunctionExpression function = funElement.parseNode(compiler); |
| 240 visitor.visit(function.body); | 277 visitor.visit(function.body); |
| 241 Map mapping = map(visitor); | 278 Expect.equals(0, compiler.warnings.length); |
| 242 List<Element> values = mapping.values.toList(); | 279 Expect.equals(1, compiler.errors.length); |
| 243 Expect.equals(0, mapping.length); | 280 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, |
| 244 Expect.equals(0, compiler.warnings.length); | 281 compiler.errors[0].message.kind); |
| 245 | 282 }), |
| 246 compiler = new MockCompiler(); | 283 ]); |
| 247 compiler.resolveStatement("main() { return this; }"); | 284 } |
| 248 Expect.equals(0, compiler.warnings.length); | 285 |
| 249 Expect.equals(1, compiler.errors.length); | 286 Future testLocalsOne() { |
| 250 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, | 287 return Future.forEach([ |
| 251 compiler.errors[0].message.kind); | 288 () => testLocals([["foo", false]]), |
| 252 | 289 () => testLocals([["foo", false], ["bar", false]]), |
| 253 compiler = new MockCompiler(); | 290 () => testLocals([["foo", false], ["bar", false], ["foobar", false]]), |
| 254 compiler.parseScript("class Foo { static foo() { return this; } }"); | 291 |
| 255 compiler.resolveStatement("Foo foo;"); | 292 () => testLocals([["foo", true]]), |
| 256 fooElement = compiler.mainApp.find("Foo"); | 293 () => testLocals([["foo", false], ["bar", true]]), |
| 257 funElement = fooElement.lookupLocalMember("foo"); | 294 () => testLocals([["foo", true], ["bar", true]]), |
| 258 visitor = new ResolverVisitor(compiler, funElement, | 295 |
| 259 new ResolutionRegistry.internal(compiler, | 296 () => testLocals([["foo", false], ["bar", false], ["foobar", true]]), |
| 260 new CollectingTreeElements(funElement))); | 297 () => testLocals([["foo", false], ["bar", true], ["foobar", true]]), |
| 261 function = funElement.parseNode(compiler); | 298 () => testLocals([["foo", true], ["bar", true], ["foobar", true]]), |
| 262 visitor.visit(function.body); | 299 |
| 263 Expect.equals(0, compiler.warnings.length); | 300 () => testLocals([["foo", false], ["foo", false]]) |
| 264 Expect.equals(1, compiler.errors.length); | 301 .then((MockCompiler compiler) { |
| 265 Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, | 302 Expect.equals(1, compiler.errors.length); |
| 266 compiler.errors[0].message.kind); | 303 Expect.equals( |
| 267 } | 304 new Message(MessageKind.DUPLICATE_DEFINITION, {'name': 'foo'}, false), |
| 268 | 305 compiler.errors[0].message); |
| 269 testLocalsOne() { | 306 })], (f) => f()); |
| 270 testLocals([["foo", false]]); | 307 } |
| 271 testLocals([["foo", false], ["bar", false]]); | 308 |
| 272 testLocals([["foo", false], ["bar", false], ["foobar", false]]); | 309 |
| 273 | 310 Future testLocalsTwo() { |
| 274 testLocals([["foo", true]]); | 311 return MockCompiler.create((MockCompiler compiler) { |
| 275 testLocals([["foo", false], ["bar", true]]); | 312 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 276 testLocals([["foo", true], ["bar", true]]); | 313 Node tree = parseStatement("if (true) { var a = 1; var b = 2; }"); |
| 277 | 314 Element element = visitor.visit(tree); |
| 278 testLocals([["foo", false], ["bar", false], ["foobar", true]]); | 315 Expect.equals(null, element); |
| 279 testLocals([["foo", false], ["bar", true], ["foobar", true]]); | 316 MethodScope scope = visitor.scope; |
| 280 testLocals([["foo", true], ["bar", true], ["foobar", true]]); | 317 Expect.equals(0, scope.elements.length); |
| 281 | 318 Expect.equals(2, map(visitor).length); |
| 282 MockCompiler compiler = testLocals([["foo", false], ["foo", false]]); | 319 |
| 283 Expect.equals(1, compiler.errors.length); | 320 List<Element> elements = new List<Element>.from(map(visitor).values); |
| 284 Expect.equals( | 321 Expect.notEquals(elements[0], elements[1]); |
| 285 new Message(MessageKind.DUPLICATE_DEFINITION, {'name': 'foo'}, false), | 322 }); |
| 286 compiler.errors[0].message); | 323 } |
| 287 } | 324 |
| 288 | 325 Future testLocalsThree() { |
| 289 | 326 return MockCompiler.create((MockCompiler compiler) { |
| 290 testLocalsTwo() { | 327 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 291 MockCompiler compiler = new MockCompiler(); | 328 Node tree = parseStatement("{ var a = 1; if (true) { a; } }"); |
| 292 ResolverVisitor visitor = compiler.resolverVisitor(); | 329 Element element = visitor.visit(tree); |
| 293 Node tree = parseStatement("if (true) { var a = 1; var b = 2; }"); | 330 Expect.equals(null, element); |
| 294 Element element = visitor.visit(tree); | 331 MethodScope scope = visitor.scope; |
| 295 Expect.equals(null, element); | 332 Expect.equals(0, scope.elements.length); |
| 296 MethodScope scope = visitor.scope; | 333 Expect.equals(3, map(visitor).length); |
| 297 Expect.equals(0, scope.elements.length); | 334 List<Element> elements = map(visitor).values.toList(); |
| 298 Expect.equals(2, map(visitor).length); | 335 Expect.equals(elements[0], elements[1]); |
| 299 | 336 }); |
| 300 List<Element> elements = new List<Element>.from(map(visitor).values); | 337 } |
| 301 Expect.notEquals(elements[0], elements[1]); | 338 |
| 302 } | 339 Future testLocalsFour() { |
| 303 | 340 return MockCompiler.create((MockCompiler compiler) { |
| 304 testLocalsThree() { | 341 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 305 MockCompiler compiler = new MockCompiler(); | 342 Node tree = parseStatement("{ var a = 1; if (true) { var a = 1; } }"); |
| 306 ResolverVisitor visitor = compiler.resolverVisitor(); | 343 Element element = visitor.visit(tree); |
| 307 Node tree = parseStatement("{ var a = 1; if (true) { a; } }"); | 344 Expect.equals(null, element); |
| 308 Element element = visitor.visit(tree); | 345 MethodScope scope = visitor.scope; |
| 309 Expect.equals(null, element); | 346 Expect.equals(0, scope.elements.length); |
| 310 MethodScope scope = visitor.scope; | 347 Expect.equals(2, map(visitor).length); |
| 311 Expect.equals(0, scope.elements.length); | 348 List<Element> elements = map(visitor).values.toList(); |
| 312 Expect.equals(3, map(visitor).length); | 349 Expect.notEquals(elements[0], elements[1]); |
| 313 List<Element> elements = map(visitor).values.toList(); | 350 }); |
| 314 Expect.equals(elements[0], elements[1]); | 351 } |
| 315 } | 352 |
| 316 | 353 Future testLocalsFive() { |
| 317 testLocalsFour() { | 354 return MockCompiler.create((MockCompiler compiler) { |
| 318 MockCompiler compiler = new MockCompiler(); | 355 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 319 ResolverVisitor visitor = compiler.resolverVisitor(); | 356 If tree = |
| 320 Node tree = parseStatement("{ var a = 1; if (true) { var a = 1; } }"); | 357 parseStatement("if (true) { var a = 1; a; } else { var a = 2; a;}"); |
| 321 Element element = visitor.visit(tree); | 358 Element element = visitor.visit(tree); |
| 322 Expect.equals(null, element); | 359 Expect.equals(null, element); |
| 323 MethodScope scope = visitor.scope; | 360 MethodScope scope = visitor.scope; |
| 324 Expect.equals(0, scope.elements.length); | 361 Expect.equals(0, scope.elements.length); |
| 325 Expect.equals(2, map(visitor).length); | 362 Expect.equals(6, map(visitor).length); |
| 326 List<Element> elements = map(visitor).values.toList(); | 363 |
| 327 Expect.notEquals(elements[0], elements[1]); | 364 Block thenPart = tree.thenPart; |
| 328 } | 365 List statements1 = thenPart.statements.nodes.toList(); |
| 329 | 366 Node def1 = statements1[0].definitions.nodes.head; |
| 330 testLocalsFive() { | 367 Node id1 = statements1[1].expression; |
| 331 MockCompiler compiler = new MockCompiler(); | 368 Expect.equals(visitor.registry.mapping[def1], |
| 332 ResolverVisitor visitor = compiler.resolverVisitor(); | 369 visitor.registry.mapping[id1]); |
| 333 If tree = parseStatement("if (true) { var a = 1; a; } else { var a = 2; a;}"); | 370 |
| 334 Element element = visitor.visit(tree); | 371 Block elsePart = tree.elsePart; |
| 335 Expect.equals(null, element); | 372 List statements2 = elsePart.statements.nodes.toList(); |
| 336 MethodScope scope = visitor.scope; | 373 Node def2 = statements2[0].definitions.nodes.head; |
| 337 Expect.equals(0, scope.elements.length); | 374 Node id2 = statements2[1].expression; |
| 338 Expect.equals(6, map(visitor).length); | 375 Expect.equals(visitor.registry.mapping[def2], |
| 339 | 376 visitor.registry.mapping[id2]); |
| 340 Block thenPart = tree.thenPart; | 377 |
| 341 List statements1 = thenPart.statements.nodes.toList(); | 378 Expect.notEquals(visitor.registry.mapping[def1], |
| 342 Node def1 = statements1[0].definitions.nodes.head; | 379 visitor.registry.mapping[def2]); |
| 343 Node id1 = statements1[1].expression; | 380 Expect.notEquals(visitor.registry.mapping[id1], |
| 344 Expect.equals(visitor.registry.mapping[def1], visitor.registry.mapping[id1]); | 381 visitor.registry.mapping[id2]); |
| 345 | 382 }); |
| 346 Block elsePart = tree.elsePart; | 383 } |
| 347 List statements2 = elsePart.statements.nodes.toList(); | 384 |
| 348 Node def2 = statements2[0].definitions.nodes.head; | 385 Future testParametersOne() { |
| 349 Node id2 = statements2[1].expression; | 386 return MockCompiler.create((MockCompiler compiler) { |
| 350 Expect.equals(visitor.registry.mapping[def2], visitor.registry.mapping[id2]); | 387 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 351 | 388 FunctionExpression tree = |
| 352 Expect.notEquals(visitor.registry.mapping[def1], | 389 parseFunction("void foo(int a) { return a; }", compiler); |
| 353 visitor.registry.mapping[def2]); | 390 visitor.visit(tree); |
| 354 Expect.notEquals(visitor.registry.mapping[id1], | 391 |
| 355 visitor.registry.mapping[id2]); | 392 // Check that an element has been created for the parameter. |
| 356 } | 393 VariableDefinitions vardef = tree.parameters.nodes.head; |
| 357 | 394 Node param = vardef.definitions.nodes.head; |
| 358 testParametersOne() { | 395 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[param].kind); |
| 359 MockCompiler compiler = new MockCompiler(); | 396 |
| 360 ResolverVisitor visitor = compiler.resolverVisitor(); | 397 // Check that 'a' in 'return a' is resolved to the parameter. |
| 361 FunctionExpression tree = | 398 Block body = tree.body; |
| 362 parseFunction("void foo(int a) { return a; }", compiler); | 399 Return ret = body.statements.nodes.head; |
| 363 visitor.visit(tree); | 400 Send use = ret.expression; |
| 364 | 401 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[use].kind); |
| 365 // Check that an element has been created for the parameter. | 402 Expect.equals(visitor.registry.mapping[param], |
| 366 VariableDefinitions vardef = tree.parameters.nodes.head; | 403 visitor.registry.mapping[use]); |
| 367 Node param = vardef.definitions.nodes.head; | 404 }); |
| 368 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[param].kind); | 405 } |
| 369 | 406 |
| 370 // Check that 'a' in 'return a' is resolved to the parameter. | 407 Future testFor() { |
| 371 Block body = tree.body; | 408 return MockCompiler.create((MockCompiler compiler) { |
| 372 Return ret = body.statements.nodes.head; | 409 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 373 Send use = ret.expression; | 410 For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }"); |
| 374 Expect.equals(ElementKind.PARAMETER, visitor.registry.mapping[use].kind); | 411 visitor.visit(tree); |
| 375 Expect.equals(visitor.registry.mapping[param], visitor.registry.mapping[use]); | 412 |
| 376 } | 413 MethodScope scope = visitor.scope; |
| 377 | 414 Expect.equals(0, scope.elements.length); |
| 378 testFor() { | 415 Expect.equals(10, map(visitor).length); |
| 379 MockCompiler compiler = new MockCompiler(); | 416 |
| 380 ResolverVisitor visitor = compiler.resolverVisitor(); | 417 VariableDefinitions initializer = tree.initializer; |
| 381 For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }"); | 418 Node iNode = initializer.definitions.nodes.head; |
| 382 visitor.visit(tree); | 419 Element iElement = visitor.registry.mapping[iNode]; |
| 383 | 420 |
| 384 MethodScope scope = visitor.scope; | 421 // Check that we have the expected nodes. This test relies on the mapping |
| 385 Expect.equals(0, scope.elements.length); | 422 // field to be a linked hash map (preserving insertion order). |
| 386 Expect.equals(10, map(visitor).length); | 423 Expect.isTrue(map(visitor) is LinkedHashMap); |
| 387 | 424 List<Node> nodes = map(visitor).keys.toList(); |
| 388 VariableDefinitions initializer = tree.initializer; | 425 List<Element> elements = map(visitor).values.toList(); |
| 389 Node iNode = initializer.definitions.nodes.head; | 426 |
| 390 Element iElement = visitor.registry.mapping[iNode]; | 427 |
| 391 | 428 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 392 // Check that we have the expected nodes. This test relies on the mapping | 429 // ^^^ |
| 393 // field to be a linked hash map (preserving insertion order). | 430 Expect.isTrue(nodes[0] is TypeAnnotation); |
| 394 Expect.isTrue(map(visitor) is LinkedHashMap); | 431 |
| 395 List<Node> nodes = map(visitor).keys.toList(); | 432 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 396 List<Element> elements = map(visitor).values.toList(); | 433 // ^^^^^ |
| 397 | 434 checkSendSet(iElement, nodes[1], elements[1]); |
| 398 | 435 |
| 399 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 436 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 400 // ^^^ | 437 // ^ |
| 401 Expect.isTrue(nodes[0] is TypeAnnotation); | 438 checkIdentifier(iElement, nodes[2], elements[2]); |
| 402 | 439 |
| 403 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 440 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 404 // ^^^^^ | 441 // ^ |
| 405 checkSendSet(iElement, nodes[1], elements[1]); | 442 checkSend(iElement, nodes[3], elements[3]); |
| 406 | 443 |
| 407 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 444 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 408 // ^ | 445 // ^ |
| 409 checkIdentifier(iElement, nodes[2], elements[2]); | 446 checkIdentifier(iElement, nodes[4], elements[4]); |
| 410 | 447 |
| 411 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 448 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 412 // ^ | 449 // ^ |
| 413 checkSend(iElement, nodes[3], elements[3]); | 450 checkIdentifier(iElement, nodes[5], elements[5]); |
| 414 | 451 |
| 415 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 452 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 416 // ^ | 453 // ^ |
| 417 checkIdentifier(iElement, nodes[4], elements[4]); | 454 checkSend(iElement, nodes[6], elements[6]); |
| 418 | 455 |
| 419 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 456 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 420 // ^ | 457 // ^^^^^^^^^ |
| 421 checkIdentifier(iElement, nodes[5], elements[5]); | 458 checkSendSet(iElement, nodes[7], elements[7]); |
| 422 | 459 |
| 423 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 460 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 424 // ^ | 461 // ^ |
| 425 checkSend(iElement, nodes[6], elements[6]); | 462 checkIdentifier(iElement, nodes[8], elements[8]); |
| 426 | 463 |
| 427 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | 464 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
| 428 // ^^^^^^^^^ | 465 // ^^^^^ |
| 429 checkSendSet(iElement, nodes[7], elements[7]); | 466 checkSendSet(iElement, nodes[9], elements[9]); |
| 430 | 467 }); |
| 431 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | |
| 432 // ^ | |
| 433 checkIdentifier(iElement, nodes[8], elements[8]); | |
| 434 | |
| 435 // for (int i = 0; i < 10; i = i + 1) { i = 5; }; | |
| 436 // ^^^^^ | |
| 437 checkSendSet(iElement, nodes[9], elements[9]); | |
| 438 } | 468 } |
| 439 | 469 |
| 440 checkIdentifier(Element expected, Node node, Element actual) { | 470 checkIdentifier(Element expected, Node node, Element actual) { |
| 441 Expect.isTrue(node is Identifier, node.toDebugString()); | 471 Expect.isTrue(node is Identifier, node.toDebugString()); |
| 442 Expect.equals(expected, actual); | 472 Expect.equals(expected, actual); |
| 443 } | 473 } |
| 444 | 474 |
| 445 checkSend(Element expected, Node node, Element actual) { | 475 checkSend(Element expected, Node node, Element actual) { |
| 446 Expect.isTrue(node is Send, node.toDebugString()); | 476 Expect.isTrue(node is Send, node.toDebugString()); |
| 447 Expect.isTrue(node is !SendSet, node.toDebugString()); | 477 Expect.isTrue(node is !SendSet, node.toDebugString()); |
| 448 Expect.equals(expected, actual); | 478 Expect.equals(expected, actual); |
| 449 } | 479 } |
| 450 | 480 |
| 451 checkSendSet(Element expected, Node node, Element actual) { | 481 checkSendSet(Element expected, Node node, Element actual) { |
| 452 Expect.isTrue(node is SendSet, node.toDebugString()); | 482 Expect.isTrue(node is SendSet, node.toDebugString()); |
| 453 Expect.equals(expected, actual); | 483 Expect.equals(expected, actual); |
| 454 } | 484 } |
| 455 | 485 |
| 456 testTypeAnnotation() { | 486 Future testTypeAnnotation() { |
| 457 MockCompiler compiler = new MockCompiler(); | 487 return MockCompiler.create((MockCompiler compiler) { |
| 458 String statement = "Foo bar;"; | 488 String statement = "Foo bar;"; |
| 459 | 489 |
| 460 // Test that we get a warning when Foo is not defined. | 490 // Test that we get a warning when Foo is not defined. |
| 461 Map mapping = compiler.resolveStatement(statement).map; | 491 Map mapping = compiler.resolveStatement(statement).map; |
| 462 | 492 |
| 463 Expect.equals(2, mapping.length); // Both Foo and bar have an element. | 493 Expect.equals(2, mapping.length); // Both Foo and bar have an element. |
| 464 Expect.equals(1, compiler.warnings.length); | 494 Expect.equals(1, compiler.warnings.length); |
| 465 | 495 |
| 466 Node warningNode = compiler.warnings[0].node; | 496 Node warningNode = compiler.warnings[0].node; |
| 467 | 497 |
| 468 Expect.equals( | 498 Expect.equals( |
| 469 new Message( | 499 new Message( |
| 470 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'Foo'}, false), | 500 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'Foo'}, false), |
| 471 compiler.warnings[0].message); | 501 compiler.warnings[0].message); |
| 472 VariableDefinitions definition = compiler.parsedTree; | 502 VariableDefinitions definition = compiler.parsedTree; |
| 473 Expect.equals(warningNode, definition.type); | 503 Expect.equals(warningNode, definition.type); |
| 474 compiler.clearMessages(); | 504 compiler.clearMessages(); |
| 475 | 505 |
| 476 // Test that there is no warning after defining Foo. | 506 // Test that there is no warning after defining Foo. |
| 477 compiler.parseScript("class Foo {}"); | 507 compiler.parseScript("class Foo {}"); |
| 478 mapping = compiler.resolveStatement(statement).map; | 508 mapping = compiler.resolveStatement(statement).map; |
| 479 Expect.equals(2, mapping.length); | 509 Expect.equals(2, mapping.length); |
| 480 Expect.equals(0, compiler.warnings.length); | 510 Expect.equals(0, compiler.warnings.length); |
| 481 | 511 |
| 482 // Test that 'var' does not create a warning. | 512 // Test that 'var' does not create a warning. |
| 483 mapping = compiler.resolveStatement("var foo;").map; | 513 mapping = compiler.resolveStatement("var foo;").map; |
| 484 Expect.equals(1, mapping.length); | 514 Expect.equals(1, mapping.length); |
| 485 Expect.equals(0, compiler.warnings.length); | 515 Expect.equals(0, compiler.warnings.length); |
| 486 } | 516 }); |
| 487 | 517 } |
| 488 testSuperclass() { | 518 |
| 489 MockCompiler compiler = new MockCompiler(); | 519 Future testSuperclass() { |
| 490 compiler.parseScript("class Foo extends Bar {}"); | 520 return Future.wait([ |
| 491 compiler.resolveStatement("Foo bar;"); | 521 MockCompiler.create((MockCompiler compiler) { |
| 492 Expect.equals(1, compiler.errors.length); | 522 compiler.parseScript("class Foo extends Bar {}"); |
| 493 var cannotResolveBar = new Message(MessageKind.CANNOT_EXTEND_MALFORMED, | 523 compiler.resolveStatement("Foo bar;"); |
| 494 {'typeName': 'Bar'}, false); | 524 Expect.equals(1, compiler.errors.length); |
| 495 Expect.equals(cannotResolveBar, compiler.errors[0].message); | 525 var cannotResolveBar = new Message(MessageKind.CANNOT_EXTEND_MALFORMED, |
| 496 compiler.clearMessages(); | 526 {'typeName': 'Bar'}, false); |
| 497 | 527 Expect.equals(cannotResolveBar, compiler.errors[0].message); |
| 498 compiler = new MockCompiler(); | 528 compiler.clearMessages(); |
| 499 compiler.parseScript("class Foo extends Bar {}"); | 529 }), |
| 500 compiler.parseScript("class Bar {}"); | 530 MockCompiler.create((MockCompiler compiler) { |
| 501 Map mapping = compiler.resolveStatement("Foo bar;").map; | 531 compiler.parseScript("class Foo extends Bar {}"); |
| 502 Expect.equals(2, mapping.length); | 532 compiler.parseScript("class Bar {}"); |
| 503 | 533 Map mapping = compiler.resolveStatement("Foo bar;").map; |
| 504 ClassElement fooElement = compiler.mainApp.find('Foo'); | 534 Expect.equals(2, mapping.length); |
| 505 ClassElement barElement = compiler.mainApp.find('Bar'); | 535 |
| 506 Expect.equals(barElement.computeType(compiler), | 536 ClassElement fooElement = compiler.mainApp.find('Foo'); |
| 507 fooElement.supertype); | 537 ClassElement barElement = compiler.mainApp.find('Bar'); |
| 508 Expect.isTrue(fooElement.interfaces.isEmpty); | 538 Expect.equals(barElement.computeType(compiler), |
| 509 Expect.isTrue(barElement.interfaces.isEmpty); | 539 fooElement.supertype); |
| 510 } | 540 Expect.isTrue(fooElement.interfaces.isEmpty); |
| 511 | 541 Expect.isTrue(barElement.interfaces.isEmpty); |
| 512 testVarSuperclass() { | 542 }), |
| 513 MockCompiler compiler = new MockCompiler(); | 543 ]); |
| 514 compiler.parseScript("class Foo extends var {}"); | 544 } |
| 515 compiler.resolveStatement("Foo bar;"); | 545 |
| 516 Expect.equals(1, compiler.errors.length); | 546 Future testVarSuperclass() { |
| 517 Expect.equals( | 547 return MockCompiler.create((MockCompiler compiler) { |
| 518 new Message( | 548 compiler.parseScript("class Foo extends var {}"); |
| 519 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'var'}, false), | 549 compiler.resolveStatement("Foo bar;"); |
| 520 compiler.errors[0].message); | 550 Expect.equals(1, compiler.errors.length); |
| 521 compiler.clearMessages(); | 551 Expect.equals( |
| 522 } | 552 new Message( |
| 523 | 553 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'var'}, false), |
| 524 testOneInterface() { | 554 compiler.errors[0].message); |
| 525 MockCompiler compiler = new MockCompiler(); | 555 compiler.clearMessages(); |
| 526 compiler.parseScript("class Foo implements Bar {}"); | 556 }); |
| 527 compiler.resolveStatement("Foo bar;"); | 557 } |
| 528 Expect.equals(1, compiler.errors.length); | 558 |
| 529 Expect.equals( | 559 Future testOneInterface() { |
| 530 new Message( | 560 return MockCompiler.create((MockCompiler compiler) { |
| 531 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'bar'}, false), | 561 compiler.parseScript("class Foo implements Bar {}"); |
| 532 compiler.errors[0].message); | 562 compiler.resolveStatement("Foo bar;"); |
| 533 compiler.clearMessages(); | 563 Expect.equals(1, compiler.errors.length); |
| 534 | 564 Expect.equals( |
| 535 // Add the abstract class to the world and make sure everything is setup | 565 new Message( |
| 536 // correctly. | 566 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': 'bar'}, false), |
| 537 compiler.parseScript("abstract class Bar {}"); | 567 compiler.errors[0].message); |
| 538 | 568 compiler.clearMessages(); |
| 539 ResolverVisitor visitor = | 569 |
| 540 new ResolverVisitor(compiler, null, | 570 // Add the abstract class to the world and make sure everything is setup |
| 541 new ResolutionRegistry.internal(compiler, | 571 // correctly. |
| 542 new CollectingTreeElements(null))); | 572 compiler.parseScript("abstract class Bar {}"); |
| 543 compiler.resolveStatement("Foo bar;"); | 573 |
| 544 | 574 ResolverVisitor visitor = |
| 545 ClassElement fooElement = compiler.mainApp.find('Foo'); | 575 new ResolverVisitor(compiler, null, |
| 546 ClassElement barElement = compiler.mainApp.find('Bar'); | 576 new ResolutionRegistry.internal(compiler, |
| 547 | 577 new CollectingTreeElements(null))); |
| 548 Expect.equals(null, barElement.supertype); | 578 compiler.resolveStatement("Foo bar;"); |
| 549 Expect.isTrue(barElement.interfaces.isEmpty); | 579 |
| 550 | 580 ClassElement fooElement = compiler.mainApp.find('Foo'); |
| 551 Expect.equals(barElement.computeType(compiler), | 581 ClassElement barElement = compiler.mainApp.find('Bar'); |
| 552 fooElement.interfaces.head); | 582 |
| 553 Expect.equals(1, length(fooElement.interfaces)); | 583 Expect.equals(null, barElement.supertype); |
| 554 } | 584 Expect.isTrue(barElement.interfaces.isEmpty); |
| 555 | 585 |
| 556 testTwoInterfaces() { | 586 Expect.equals(barElement.computeType(compiler), |
| 557 MockCompiler compiler = new MockCompiler(); | 587 fooElement.interfaces.head); |
| 558 compiler.parseScript( | 588 Expect.equals(1, length(fooElement.interfaces)); |
| 559 "abstract class I1 {} abstract class I2 {} class C implements I1, I2 {}"); | 589 }); |
| 560 compiler.resolveStatement("Foo bar;"); | 590 } |
| 561 | 591 |
| 562 ClassElement c = compiler.mainApp.find('C'); | 592 Future testTwoInterfaces() { |
| 563 Element i1 = compiler.mainApp.find('I1'); | 593 return MockCompiler.create((MockCompiler compiler) { |
| 564 Element i2 = compiler.mainApp.find('I2'); | 594 compiler.parseScript( |
| 565 | 595 """abstract class I1 {} |
| 566 Expect.equals(2, length(c.interfaces)); | 596 abstract class I2 {} |
| 567 Expect.equals(i1.computeType(compiler), at(c.interfaces, 0)); | 597 class C implements I1, I2 {}"""); |
| 568 Expect.equals(i2.computeType(compiler), at(c.interfaces, 1)); | 598 compiler.resolveStatement("Foo bar;"); |
| 569 } | 599 |
| 570 | 600 ClassElement c = compiler.mainApp.find('C'); |
| 571 testFunctionExpression() { | 601 Element i1 = compiler.mainApp.find('I1'); |
| 572 MockCompiler compiler = new MockCompiler(); | 602 Element i2 = compiler.mainApp.find('I2'); |
| 573 ResolverVisitor visitor = compiler.resolverVisitor(); | 603 |
| 574 Map mapping = compiler.resolveStatement("int f() {}").map; | 604 Expect.equals(2, length(c.interfaces)); |
| 575 Expect.equals(3, mapping.length); | 605 Expect.equals(i1.computeType(compiler), at(c.interfaces, 0)); |
| 576 Element element; | 606 Expect.equals(i2.computeType(compiler), at(c.interfaces, 1)); |
| 577 Node node; | 607 }); |
| 578 mapping.forEach((Node n, Element e) { | 608 } |
| 579 if (n is FunctionExpression) { | 609 |
| 580 element = e; | 610 Future testFunctionExpression() { |
| 581 node = n; | 611 return MockCompiler.create((MockCompiler compiler) { |
| 612 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 613 Map mapping = compiler.resolveStatement("int f() {}").map; |
| 614 Expect.equals(3, mapping.length); |
| 615 Element element; |
| 616 Node node; |
| 617 mapping.forEach((Node n, Element e) { |
| 618 if (n is FunctionExpression) { |
| 619 element = e; |
| 620 node = n; |
| 621 } |
| 622 }); |
| 623 Expect.equals(ElementKind.FUNCTION, element.kind); |
| 624 Expect.equals('f', element.name); |
| 625 Expect.equals(element.parseNode(compiler), node); |
| 626 }); |
| 627 } |
| 628 |
| 629 Future testNewExpression() { |
| 630 return MockCompiler.create((MockCompiler compiler) { |
| 631 compiler.parseScript("class A {} foo() { print(new A()); }"); |
| 632 ClassElement aElement = compiler.mainApp.find('A'); |
| 633 FunctionElement fooElement = compiler.mainApp.find('foo'); |
| 634 Expect.isNotNull(aElement); |
| 635 Expect.isNotNull(fooElement); |
| 636 |
| 637 fooElement.parseNode(compiler); |
| 638 compiler.resolver.resolve(fooElement); |
| 639 |
| 640 TreeElements elements = compiler.resolveStatement("new A();"); |
| 641 NewExpression expression = |
| 642 compiler.parsedTree.asExpressionStatement().expression; |
| 643 Element element = elements[expression.send]; |
| 644 Expect.equals(ElementKind.GENERATIVE_CONSTRUCTOR, element.kind); |
| 645 Expect.isTrue(element.isSynthesized); |
| 646 }); |
| 647 } |
| 648 |
| 649 Future testConstructorArgumentMismatch() { |
| 650 return MockCompiler.create((MockCompiler compiler) { |
| 651 String script = "class A {} foo() { print(new A(42)); }"; |
| 652 compiler.parseScript(script); |
| 653 FunctionElement fooElement = compiler.mainApp.find('foo'); |
| 654 Expect.isNotNull(fooElement); |
| 655 fooElement.parseNode(compiler); |
| 656 compiler.resolver.resolve(fooElement); |
| 657 |
| 658 compareWarningKinds( |
| 659 script, [MessageKind.INVALID_ARGUMENTS], compiler.warnings); |
| 660 compareWarningKinds(script, [], compiler.errors); |
| 661 }); |
| 662 } |
| 663 |
| 664 Future testTopLevelFields() { |
| 665 return MockCompiler.create((MockCompiler compiler) { |
| 666 compiler.parseScript("int a;"); |
| 667 VariableElementX element = compiler.mainApp.find("a"); |
| 668 Expect.equals(ElementKind.FIELD, element.kind); |
| 669 VariableDefinitions node = element.variables.parseNode(element, compiler); |
| 670 Identifier typeName = node.type.typeName; |
| 671 Expect.equals(typeName.source, 'int'); |
| 672 |
| 673 compiler.parseScript("var b, c;"); |
| 674 VariableElementX bElement = compiler.mainApp.find("b"); |
| 675 VariableElementX cElement = compiler.mainApp.find("c"); |
| 676 Expect.equals(ElementKind.FIELD, bElement.kind); |
| 677 Expect.equals(ElementKind.FIELD, cElement.kind); |
| 678 Expect.isTrue(bElement != cElement); |
| 679 |
| 680 VariableDefinitions bNode = bElement.variables.parseNode(bElement, compiler)
; |
| 681 VariableDefinitions cNode = cElement.variables.parseNode(cElement, compiler)
; |
| 682 Expect.equals(bNode, cNode); |
| 683 Expect.isNull(bNode.type); |
| 684 Expect.isTrue(bNode.modifiers.isVar); |
| 685 }); |
| 686 } |
| 687 |
| 688 Future resolveConstructor( |
| 689 String script, String statement, String className, |
| 690 String constructor, int expectedElementCount, |
| 691 {List expectedWarnings: const [], |
| 692 List expectedErrors: const [], |
| 693 List expectedInfos: const [], |
| 694 String corelib: DEFAULT_CORELIB}) { |
| 695 MockCompiler compiler = new MockCompiler.internal(coreSource: corelib); |
| 696 return compiler.init().then((_) { |
| 697 compiler.parseScript(script); |
| 698 compiler.resolveStatement(statement); |
| 699 ClassElement classElement = compiler.mainApp.find(className); |
| 700 Element element; |
| 701 if (constructor != '') { |
| 702 element = classElement.lookupConstructor( |
| 703 new Selector.callConstructor(constructor, classElement.library)); |
| 704 } else { |
| 705 element = classElement.lookupConstructor( |
| 706 new Selector.callDefaultConstructor(classElement.library)); |
| 582 } | 707 } |
| 583 }); | 708 |
| 584 Expect.equals(ElementKind.FUNCTION, element.kind); | 709 FunctionExpression tree = element.parseNode(compiler); |
| 585 Expect.equals('f', element.name); | 710 ResolverVisitor visitor = |
| 586 Expect.equals(element.parseNode(compiler), node); | 711 new ResolverVisitor(compiler, element, |
| 587 } | 712 new ResolutionRegistry.internal(compiler, |
| 588 | 713 new CollectingTreeElements(element))); |
| 589 testNewExpression() { | 714 new InitializerResolver(visitor).resolveInitializers(element, tree); |
| 590 MockCompiler compiler = new MockCompiler(); | 715 visitor.visit(tree.body); |
| 591 compiler.parseScript("class A {} foo() { print(new A()); }"); | 716 Expect.equals(expectedElementCount, map(visitor).length); |
| 592 ClassElement aElement = compiler.mainApp.find('A'); | 717 |
| 593 FunctionElement fooElement = compiler.mainApp.find('foo'); | 718 compareWarningKinds(script, expectedWarnings, compiler.warnings); |
| 594 Expect.isNotNull(aElement); | 719 compareWarningKinds(script, expectedErrors, compiler.errors); |
| 595 Expect.isNotNull(fooElement); | 720 compareWarningKinds(script, expectedInfos, compiler.infos); |
| 596 | 721 }); |
| 597 fooElement.parseNode(compiler); | 722 } |
| 598 compiler.resolver.resolve(fooElement); | 723 |
| 599 | 724 Future testClassHierarchy() { |
| 600 TreeElements elements = compiler.resolveStatement("new A();"); | |
| 601 NewExpression expression = | |
| 602 compiler.parsedTree.asExpressionStatement().expression; | |
| 603 Element element = elements[expression.send]; | |
| 604 Expect.equals(ElementKind.GENERATIVE_CONSTRUCTOR, element.kind); | |
| 605 Expect.isTrue(element.isSynthesized); | |
| 606 } | |
| 607 | |
| 608 testConstructorArgumentMismatch() { | |
| 609 String script = "class A {} foo() { print(new A(42)); }"; | |
| 610 MockCompiler compiler = new MockCompiler(); | |
| 611 compiler.parseScript(script); | |
| 612 FunctionElement fooElement = compiler.mainApp.find('foo'); | |
| 613 Expect.isNotNull(fooElement); | |
| 614 fooElement.parseNode(compiler); | |
| 615 compiler.resolver.resolve(fooElement); | |
| 616 | |
| 617 compareWarningKinds( | |
| 618 script, [MessageKind.INVALID_ARGUMENTS], compiler.warnings); | |
| 619 compareWarningKinds(script, [], compiler.errors); | |
| 620 } | |
| 621 | |
| 622 testTopLevelFields() { | |
| 623 MockCompiler compiler = new MockCompiler(); | |
| 624 compiler.parseScript("int a;"); | |
| 625 VariableElementX element = compiler.mainApp.find("a"); | |
| 626 Expect.equals(ElementKind.FIELD, element.kind); | |
| 627 VariableDefinitions node = element.variables.parseNode(element, compiler); | |
| 628 Identifier typeName = node.type.typeName; | |
| 629 Expect.equals(typeName.source, 'int'); | |
| 630 | |
| 631 compiler.parseScript("var b, c;"); | |
| 632 VariableElementX bElement = compiler.mainApp.find("b"); | |
| 633 VariableElementX cElement = compiler.mainApp.find("c"); | |
| 634 Expect.equals(ElementKind.FIELD, bElement.kind); | |
| 635 Expect.equals(ElementKind.FIELD, cElement.kind); | |
| 636 Expect.isTrue(bElement != cElement); | |
| 637 | |
| 638 VariableDefinitions bNode = bElement.variables.parseNode(bElement, compiler); | |
| 639 VariableDefinitions cNode = cElement.variables.parseNode(cElement, compiler); | |
| 640 Expect.equals(bNode, cNode); | |
| 641 Expect.isNull(bNode.type); | |
| 642 Expect.isTrue(bNode.modifiers.isVar); | |
| 643 } | |
| 644 | |
| 645 resolveConstructor(String script, String statement, String className, | |
| 646 String constructor, int expectedElementCount, | |
| 647 {List expectedWarnings: const [], | |
| 648 List expectedErrors: const [], | |
| 649 List expectedInfos: const [], | |
| 650 String corelib: DEFAULT_CORELIB}) { | |
| 651 MockCompiler compiler = new MockCompiler(coreSource: corelib); | |
| 652 compiler.parseScript(script); | |
| 653 compiler.resolveStatement(statement); | |
| 654 ClassElement classElement = compiler.mainApp.find(className); | |
| 655 Element element; | |
| 656 if (constructor != '') { | |
| 657 element = classElement.lookupConstructor( | |
| 658 new Selector.callConstructor(constructor, classElement.library)); | |
| 659 } else { | |
| 660 element = classElement.lookupConstructor( | |
| 661 new Selector.callDefaultConstructor(classElement.library)); | |
| 662 } | |
| 663 | |
| 664 FunctionExpression tree = element.parseNode(compiler); | |
| 665 ResolverVisitor visitor = | |
| 666 new ResolverVisitor(compiler, element, | |
| 667 new ResolutionRegistry.internal(compiler, | |
| 668 new CollectingTreeElements(element))); | |
| 669 new InitializerResolver(visitor).resolveInitializers(element, tree); | |
| 670 visitor.visit(tree.body); | |
| 671 Expect.equals(expectedElementCount, map(visitor).length); | |
| 672 | |
| 673 compareWarningKinds(script, expectedWarnings, compiler.warnings); | |
| 674 compareWarningKinds(script, expectedErrors, compiler.errors); | |
| 675 compareWarningKinds(script, expectedInfos, compiler.infos); | |
| 676 } | |
| 677 | |
| 678 testClassHierarchy() { | |
| 679 final MAIN = "main"; | 725 final MAIN = "main"; |
| 680 MockCompiler compiler = new MockCompiler(); | 726 return Future.wait([ |
| 681 compiler.parseScript("""class A extends A {} | 727 MockCompiler.create((MockCompiler compiler) { |
| 682 main() { return new A(); }"""); | 728 compiler.parseScript("""class A extends A {} |
| 683 FunctionElement mainElement = compiler.mainApp.find(MAIN); | 729 main() { return new A(); }"""); |
| 684 compiler.resolver.resolve(mainElement); | 730 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 685 Expect.equals(0, compiler.warnings.length); | 731 compiler.resolver.resolve(mainElement); |
| 686 Expect.equals(1, compiler.errors.length); | 732 Expect.equals(0, compiler.warnings.length); |
| 687 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, | 733 Expect.equals(1, compiler.errors.length); |
| 688 compiler.errors[0].message.kind); | 734 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 689 | 735 compiler.errors[0].message.kind); |
| 690 compiler = new MockCompiler(); | 736 }), |
| 691 compiler.parseScript("""class A extends B {} | 737 MockCompiler.create((MockCompiler compiler) { |
| 692 class B extends A {} | 738 compiler.parseScript("""class A extends B {} |
| 693 main() { return new A(); }"""); | 739 class B extends A {} |
| 694 mainElement = compiler.mainApp.find(MAIN); | 740 main() { return new A(); }"""); |
| 695 compiler.resolver.resolve(mainElement); | 741 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 696 Expect.equals(0, compiler.warnings.length); | 742 compiler.resolver.resolve(mainElement); |
| 697 Expect.equals(2, compiler.errors.length); | 743 Expect.equals(0, compiler.warnings.length); |
| 698 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, | 744 Expect.equals(2, compiler.errors.length); |
| 699 compiler.errors[0].message.kind); | 745 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 700 Expect.equals(MessageKind.CANNOT_FIND_CONSTRUCTOR, | 746 compiler.errors[0].message.kind); |
| 701 compiler.errors[1].message.kind); | 747 Expect.equals(MessageKind.CANNOT_FIND_CONSTRUCTOR, |
| 702 | 748 compiler.errors[1].message.kind); |
| 703 compiler = new MockCompiler(); | 749 }), |
| 704 compiler.parseScript("""abstract class A extends B {} | 750 MockCompiler.create((MockCompiler compiler) { |
| 705 abstract class B extends A {} | 751 compiler.parseScript("""abstract class A extends B {} |
| 706 class C implements A {} | 752 abstract class B extends A {} |
| 707 main() { return new C(); }"""); | 753 class C implements A {} |
| 708 mainElement = compiler.mainApp.find(MAIN); | 754 main() { return new C(); }"""); |
| 709 compiler.resolver.resolve(mainElement); | 755 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 710 Expect.equals(0, compiler.warnings.length); | 756 compiler.resolver.resolve(mainElement); |
| 711 Expect.equals(1, compiler.errors.length); | 757 Expect.equals(0, compiler.warnings.length); |
| 712 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, | 758 Expect.equals(1, compiler.errors.length); |
| 713 compiler.errors[0].message.kind); | 759 Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
| 714 | 760 compiler.errors[0].message.kind); |
| 715 compiler = new MockCompiler(); | 761 }), |
| 716 compiler.parseScript("""class A extends B {} | 762 MockCompiler.create((MockCompiler compiler) { |
| 717 class B extends C {} | 763 compiler.parseScript("""class A extends B {} |
| 718 class C {} | 764 class B extends C {} |
| 719 main() { return new A(); }"""); | 765 class C {} |
| 720 mainElement = compiler.mainApp.find(MAIN); | 766 main() { return new A(); }"""); |
| 721 compiler.resolver.resolve(mainElement); | 767 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 722 Expect.equals(0, compiler.warnings.length); | 768 compiler.resolver.resolve(mainElement); |
| 723 Expect.equals(0, compiler.errors.length); | 769 Expect.equals(0, compiler.warnings.length); |
| 724 ClassElement aElement = compiler.mainApp.find("A"); | 770 Expect.equals(0, compiler.errors.length); |
| 725 Link<DartType> supertypes = aElement.allSupertypes; | 771 ClassElement aElement = compiler.mainApp.find("A"); |
| 726 Expect.equals(<String>['B', 'C', 'Object'].toString(), | 772 Link<DartType> supertypes = aElement.allSupertypes; |
| 727 asSortedStrings(supertypes).toString()); | 773 Expect.equals(<String>['B', 'C', 'Object'].toString(), |
| 728 | 774 asSortedStrings(supertypes).toString()); |
| 729 compiler = new MockCompiler(); | 775 }), |
| 730 compiler.parseScript("""class A<T> {} | 776 MockCompiler.create((MockCompiler compiler) { |
| 731 class B<Z,W> extends A<int> implements I<Z,List<W>> {} | 777 compiler.parseScript("""class A<T> {} |
| 732 class I<X,Y> {} | 778 class B<Z,W> extends A<int> |
| 733 class C extends B<bool,String> {} | 779 implements I<Z,List<W>> {} |
| 734 main() { return new C(); }"""); | 780 class I<X,Y> {} |
| 735 mainElement = compiler.mainApp.find(MAIN); | 781 class C extends B<bool,String> {} |
| 736 compiler.resolver.resolve(mainElement); | 782 main() { return new C(); }"""); |
| 737 Expect.equals(0, compiler.warnings.length); | 783 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 738 Expect.equals(0, compiler.errors.length); | 784 compiler.resolver.resolve(mainElement); |
| 739 aElement = compiler.mainApp.find("C"); | 785 Expect.equals(0, compiler.warnings.length); |
| 740 supertypes = aElement.allSupertypes; | 786 Expect.equals(0, compiler.errors.length); |
| 741 // Object is once per inheritance path, that is from both A and I. | 787 ClassElement aElement = compiler.mainApp.find("C"); |
| 742 Expect.equals(<String>['A<int>', 'B<bool, String>', 'I<bool, List<String>>', | 788 Link<DartType> supertypes = aElement.allSupertypes; |
| 743 'Object'].toString(), | 789 // Object is once per inheritance path, that is from both A and I. |
| 744 asSortedStrings(supertypes).toString()); | 790 Expect.equals(<String>['A<int>', 'B<bool, String>', |
| 745 | 791 'I<bool, List<String>>', 'Object'].toString(), |
| 746 compiler = new MockCompiler(); | 792 asSortedStrings(supertypes).toString()); |
| 747 compiler.parseScript("""class A<T> {} | 793 }), |
| 748 class D extends A<E> {} | 794 MockCompiler.create((MockCompiler compiler) { |
| 749 class E extends D {} | 795 compiler.parseScript("""class A<T> {} |
| 750 main() { return new E(); }"""); | 796 class D extends A<E> {} |
| 751 mainElement = compiler.mainApp.find(MAIN); | 797 class E extends D {} |
| 752 compiler.resolver.resolve(mainElement); | 798 main() { return new E(); }"""); |
| 753 Expect.equals(0, compiler.warnings.length); | 799 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 754 Expect.equals(0, compiler.errors.length); | 800 compiler.resolver.resolve(mainElement); |
| 755 aElement = compiler.mainApp.find("E"); | 801 Expect.equals(0, compiler.warnings.length); |
| 756 supertypes = aElement.allSupertypes; | 802 Expect.equals(0, compiler.errors.length); |
| 757 Expect.equals(<String>['A<E>', 'D', 'Object'].toString(), | 803 ClassElement aElement = compiler.mainApp.find("E"); |
| 758 asSortedStrings(supertypes).toString()); | 804 Link<DartType> supertypes = aElement.allSupertypes; |
| 759 | 805 Expect.equals(<String>['A<E>', 'D', 'Object'].toString(), |
| 760 compiler = new MockCompiler(); | 806 asSortedStrings(supertypes).toString()); |
| 761 compiler.parseScript("""class A<T> {} | 807 }), |
| 762 class D extends A<int> implements A<double> {} | 808 MockCompiler.create((MockCompiler compiler) { |
| 763 main() { return new D(); }"""); | 809 compiler.parseScript("""class A<T> {} |
| 764 mainElement = compiler.mainApp.find(MAIN); | 810 class D extends A<int> implements A<double> {} |
| 765 compiler.resolver.resolve(mainElement); | 811 main() { return new D(); }"""); |
| 766 Expect.equals(0, compiler.warnings.length); | 812 FunctionElement mainElement = compiler.mainApp.find(MAIN); |
| 767 Expect.equals(1, compiler.errors.length); | 813 compiler.resolver.resolve(mainElement); |
| 768 Expect.equals(MessageKind.MULTI_INHERITANCE, | 814 Expect.equals(0, compiler.warnings.length); |
| 769 compiler.errors[0].message.kind); | 815 Expect.equals(1, compiler.errors.length); |
| 770 Expect.equals(0, compiler.crashes.length); | 816 Expect.equals(MessageKind.MULTI_INHERITANCE, |
| 771 } | 817 compiler.errors[0].message.kind); |
| 772 | 818 Expect.equals(0, compiler.crashes.length); |
| 773 testInitializers() { | 819 }), |
| 774 String script; | 820 ]); |
| 775 script = """class A { | 821 } |
| 776 int foo; int bar; | 822 |
| 777 A() : this.foo = 1, bar = 2; | 823 Future testInitializers() { |
| 778 }"""; | 824 return Future.forEach([ |
| 779 resolveConstructor(script, "A a = new A();", "A", "", 2); | 825 () { |
| 780 | 826 String script = |
| 781 script = """class A { | 827 """class A { |
| 782 int foo; A a; | 828 int foo; int bar; |
| 783 A() : a.foo = 1; | 829 A() : this.foo = 1, bar = 2; |
| 784 }"""; | 830 }"""; |
| 785 resolveConstructor(script, "A a = new A();", "A", "", 0, | 831 return resolveConstructor(script, "A a = new A();", "A", "", 2); |
| 786 expectedWarnings: [], | 832 }, |
| 787 expectedErrors: | 833 () { |
| 788 [MessageKind.INVALID_RECEIVER_IN_INITIALIZER]); | 834 String script = |
| 789 | 835 """class A { |
| 790 script = """class A { | 836 int foo; A a; |
| 791 int foo; | 837 A() : a.foo = 1; |
| 792 A() : this.foo = 1, this.foo = 2; | 838 }"""; |
| 793 }"""; | 839 return resolveConstructor(script, "A a = new A();", "A", "", 0, |
| 794 resolveConstructor(script, "A a = new A();", "A", "", 2, | 840 expectedWarnings: [], |
| 795 expectedInfos: [MessageKind.ALREADY_INITIALIZED], | 841 expectedErrors: [MessageKind.INVALID_RECEIVER_IN_INITIALIZER]); |
| 796 expectedErrors: [MessageKind.DUPLICATE_INITIALIZER]); | 842 }, |
| 797 | 843 () { |
| 798 script = """class A { | 844 String script = |
| 799 A() : this.foo = 1; | 845 """class A { |
| 800 }"""; | 846 int foo; |
| 801 resolveConstructor(script, "A a = new A();", "A", "", 0, | 847 A() : this.foo = 1, this.foo = 2; |
| 802 expectedWarnings: [], | 848 }"""; |
| 803 expectedErrors: [MessageKind.CANNOT_RESOLVE]); | 849 return resolveConstructor(script, "A a = new A();", "A", "", 2, |
| 804 | 850 expectedInfos: [MessageKind.ALREADY_INITIALIZED], |
| 805 script = """class A { | 851 expectedErrors: [MessageKind.DUPLICATE_INITIALIZER]); |
| 806 int foo; | 852 }, |
| 807 int bar; | 853 () { |
| 808 A() : this.foo = bar; | 854 String script = |
| 809 }"""; | 855 """class A { |
| 810 resolveConstructor(script, "A a = new A();", "A", "", 3, | 856 A() : this.foo = 1; |
| 811 expectedWarnings: [], | 857 }"""; |
| 812 expectedErrors: [MessageKind.NO_INSTANCE_AVAILABLE]); | 858 return resolveConstructor(script, "A a = new A();", "A", "", 0, |
| 813 | 859 expectedWarnings: [], |
| 814 script = """class A { | 860 expectedErrors: [MessageKind.CANNOT_RESOLVE]); |
| 815 int foo() => 42; | 861 }, |
| 816 A() : foo(); | 862 () { |
| 817 }"""; | 863 String script = |
| 818 resolveConstructor(script, "A a = new A();", "A", "", 0, | 864 """class A { |
| 819 expectedWarnings: [], | 865 int foo; |
| 820 expectedErrors: [MessageKind.CONSTRUCTOR_CALL_EXPECTED]); | 866 int bar; |
| 821 | 867 A() : this.foo = bar; |
| 822 script = """class A { | 868 }"""; |
| 823 int i; | 869 return resolveConstructor(script, "A a = new A();", "A", "", 3, |
| 824 A.a() : this.b(0); | 870 expectedWarnings: [], |
| 825 A.b(int i); | 871 expectedErrors: [MessageKind.NO_INSTANCE_AVAILABLE]); |
| 826 }"""; | 872 }, |
| 827 resolveConstructor(script, "A a = new A.a();", "A", "a", 1); | 873 () { |
| 828 | 874 String script = |
| 829 script = """class A { | 875 """class A { |
| 830 int i; | 876 int foo() => 42; |
| 831 A.a() : i = 42, this(0); | 877 A() : foo(); |
| 832 A(int i); | 878 }"""; |
| 833 }"""; | 879 return resolveConstructor(script, "A a = new A();", "A", "", 0, |
| 834 resolveConstructor(script, "A a = new A.a();", "A", "a", 2, | 880 expectedWarnings: [], |
| 835 expectedWarnings: [], | 881 expectedErrors: [MessageKind.CONSTRUCTOR_CALL_EXPECTED]); |
| 836 expectedErrors: | 882 }, |
| 837 [MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER]); | 883 () { |
| 838 | 884 String script = |
| 839 script = """class A { | 885 """class A { |
| 840 int i; | 886 int i; |
| 841 A(i); | 887 A.a() : this.b(0); |
| 842 } | 888 A.b(int i); |
| 843 class B extends A { | 889 }"""; |
| 844 B() : super(0); | 890 return resolveConstructor(script, "A a = new A.a();", "A", "a", 1); |
| 845 }"""; | 891 }, |
| 846 resolveConstructor(script, "B a = new B();", "B", "", 1); | 892 () { |
| 847 | 893 String script = |
| 848 script = """class A { | 894 """class A { |
| 849 int i; | 895 int i; |
| 850 A(i); | 896 A.a() : i = 42, this(0); |
| 851 } | 897 A(int i); |
| 852 class B extends A { | 898 }"""; |
| 853 B() : super(0), super(1); | 899 return resolveConstructor(script, "A a = new A.a();", "A", "a", 2, |
| 854 }"""; | 900 expectedWarnings: [], |
| 855 resolveConstructor(script, "B b = new B();", "B", "", 2, | 901 expectedErrors: |
| 856 expectedWarnings: [], | 902 [MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER]); |
| 857 expectedErrors: [MessageKind.DUPLICATE_SUPER_INITIALIZER]); | 903 }, |
| 858 | 904 () { |
| 859 script = ""; | 905 String script = |
| 860 final String CORELIB_WITH_INVALID_OBJECT = | 906 """class A { |
| 861 '''print(var obj) {} | 907 int i; |
| 862 class int {} | 908 A(i); |
| 863 class double {} | 909 } |
| 864 class bool {} | 910 class B extends A { |
| 865 class String {} | 911 B() : super(0); |
| 866 class num {} | 912 }"""; |
| 867 class Function {} | 913 return resolveConstructor(script, "B a = new B();", "B", "", 1); |
| 868 class List<E> {} | 914 }, |
| 869 class Map {} | 915 () { |
| 870 class Closure {} | 916 String script = |
| 871 class Null {} | 917 """class A { |
| 872 class StackTrace {} | 918 int i; |
| 873 class Dynamic_ {} | 919 A(i); |
| 874 class Type {} | 920 } |
| 875 class Object { Object() : super(); } | 921 class B extends A { |
| 876 const proxy = 0;'''; | 922 B() : super(0), super(1); |
| 877 resolveConstructor(script, "Object o = new Object();", "Object", "", 1, | 923 }"""; |
| 878 expectedWarnings: [], | 924 return resolveConstructor(script, "B b = new B();", "B", "", 2, |
| 879 expectedErrors: [MessageKind.SUPER_INITIALIZER_IN_OBJECT], | 925 expectedWarnings: [], |
| 880 corelib: CORELIB_WITH_INVALID_OBJECT); | 926 expectedErrors: [MessageKind.DUPLICATE_SUPER_INITIALIZER]); |
| 927 }, |
| 928 () { |
| 929 String script = ""; |
| 930 final String CORELIB_WITH_INVALID_OBJECT = |
| 931 '''print(var obj) {} |
| 932 class int {} |
| 933 class double {} |
| 934 class bool {} |
| 935 class String {} |
| 936 class num {} |
| 937 class Function {} |
| 938 class List<E> {} |
| 939 class Map {} |
| 940 class Closure {} |
| 941 class Null {} |
| 942 class StackTrace {} |
| 943 class Dynamic_ {} |
| 944 class Type {} |
| 945 class Object { Object() : super(); } |
| 946 const proxy = 0;'''; |
| 947 return resolveConstructor(script, |
| 948 "Object o = new Object();", "Object", "", 1, |
| 949 expectedWarnings: [], |
| 950 expectedErrors: [MessageKind.SUPER_INITIALIZER_IN_OBJECT], |
| 951 corelib: CORELIB_WITH_INVALID_OBJECT); |
| 952 }, |
| 953 ], (f) => f()); |
| 881 } | 954 } |
| 882 | 955 |
| 883 map(ResolverVisitor visitor) { | 956 map(ResolverVisitor visitor) { |
| 884 CollectingTreeElements elements = visitor.registry.mapping; | 957 CollectingTreeElements elements = visitor.registry.mapping; |
| 885 return elements.map; | 958 return elements.map; |
| 886 } | 959 } |
| 887 | 960 |
| 888 at(Link link, int index) => (index == 0) ? link.head : at(link.tail, index - 1); | 961 at(Link link, int index) => (index == 0) ? link.head : at(link.tail, index - 1); |
| 889 | 962 |
| 890 List<String> asSortedStrings(Link link) { | 963 List<String> asSortedStrings(Link link) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 }"""; | 1093 }"""; |
| 1021 asyncTest(() => compileScript(script2).then((compiler) { | 1094 asyncTest(() => compileScript(script2).then((compiler) { |
| 1022 expect(compiler, | 1095 expect(compiler, |
| 1023 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS], | 1096 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS], |
| 1024 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, | 1097 [MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, |
| 1025 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, | 1098 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR, |
| 1026 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD, | 1099 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD, |
| 1027 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD]); | 1100 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD]); |
| 1028 })); | 1101 })); |
| 1029 } | 1102 } |
| OLD | NEW |