| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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("../../../leg/leg.dart"); | 5 #import("../../../leg/leg.dart"); |
| 6 #import("../../../leg/elements/elements.dart"); | 6 #import("../../../leg/elements/elements.dart"); |
| 7 #import("../../../leg/tree/tree.dart"); | 7 #import("../../../leg/tree/tree.dart"); |
| 8 #import("../../../leg/util/util.dart"); | 8 #import("../../../leg/util/util.dart"); |
| 9 #import("mock_compiler.dart"); |
| 9 #import("parser_helper.dart"); | 10 #import("parser_helper.dart"); |
| 10 | 11 |
| 11 class WarningMessage { | |
| 12 Node node; | |
| 13 Message message; | |
| 14 WarningMessage(this.node, this.message); | |
| 15 } | |
| 16 | |
| 17 class MockCompiler extends Compiler { | |
| 18 List warnings; | |
| 19 List errors; | |
| 20 Node parsedTree; | |
| 21 | |
| 22 MockCompiler() : super(null), warnings = [], errors = [] { | |
| 23 parseScript('lt() {} add() {}'); | |
| 24 } | |
| 25 | |
| 26 void reportWarning(Node node, var message) { | |
| 27 warnings.add(new WarningMessage(node, message.message)); | |
| 28 } | |
| 29 | |
| 30 void reportError(Node node, var message) { | |
| 31 errors.add(new WarningMessage(node, message.message)); | |
| 32 } | |
| 33 | |
| 34 void clearWarnings() { | |
| 35 warnings = []; | |
| 36 } | |
| 37 | |
| 38 void clearErrors() { | |
| 39 errors = []; | |
| 40 } | |
| 41 | |
| 42 resolveStatement(String text) { | |
| 43 parsedTree = parseStatement(text); | |
| 44 return resolver.resolveStatement(parsedTree); | |
| 45 } | |
| 46 | |
| 47 parseScript(String text) { | |
| 48 for (Link<Element> link = parseUnit(text, this); | |
| 49 !link.isEmpty(); | |
| 50 link = link.tail) { | |
| 51 universe.define(link.head); | |
| 52 } | |
| 53 } | |
| 54 | |
| 55 resolve(ClassElement element) { | |
| 56 return resolver.resolveType(element.parseNode(this, this)); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 Node buildIdentifier(String name) => new Identifier(scan(name)); | 12 Node buildIdentifier(String name) => new Identifier(scan(name)); |
| 61 | 13 |
| 62 Node buildInitialization(String name) => | 14 Node buildInitialization(String name) => |
| 63 parseBodyCode('$name = 1', | 15 parseBodyCode('$name = 1', |
| 64 (parser, tokens) => parser.parseOptionallyInitializedIdentifier(tokens)); | 16 (parser, tokens) => parser.parseOptionallyInitializedIdentifier(tokens)); |
| 65 | 17 |
| 66 | 18 |
| 67 createLocals(List variables) { | 19 createLocals(List variables) { |
| 68 var locals = []; | 20 var locals = []; |
| 69 for (final variable in variables) { | 21 for (final variable in variables) { |
| 70 String name = variable[0]; | 22 String name = variable[0]; |
| 71 bool init = variable[1]; | 23 bool init = variable[1]; |
| 72 if (init) { | 24 if (init) { |
| 73 locals.add(buildInitialization(name)); | 25 locals.add(buildInitialization(name)); |
| 74 } else { | 26 } else { |
| 75 locals.add(buildIdentifier(name)); | 27 locals.add(buildIdentifier(name)); |
| 76 } | 28 } |
| 77 } | 29 } |
| 78 var definitions = new NodeList(null, new Link.fromList(locals), null, null); | 30 var definitions = new NodeList(null, new Link.fromList(locals), null, null); |
| 79 return new VariableDefinitions(null, null, definitions, null); | 31 return new VariableDefinitions(null, null, definitions, null); |
| 80 } | 32 } |
| 81 | 33 |
| 82 testLocals(List variables) { | 34 testLocals(List variables) { |
| 83 MockCompiler compiler = new MockCompiler(); | 35 MockCompiler compiler = new MockCompiler(); |
| 84 ResolverVisitor visitor = new FullResolverVisitor(compiler); | 36 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 85 Element element = visitor.visit(createLocals(variables)); | 37 Element element = visitor.visit(createLocals(variables)); |
| 86 // A VariableDefinitions does not have an element. | 38 // A VariableDefinitions does not have an element. |
| 87 Expect.equals(null, element); | 39 Expect.equals(null, element); |
| 88 Expect.equals(variables.length, visitor.mapping.map.length); | 40 Expect.equals(variables.length, visitor.mapping.map.length); |
| 89 | 41 |
| 90 for (final variable in variables) { | 42 for (final variable in variables) { |
| 91 final name = variable[0]; | 43 final name = variable[0]; |
| 92 Identifier id = buildIdentifier(name); | 44 Identifier id = buildIdentifier(name); |
| 93 final element = visitor.visit(id); | 45 final element = visitor.visit(id); |
| 94 Expect.equals(element, visitor.context.elements[buildSourceString(name)]); | 46 Expect.equals(element, visitor.context.elements[buildSourceString(name)]); |
| 95 } | 47 } |
| 96 return compiler; | 48 return compiler; |
| 97 } | 49 } |
| 98 | 50 |
| 99 main() { | 51 main() { |
| 100 testLocalsOne(); | 52 testLocalsOne(); |
| 101 testLocalsTwo(); | 53 testLocalsTwo(); |
| 102 testLocalsThree(); | 54 testLocalsThree(); |
| 103 testLocalsFour(); | 55 testLocalsFour(); |
| 104 testLocalsFive(); | 56 testLocalsFive(); |
| 105 testParametersOne(); | 57 testParametersOne(); |
| 106 testFor(); | 58 testFor(); |
| 107 testTypeAnnotation(); | 59 testTypeAnnotation(); |
| 108 testSuperclass(); | 60 testSuperclass(); |
| 109 // testVarSuperclass(); // The parser crashes with 'class Foo extends var'. | 61 // testVarSuperclass(); // The parser crashes with 'class Foo extends var'. |
| 110 // testOneInterface(); // The parser does not handle interfaces. | 62 // testOneInterface(); // The parser does not handle interfaces. |
| 111 // testTwoInterfaces(); // The parser does not handle interfaces. | 63 // testTwoInterfaces(); // The parser does not handle interfaces. |
| 112 testFunctionExpression(); | 64 testFunctionExpression(); |
| 65 testNewExpression(); |
| 113 } | 66 } |
| 114 | 67 |
| 115 testLocalsOne() { | 68 testLocalsOne() { |
| 116 testLocals([["foo", false]]); | 69 testLocals([["foo", false]]); |
| 117 testLocals([["foo", false], ["bar", false]]); | 70 testLocals([["foo", false], ["bar", false]]); |
| 118 testLocals([["foo", false], ["bar", false], ["foobar", false]]); | 71 testLocals([["foo", false], ["bar", false], ["foobar", false]]); |
| 119 | 72 |
| 120 testLocals([["foo", true]]); | 73 testLocals([["foo", true]]); |
| 121 testLocals([["foo", false], ["bar", true]]); | 74 testLocals([["foo", false], ["bar", true]]); |
| 122 testLocals([["foo", true], ["bar", true]]); | 75 testLocals([["foo", true], ["bar", true]]); |
| 123 | 76 |
| 124 testLocals([["foo", false], ["bar", false], ["foobar", true]]); | 77 testLocals([["foo", false], ["bar", false], ["foobar", true]]); |
| 125 testLocals([["foo", false], ["bar", true], ["foobar", true]]); | 78 testLocals([["foo", false], ["bar", true], ["foobar", true]]); |
| 126 testLocals([["foo", true], ["bar", true], ["foobar", true]]); | 79 testLocals([["foo", true], ["bar", true], ["foobar", true]]); |
| 127 | 80 |
| 128 MockCompiler compiler = testLocals([["foo", false], ["foo", false]]); | 81 MockCompiler compiler = testLocals([["foo", false], ["foo", false]]); |
| 129 Expect.equals(1, compiler.errors.length); | 82 Expect.equals(1, compiler.errors.length); |
| 130 Expect.equals( | 83 Expect.equals( |
| 131 new Message(MessageKind.DUPLICATE_DEFINITION, ['foo']), | 84 new Message(MessageKind.DUPLICATE_DEFINITION, ['foo']), |
| 132 compiler.errors[0].message); | 85 compiler.errors[0].message); |
| 133 } | 86 } |
| 134 | 87 |
| 135 | 88 |
| 136 testLocalsTwo() { | 89 testLocalsTwo() { |
| 137 ResolverVisitor visitor = new FullResolverVisitor(new Compiler(null)); | 90 MockCompiler compiler = new MockCompiler(); |
| 91 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 138 Node tree = parseStatement("if (true) { var a = 1; var b = 2; }"); | 92 Node tree = parseStatement("if (true) { var a = 1; var b = 2; }"); |
| 139 Element element = visitor.visit(tree); | 93 Element element = visitor.visit(tree); |
| 140 Expect.equals(null, element); | 94 Expect.equals(null, element); |
| 141 Expect.equals(0, visitor.context.elements.length); | 95 Expect.equals(0, visitor.context.elements.length); |
| 142 Expect.equals(2, visitor.mapping.map.length); | 96 Expect.equals(2, visitor.mapping.map.length); |
| 143 | 97 |
| 144 List<Element> elements = visitor.mapping.map.getValues(); | 98 List<Element> elements = visitor.mapping.map.getValues(); |
| 145 Expect.notEquals(elements[0], elements[1]); | 99 Expect.notEquals(elements[0], elements[1]); |
| 146 } | 100 } |
| 147 | 101 |
| 148 testLocalsThree() { | 102 testLocalsThree() { |
| 149 ResolverVisitor visitor = new FullResolverVisitor(new Compiler(null)); | 103 MockCompiler compiler = new MockCompiler(); |
| 104 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 150 Node tree = parseStatement("{ var a = 1; if (true) { a; } }"); | 105 Node tree = parseStatement("{ var a = 1; if (true) { a; } }"); |
| 151 Element element = visitor.visit(tree); | 106 Element element = visitor.visit(tree); |
| 152 Expect.equals(null, element); | 107 Expect.equals(null, element); |
| 153 Expect.equals(0, visitor.context.elements.length); | 108 Expect.equals(0, visitor.context.elements.length); |
| 154 Expect.equals(2, visitor.mapping.map.length); | 109 Expect.equals(2, visitor.mapping.map.length); |
| 155 List<Element> elements = visitor.mapping.map.getValues(); | 110 List<Element> elements = visitor.mapping.map.getValues(); |
| 156 Expect.equals(elements[0], elements[1]); | 111 Expect.equals(elements[0], elements[1]); |
| 157 } | 112 } |
| 158 | 113 |
| 159 testLocalsFour() { | 114 testLocalsFour() { |
| 160 ResolverVisitor visitor = new FullResolverVisitor(new Compiler(null)); | 115 MockCompiler compiler = new MockCompiler(); |
| 116 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 161 Node tree = parseStatement("{ var a = 1; if (true) { var a = 1; } }"); | 117 Node tree = parseStatement("{ var a = 1; if (true) { var a = 1; } }"); |
| 162 Element element = visitor.visit(tree); | 118 Element element = visitor.visit(tree); |
| 163 Expect.equals(null, element); | 119 Expect.equals(null, element); |
| 164 Expect.equals(0, visitor.context.elements.length); | 120 Expect.equals(0, visitor.context.elements.length); |
| 165 Expect.equals(2, visitor.mapping.map.length); | 121 Expect.equals(2, visitor.mapping.map.length); |
| 166 List<Element> elements = visitor.mapping.map.getValues(); | 122 List<Element> elements = visitor.mapping.map.getValues(); |
| 167 Expect.notEquals(elements[0], elements[1]); | 123 Expect.notEquals(elements[0], elements[1]); |
| 168 } | 124 } |
| 169 | 125 |
| 170 testLocalsFive() { | 126 testLocalsFive() { |
| 171 ResolverVisitor visitor = new FullResolverVisitor(new Compiler(null)); | 127 MockCompiler compiler = new MockCompiler(); |
| 128 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 172 If tree = parseStatement("if (true) { var a = 1; a; } else { var a = 2; a;}"); | 129 If tree = parseStatement("if (true) { var a = 1; a; } else { var a = 2; a;}"); |
| 173 Element element = visitor.visit(tree); | 130 Element element = visitor.visit(tree); |
| 174 Expect.equals(null, element); | 131 Expect.equals(null, element); |
| 175 Expect.equals(0, visitor.context.elements.length); | 132 Expect.equals(0, visitor.context.elements.length); |
| 176 Expect.equals(4, visitor.mapping.map.length); | 133 Expect.equals(4, visitor.mapping.map.length); |
| 177 | 134 |
| 178 Block thenPart = tree.thenPart; | 135 Block thenPart = tree.thenPart; |
| 179 List statements1 = thenPart.statements.nodes.toList(); | 136 List statements1 = thenPart.statements.nodes.toList(); |
| 180 Node def1 = statements1[0].definitions.nodes.head; | 137 Node def1 = statements1[0].definitions.nodes.head; |
| 181 Node id1 = statements1[1].expression; | 138 Node id1 = statements1[1].expression; |
| 182 Expect.equals(visitor.mapping[def1], visitor.mapping[id1]); | 139 Expect.equals(visitor.mapping[def1], visitor.mapping[id1]); |
| 183 | 140 |
| 184 Block elsePart = tree.elsePart; | 141 Block elsePart = tree.elsePart; |
| 185 List statements2 = elsePart.statements.nodes.toList(); | 142 List statements2 = elsePart.statements.nodes.toList(); |
| 186 Node def2 = statements2[0].definitions.nodes.head; | 143 Node def2 = statements2[0].definitions.nodes.head; |
| 187 Node id2 = statements2[1].expression; | 144 Node id2 = statements2[1].expression; |
| 188 Expect.equals(visitor.mapping[def2], visitor.mapping[id2]); | 145 Expect.equals(visitor.mapping[def2], visitor.mapping[id2]); |
| 189 | 146 |
| 190 Expect.notEquals(visitor.mapping[def1], visitor.mapping[def2]); | 147 Expect.notEquals(visitor.mapping[def1], visitor.mapping[def2]); |
| 191 Expect.notEquals(visitor.mapping[id1], visitor.mapping[id2]); | 148 Expect.notEquals(visitor.mapping[id1], visitor.mapping[id2]); |
| 192 } | 149 } |
| 193 | 150 |
| 194 testParametersOne() { | 151 testParametersOne() { |
| 195 Compiler compiler = new Compiler(null); | 152 MockCompiler compiler = new MockCompiler(); |
| 196 ResolverVisitor visitor = new FullResolverVisitor(compiler); | 153 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 197 FunctionExpression tree = | 154 FunctionExpression tree = |
| 198 parseFunction("void foo(int a) { return a; }", compiler); | 155 parseFunction("void foo(int a) { return a; }", compiler); |
| 199 Element element = visitor.visit(tree); | 156 Element element = visitor.visit(tree); |
| 200 Expect.equals(ElementKind.FUNCTION, element.kind); | 157 Expect.equals(ElementKind.FUNCTION, element.kind); |
| 201 | 158 |
| 202 // Check that an element has been created for the parameter. | 159 // Check that an element has been created for the parameter. |
| 203 Node param = tree.parameters.nodes.head.definitions.nodes.head; | 160 Node param = tree.parameters.nodes.head.definitions.nodes.head; |
| 204 Expect.equals(ElementKind.PARAMETER, visitor.mapping[param].kind); | 161 Expect.equals(ElementKind.PARAMETER, visitor.mapping[param].kind); |
| 205 | 162 |
| 206 // Check that 'a' in 'return a' is resolved to the parameter. | 163 // Check that 'a' in 'return a' is resolved to the parameter. |
| 207 Block body = tree.body; | 164 Block body = tree.body; |
| 208 Return ret = body.statements.nodes.head; | 165 Return ret = body.statements.nodes.head; |
| 209 Send use = ret.expression; | 166 Send use = ret.expression; |
| 210 Expect.equals(ElementKind.PARAMETER, visitor.mapping[use].kind); | 167 Expect.equals(ElementKind.PARAMETER, visitor.mapping[use].kind); |
| 211 Expect.equals(visitor.mapping[param], visitor.mapping[use]); | 168 Expect.equals(visitor.mapping[param], visitor.mapping[use]); |
| 212 } | 169 } |
| 213 | 170 |
| 214 testFor() { | 171 testFor() { |
| 215 MockCompiler compiler = new MockCompiler(); | 172 MockCompiler compiler = new MockCompiler(); |
| 216 ResolverVisitor visitor = new FullResolverVisitor(compiler); | 173 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 217 For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }"); | 174 For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }"); |
| 218 visitor.visit(tree); | 175 visitor.visit(tree); |
| 219 | 176 |
| 220 Expect.equals(0, visitor.context.elements.length); | 177 Expect.equals(0, visitor.context.elements.length); |
| 221 Expect.equals(7, visitor.mapping.map.length); | 178 Expect.equals(7, visitor.mapping.map.length); |
| 222 | 179 |
| 223 VariableDefinitions initializer = tree.initializer; | 180 VariableDefinitions initializer = tree.initializer; |
| 224 Node iNode = initializer.definitions.nodes.head; | 181 Node iNode = initializer.definitions.nodes.head; |
| 225 Element iElement = visitor.mapping[iNode]; | 182 Element iElement = visitor.mapping[iNode]; |
| 226 | 183 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 Element i1 = compiler.universe.find(buildSourceString('I1')); | 314 Element i1 = compiler.universe.find(buildSourceString('I1')); |
| 358 Element i2 = compiler.universe.find(buildSourceString('I2')); | 315 Element i2 = compiler.universe.find(buildSourceString('I2')); |
| 359 | 316 |
| 360 Expect.equals(2, c.interfaces.length); | 317 Expect.equals(2, c.interfaces.length); |
| 361 Expect.equals(i1.computeType(compiler, null), c.interfaces[0]); | 318 Expect.equals(i1.computeType(compiler, null), c.interfaces[0]); |
| 362 Expect.equals(i2.computeType(compiler, null), c.interfaces[1]); | 319 Expect.equals(i2.computeType(compiler, null), c.interfaces[1]); |
| 363 } | 320 } |
| 364 | 321 |
| 365 testFunctionExpression() { | 322 testFunctionExpression() { |
| 366 MockCompiler compiler = new MockCompiler(); | 323 MockCompiler compiler = new MockCompiler(); |
| 367 ResolverVisitor visitor = new FullResolverVisitor(compiler); | 324 ResolverVisitor visitor = compiler.resolverVisitor(); |
| 368 Map mapping = compiler.resolveStatement("int f() {}").map; | 325 Map mapping = compiler.resolveStatement("int f() {}").map; |
| 369 Expect.equals(1, mapping.length); | 326 Expect.equals(1, mapping.length); |
| 370 Element element; | 327 Element element; |
| 371 Node node; | 328 Node node; |
| 372 mapping.forEach((Node n, Element e) { | 329 mapping.forEach((Node n, Element e) { |
| 373 element = e; | 330 element = e; |
| 374 node = n; | 331 node = n; |
| 375 }); | 332 }); |
| 376 Expect.equals(ElementKind.FUNCTION, element.kind); | 333 Expect.equals(ElementKind.FUNCTION, element.kind); |
| 377 Expect.equals(buildSourceString('f'), element.name); | 334 Expect.equals(buildSourceString('f'), element.name); |
| 378 Expect.equals(element.parseNode(compiler, compiler), node); | 335 Expect.equals(element.parseNode(compiler, compiler), node); |
| 379 } | 336 } |
| 337 |
| 338 testNewExpression() { |
| 339 MockCompiler compiler = new MockCompiler(); |
| 340 compiler.parseScript("class A {} foo() { print(new A()); }"); |
| 341 ClassElement aElement = compiler.universe.find(buildSourceString('A')); |
| 342 FunctionElement fooElement = compiler.universe.find(buildSourceString('foo')); |
| 343 Expect.isTrue(aElement !== null); |
| 344 Expect.isTrue(fooElement !== null); |
| 345 |
| 346 compiler.resolver.resolve( |
| 347 fooElement.parseNode(compiler, compiler), fooElement); |
| 348 |
| 349 TreeElements elements = compiler.resolveStatement("new A();"); |
| 350 Element element = elements[compiler.parsedTree.expression]; |
| 351 Expect.equals(ElementKind.CONSTRUCTOR, element.kind); |
| 352 Expect.isTrue(element is SynthesizedConstructorElement); |
| 353 } |
| OLD | NEW |