Index: frog/tests/leg/resolver_test.dart |
=================================================================== |
--- frog/tests/leg/resolver_test.dart (revision 8644) |
+++ frog/tests/leg/resolver_test.dart (working copy) |
@@ -1,720 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-#import("../../../lib/compiler/implementation/leg.dart"); |
-#import("../../../lib/compiler/implementation/elements/elements.dart"); |
-#import("../../../lib/compiler/implementation/tree/tree.dart"); |
-#import("../../../lib/compiler/implementation/util/util.dart"); |
-#import("mock_compiler.dart"); |
-#import("parser_helper.dart"); |
- |
-Node buildIdentifier(String name) => new Identifier(scan(name)); |
- |
-Node buildInitialization(String name) => |
- parseBodyCode('$name = 1', |
- (parser, tokens) => parser.parseOptionallyInitializedIdentifier(tokens)); |
- |
-createLocals(List variables) { |
- var locals = []; |
- for (final variable in variables) { |
- String name = variable[0]; |
- bool init = variable[1]; |
- if (init) { |
- locals.add(buildInitialization(name)); |
- } else { |
- locals.add(buildIdentifier(name)); |
- } |
- } |
- var definitions = new NodeList(null, new Link.fromList(locals), null, null); |
- return new VariableDefinitions(null, null, definitions, null); |
-} |
- |
-testLocals(List variables) { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- Element element = visitor.visit(createLocals(variables)); |
- // A VariableDefinitions does not have an element. |
- Expect.equals(null, element); |
- Expect.equals(variables.length, map(visitor).length); |
- |
- for (final variable in variables) { |
- final name = variable[0]; |
- Identifier id = buildIdentifier(name); |
- final VariableElement variableElement = visitor.visit(id); |
- MethodScope scope = visitor.context; |
- Expect.equals(variableElement, scope.elements[buildSourceString(name)]); |
- } |
- return compiler; |
-} |
- |
-main() { |
- testLocalsOne(); |
- testLocalsTwo(); |
- testLocalsThree(); |
- testLocalsFour(); |
- testLocalsFive(); |
- testParametersOne(); |
- testFor(); |
- testTypeAnnotation(); |
- testSuperclass(); |
- // testVarSuperclass(); // The parser crashes with 'class Foo extends var'. |
- // testOneInterface(); // Generates unexpected error message. |
- // testTwoInterfaces(); // Generates unexpected error message. |
- testFunctionExpression(); |
- testNewExpression(); |
- testTopLevelFields(); |
- testClassHierarchy(); |
- testInitializers(); |
- testThis(); |
- testSuperCalls(); |
- testTypeVariables(); |
-} |
- |
-testTypeVariables() { |
- matchResolvedTypes(visitor, text, name, expectedElements) { |
- VariableDefinitions definition = parseStatement(text); |
- visitor.visit(definition.type); |
- InterfaceType type = visitor.mapping.getType(definition.type); |
- Expect.equals(definition.type.typeArguments.length(), |
- length(type.arguments)); |
- int index = 0; |
- Link<Type> arguments = type.arguments; |
- while (!arguments.isEmpty()) { |
- Expect.equals(true, index < expectedElements.length); |
- Expect.equals(expectedElements[index], arguments.head.element); |
- index++; |
- arguments = arguments.tail; |
- } |
- Expect.equals(index, expectedElements.length); |
- } |
- |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- compiler.parseScript('class Foo<T, U> {}'); |
- ClassElement foo = compiler.mainApp.find(buildSourceString('Foo')); |
- matchResolvedTypes(visitor, 'Foo<int, String> x;', 'Foo', |
- [compiler.intClass, compiler.stringClass]); |
- matchResolvedTypes(visitor, 'Foo<Foo, Foo> x;', 'Foo', |
- [foo, foo]); |
- |
- compiler = new MockCompiler(); |
- compiler.parseScript('class Foo<T, U> {}'); |
- compiler.resolveStatement('Foo<notype, int> x;'); |
- Expect.equals(1, compiler.warnings.length); |
- Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, |
- compiler.warnings[0].message.kind); |
- Expect.equals(0, compiler.errors.length); |
- |
- compiler = new MockCompiler(); |
- compiler.parseScript('class Foo<T, U> {}'); |
- compiler.resolveStatement('var x = new Foo<notype, int>();'); |
- Expect.equals(0, compiler.warnings.length); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals(MessageKind.CANNOT_RESOLVE_TYPE, |
- compiler.errors[0].message.kind); |
- |
- compiler = new MockCompiler(); |
- compiler.parseScript('class Foo<T> {' |
- ' Foo<T> t;' |
- ' foo(Foo<T> f) {}' |
- ' bar() { g(Foo<T> f) {}; g(); }' |
- '}'); |
- foo = compiler.mainApp.find(buildSourceString('Foo')); |
- compiler.resolveClass(foo); |
- foo.lookupLocalMember(buildSourceString('t')).computeType(compiler);; |
- foo.lookupLocalMember(buildSourceString('foo')).computeType(compiler);; |
- compiler.resolver.resolve(foo.lookupLocalMember(buildSourceString('bar'))); |
- Expect.equals(0, compiler.warnings.length); |
- Expect.equals(0, compiler.errors.length); |
-} |
- |
-testSuperCalls() { |
- MockCompiler compiler = new MockCompiler(); |
- String script = """class A { foo() {} } |
- class B extends A { foo() => super.foo(); }"""; |
- compiler.parseScript(script); |
- compiler.resolveStatement("B b;"); |
- |
- ClassElement classB = compiler.mainApp.find(buildSourceString("B")); |
- FunctionElement fooB = classB.lookupLocalMember(buildSourceString("foo")); |
- ClassElement classA = compiler.mainApp.find(buildSourceString("A")); |
- FunctionElement fooA = classA.lookupLocalMember(buildSourceString("foo")); |
- |
- ResolverVisitor visitor = new ResolverVisitor(compiler, fooB); |
- FunctionExpression node = fooB.parseNode(compiler); |
- visitor.visit(node.body); |
- Map mapping = map(visitor); |
- |
- Send superCall = node.body.asReturn().expression; |
- FunctionElement called = mapping[superCall]; |
- Expect.isTrue(called !== null); |
- Expect.equals(fooA, called); |
-} |
- |
-testThis() { |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript("class Foo { foo() { return this; } }"); |
- compiler.resolveStatement("Foo foo;"); |
- ClassElement fooElement = compiler.mainApp.find(buildSourceString("Foo")); |
- FunctionElement funElement = |
- fooElement.lookupLocalMember(buildSourceString("foo")); |
- ResolverVisitor visitor = new ResolverVisitor(compiler, funElement); |
- FunctionExpression function = funElement.parseNode(compiler); |
- visitor.visit(function.body); |
- Map mapping = map(visitor); |
- List<Element> values = mapping.getValues(); |
- Expect.equals(0, mapping.length); |
- Expect.equals(0, compiler.warnings.length); |
- |
- compiler = new MockCompiler(); |
- compiler.resolveStatement("main() { return this; }"); |
- Expect.equals(0, compiler.warnings.length); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, |
- compiler.errors[0].message.kind); |
- |
- compiler = new MockCompiler(); |
- compiler.parseScript("class Foo { static foo() { return this; } }"); |
- compiler.resolveStatement("Foo foo;"); |
- fooElement = compiler.mainApp.find(buildSourceString("Foo")); |
- funElement = |
- fooElement.lookupLocalMember(buildSourceString("foo")); |
- visitor = new ResolverVisitor(compiler, funElement); |
- function = funElement.parseNode(compiler); |
- visitor.visit(function.body); |
- Expect.equals(0, compiler.warnings.length); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals(MessageKind.NO_INSTANCE_AVAILABLE, |
- compiler.errors[0].message.kind); |
-} |
- |
-testLocalsOne() { |
- testLocals([["foo", false]]); |
- testLocals([["foo", false], ["bar", false]]); |
- testLocals([["foo", false], ["bar", false], ["foobar", false]]); |
- |
- testLocals([["foo", true]]); |
- testLocals([["foo", false], ["bar", true]]); |
- testLocals([["foo", true], ["bar", true]]); |
- |
- testLocals([["foo", false], ["bar", false], ["foobar", true]]); |
- testLocals([["foo", false], ["bar", true], ["foobar", true]]); |
- testLocals([["foo", true], ["bar", true], ["foobar", true]]); |
- |
- MockCompiler compiler = testLocals([["foo", false], ["foo", false]]); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals( |
- new Message(MessageKind.DUPLICATE_DEFINITION, ['foo']), |
- compiler.errors[0].message); |
-} |
- |
- |
-testLocalsTwo() { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- Node tree = parseStatement("if (true) { var a = 1; var b = 2; }"); |
- Element element = visitor.visit(tree); |
- Expect.equals(null, element); |
- BlockScope scope = visitor.context; |
- Expect.equals(0, scope.elements.length); |
- Expect.equals(2, map(visitor).length); |
- |
- List<Element> elements = map(visitor).getValues(); |
- Expect.notEquals(elements[0], elements[1]); |
-} |
- |
-testLocalsThree() { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- Node tree = parseStatement("{ var a = 1; if (true) { a; } }"); |
- Element element = visitor.visit(tree); |
- Expect.equals(null, element); |
- BlockScope scope = visitor.context; |
- Expect.equals(0, scope.elements.length); |
- Expect.equals(3, map(visitor).length); |
- List<Element> elements = map(visitor).getValues(); |
- Expect.equals(elements[0], elements[1]); |
-} |
- |
-testLocalsFour() { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- Node tree = parseStatement("{ var a = 1; if (true) { var a = 1; } }"); |
- Element element = visitor.visit(tree); |
- Expect.equals(null, element); |
- BlockScope scope = visitor.context; |
- Expect.equals(0, scope.elements.length); |
- Expect.equals(2, map(visitor).length); |
- List<Element> elements = map(visitor).getValues(); |
- Expect.notEquals(elements[0], elements[1]); |
-} |
- |
-testLocalsFive() { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- If tree = parseStatement("if (true) { var a = 1; a; } else { var a = 2; a;}"); |
- Element element = visitor.visit(tree); |
- Expect.equals(null, element); |
- BlockScope scope = visitor.context; |
- Expect.equals(0, scope.elements.length); |
- Expect.equals(6, map(visitor).length); |
- |
- Block thenPart = tree.thenPart; |
- List statements1 = thenPart.statements.nodes.toList(); |
- Node def1 = statements1[0].definitions.nodes.head; |
- Node id1 = statements1[1].expression; |
- Expect.equals(visitor.mapping[def1], visitor.mapping[id1]); |
- |
- Block elsePart = tree.elsePart; |
- List statements2 = elsePart.statements.nodes.toList(); |
- Node def2 = statements2[0].definitions.nodes.head; |
- Node id2 = statements2[1].expression; |
- Expect.equals(visitor.mapping[def2], visitor.mapping[id2]); |
- |
- Expect.notEquals(visitor.mapping[def1], visitor.mapping[def2]); |
- Expect.notEquals(visitor.mapping[id1], visitor.mapping[id2]); |
-} |
- |
-testParametersOne() { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- FunctionExpression tree = |
- parseFunction("void foo(int a) { return a; }", compiler); |
- visitor.visit(tree); |
- |
- // Check that an element has been created for the parameter. |
- VariableDefinitions vardef = tree.parameters.nodes.head; |
- Node param = vardef.definitions.nodes.head; |
- Expect.equals(ElementKind.PARAMETER, visitor.mapping[param].kind); |
- |
- // Check that 'a' in 'return a' is resolved to the parameter. |
- Block body = tree.body; |
- Return ret = body.statements.nodes.head; |
- Send use = ret.expression; |
- Expect.equals(ElementKind.PARAMETER, visitor.mapping[use].kind); |
- Expect.equals(visitor.mapping[param], visitor.mapping[use]); |
-} |
- |
-testFor() { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- For tree = parseStatement("for (int i = 0; i < 10; i = i + 1) { i = 5; }"); |
- visitor.visit(tree); |
- |
- BlockScope scope = visitor.context; |
- Expect.equals(0, scope.elements.length); |
- Expect.equals(10, map(visitor).length); |
- |
- VariableDefinitions initializer = tree.initializer; |
- Node iNode = initializer.definitions.nodes.head; |
- Element iElement = visitor.mapping[iNode]; |
- |
- // Check that we have the expected nodes. This test relies on the mapping |
- // field to be a linked hash map (preserving insertion order). |
- Expect.isTrue(map(visitor) is LinkedHashMap); |
- List<Node> nodes = map(visitor).getKeys(); |
- List<Element> elements = map(visitor).getValues(); |
- |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^^^ |
- Expect.isTrue(nodes[0] is TypeAnnotation); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^^^^^ |
- checkSendSet(iElement, nodes[1], elements[1]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^ |
- checkIdentifier(iElement, nodes[2], elements[2]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^ |
- checkSend(iElement, nodes[3], elements[3]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^ |
- checkIdentifier(iElement, nodes[4], elements[4]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^ |
- checkIdentifier(iElement, nodes[5], elements[5]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^ |
- checkSend(iElement, nodes[6], elements[6]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^^^^^^^^^ |
- checkSendSet(iElement, nodes[7], elements[7]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^ |
- checkIdentifier(iElement, nodes[8], elements[8]); |
- |
- // for (int i = 0; i < 10; i = i + 1) { i = 5; }; |
- // ^^^^^ |
- checkSendSet(iElement, nodes[9], elements[9]); |
-} |
- |
-checkIdentifier(Element expected, Node node, Element actual) { |
- Expect.isTrue(node is Identifier, node.toDebugString()); |
- Expect.equals(expected, actual); |
-} |
- |
-checkSend(Element expected, Node node, Element actual) { |
- Expect.isTrue(node is Send, node.toDebugString()); |
- Expect.isTrue(node is !SendSet, node.toDebugString()); |
- Expect.equals(expected, actual); |
-} |
- |
-checkSendSet(Element expected, Node node, Element actual) { |
- Expect.isTrue(node is SendSet, node.toDebugString()); |
- Expect.equals(expected, actual); |
-} |
- |
-testTypeAnnotation() { |
- MockCompiler compiler = new MockCompiler(); |
- String statement = "Foo bar;"; |
- |
- // Test that we get a warning when Foo is not defined. |
- Map mapping = compiler.resolveStatement(statement).map; |
- |
- Expect.equals(1, mapping.length); // bar has an element. |
- Expect.equals(1, compiler.warnings.length); |
- |
- Node warningNode = compiler.warnings[0].node; |
- |
- Expect.equals( |
- new Message(MessageKind.CANNOT_RESOLVE_TYPE, ['Foo']), |
- compiler.warnings[0].message); |
- VariableDefinitions definition = compiler.parsedTree; |
- Expect.equals(warningNode, definition.type); |
- compiler.clearWarnings(); |
- |
- // Test that there is no warning after defining Foo. |
- compiler.parseScript("class Foo {}"); |
- mapping = compiler.resolveStatement(statement).map; |
- Expect.equals(2, mapping.length); |
- Expect.equals(0, compiler.warnings.length); |
- |
- // Test that 'var' does not create a warning. |
- mapping = compiler.resolveStatement("var foo;").map; |
- Expect.equals(1, mapping.length); |
- Expect.equals(0, compiler.warnings.length); |
-} |
- |
-testSuperclass() { |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript("class Foo extends Bar {}"); |
- compiler.resolveStatement("Foo bar;"); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals( |
- new Message(MessageKind.CANNOT_RESOLVE_TYPE, ['Bar']), |
- compiler.errors[0].message); |
- compiler.clearErrors(); |
- |
- compiler = new MockCompiler(); |
- compiler.parseScript("class Foo extends Bar {}"); |
- compiler.parseScript("class Bar {}"); |
- Map mapping = compiler.resolveStatement("Foo bar;").map; |
- Expect.equals(2, mapping.length); |
- |
- ClassElement fooElement = compiler.mainApp.find(buildSourceString('Foo')); |
- ClassElement barElement = compiler.mainApp.find(buildSourceString('Bar')); |
- Expect.equals(barElement.computeType(compiler), |
- fooElement.supertype); |
- Expect.isTrue(fooElement.interfaces.isEmpty()); |
- Expect.isTrue(barElement.interfaces.isEmpty()); |
-} |
- |
-testVarSuperclass() { |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript("class Foo extends var {}"); |
- compiler.resolveStatement("Foo bar;"); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals( |
- new Message(MessageKind.CANNOT_RESOLVE_TYPE, ['var']), |
- compiler.errors[0].message); |
- compiler.clearErrors(); |
-} |
- |
-testOneInterface() { |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript("class Foo implements Bar {}"); |
- compiler.resolveStatement("Foo bar;"); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals( |
- new Message(MessageKind.CANNOT_RESOLVE_TYPE, ['bar']), |
- compiler.errors[0].message); |
- compiler.clearErrors(); |
- |
- // Add the interface to the world and make sure everything is setup correctly. |
- compiler.parseScript("interface Bar {}"); |
- |
- ResolverVisitor visitor = new ResolverVisitor(compiler, null); |
- compiler.resolveStatement("Foo bar;"); |
- |
- ClassElement fooElement = compiler.mainApp.find(buildSourceString('Foo')); |
- ClassElement barElement = compiler.mainApp.find(buildSourceString('Bar')); |
- |
- Expect.equals(null, barElement.supertype); |
- Expect.isTrue(barElement.interfaces.isEmpty()); |
- |
- Expect.equals(barElement.computeType(compiler), |
- fooElement.interfaces.head); |
- Expect.equals(1, length(fooElement.interfaces)); |
-} |
- |
-testTwoInterfaces() { |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript( |
- "interface I1 {} interface I2 {} class C implements I1, I2 {}"); |
- compiler.resolveStatement("Foo bar;"); |
- |
- ClassElement c = compiler.mainApp.find(buildSourceString('C')); |
- Element i1 = compiler.mainApp.find(buildSourceString('I1')); |
- Element i2 = compiler.mainApp.find(buildSourceString('I2')); |
- |
- Expect.equals(2, length(c.interfaces)); |
- Expect.equals(i1.computeType(compiler), at(c.interfaces, 0)); |
- Expect.equals(i2.computeType(compiler), at(c.interfaces, 1)); |
-} |
- |
-testFunctionExpression() { |
- MockCompiler compiler = new MockCompiler(); |
- ResolverVisitor visitor = compiler.resolverVisitor(); |
- Map mapping = compiler.resolveStatement("int f() {}").map; |
- Expect.equals(3, mapping.length); |
- Element element; |
- Node node; |
- mapping.forEach((Node n, Element e) { |
- if (n is FunctionExpression) { |
- element = e; |
- node = n; |
- } |
- }); |
- Expect.equals(ElementKind.FUNCTION, element.kind); |
- Expect.equals(buildSourceString('f'), element.name); |
- Expect.equals(element.parseNode(compiler), node); |
-} |
- |
-testNewExpression() { |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript("class A {} foo() { print(new A()); }"); |
- ClassElement aElement = compiler.mainApp.find(buildSourceString('A')); |
- FunctionElement fooElement = compiler.mainApp.find(buildSourceString('foo')); |
- Expect.isTrue(aElement !== null); |
- Expect.isTrue(fooElement !== null); |
- |
- fooElement.parseNode(compiler); |
- compiler.resolver.resolve(fooElement); |
- |
- TreeElements elements = compiler.resolveStatement("new A();"); |
- NewExpression expression = |
- compiler.parsedTree.asExpressionStatement().expression; |
- Element element = elements[expression.send]; |
- Expect.equals(ElementKind.GENERATIVE_CONSTRUCTOR, element.kind); |
- Expect.isTrue(element is SynthesizedConstructorElement); |
-} |
- |
-testTopLevelFields() { |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript("int a;"); |
- VariableElement element = compiler.mainApp.find(buildSourceString("a")); |
- Expect.equals(ElementKind.FIELD, element.kind); |
- VariableDefinitions node = element.variables.parseNode(compiler); |
- Identifier typeName = node.type.typeName; |
- Expect.equals(typeName.source.slowToString(), 'int'); |
- |
- compiler.parseScript("var b, c;"); |
- VariableElement bElement = compiler.mainApp.find(buildSourceString("b")); |
- VariableElement cElement = compiler.mainApp.find(buildSourceString("c")); |
- Expect.equals(ElementKind.FIELD, bElement.kind); |
- Expect.equals(ElementKind.FIELD, cElement.kind); |
- Expect.isTrue(bElement != cElement); |
- |
- VariableDefinitions bNode = bElement.variables.parseNode(compiler); |
- VariableDefinitions cNode = cElement.variables.parseNode(compiler); |
- Expect.equals(bNode, cNode); |
- Expect.isNull(bNode.type); |
- Expect.isTrue(bNode.modifiers.isVar()); |
-} |
- |
-resolveConstructor(String script, String statement, String className, |
- String constructor, int expectedElementCount, |
- [List expectedWarnings = const [], |
- List expectedErrors = const [], |
- String corelib = DEFAULT_CORELIB]) { |
- MockCompiler compiler = new MockCompiler(corelib); |
- compiler.parseScript(script); |
- compiler.resolveStatement(statement); |
- ClassElement classElement = |
- compiler.mainApp.find(buildSourceString(className)); |
- Element element = |
- classElement.lookupConstructor(buildSourceString(constructor)); |
- FunctionExpression tree = element.parseNode(compiler); |
- ResolverVisitor visitor = new ResolverVisitor(compiler, element); |
- new InitializerResolver(visitor).resolveInitializers(element, tree); |
- visitor.visit(tree.body); |
- Expect.equals(expectedElementCount, map(visitor).length); |
- |
- compareWarningKinds(script, expectedWarnings, compiler.warnings); |
- compareWarningKinds(script, expectedErrors, compiler.errors); |
-} |
- |
-testClassHierarchy() { |
- final MAIN = buildSourceString("main"); |
- MockCompiler compiler = new MockCompiler(); |
- compiler.parseScript("""class A extends B {} |
- class B extends A {} |
- main() { return new A(); }"""); |
- FunctionElement mainElement = compiler.mainApp.find(MAIN); |
- compiler.resolver.resolve(mainElement); |
- Expect.equals(0, compiler.warnings.length); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
- compiler.errors[0].message.kind); |
- |
- compiler = new MockCompiler(); |
- compiler.parseScript("""interface A extends B {} |
- interface B extends A {} |
- class C implements A {} |
- main() { return new C(); }"""); |
- mainElement = compiler.mainApp.find(MAIN); |
- compiler.resolver.resolve(mainElement); |
- Expect.equals(0, compiler.warnings.length); |
- Expect.equals(1, compiler.errors.length); |
- Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY, |
- compiler.errors[0].message.kind); |
- |
- compiler = new MockCompiler(); |
- compiler.parseScript("""class A extends B {} |
- class B extends C {} |
- class C {} |
- main() { return new A(); }"""); |
- mainElement = compiler.mainApp.find(MAIN); |
- compiler.resolver.resolve(mainElement); |
- Expect.equals(0, compiler.warnings.length); |
- Expect.equals(0, compiler.errors.length); |
- ClassElement aElement = compiler.mainApp.find(buildSourceString("A")); |
- Link<Type> supertypes = aElement.allSupertypes; |
- Expect.equals(<String>['B', 'C', 'Object'].toString(), |
- asSortedStrings(supertypes).toString()); |
-} |
- |
-testInitializers() { |
- String script; |
- script = """class A { |
- int foo; int bar; |
- A() : this.foo = 1, bar = 2; |
- }"""; |
- resolveConstructor(script, "A a = new A();", "A", "A", 2); |
- |
- script = """class A { |
- int foo; A a; |
- A() : a.foo = 1; |
- }"""; |
- resolveConstructor(script, "A a = new A();", "A", "A", 0, |
- [], [MessageKind.INVALID_RECEIVER_IN_INITIALIZER]); |
- |
- script = """class A { |
- int foo; |
- A() : this.foo = 1, this.foo = 2; |
- }"""; |
- resolveConstructor(script, "A a = new A();", "A", "A", 2, |
- [MessageKind.ALREADY_INITIALIZED], |
- [MessageKind.DUPLICATE_INITIALIZER]); |
- |
- script = """class A { |
- A() : this.foo = 1; |
- }"""; |
- resolveConstructor(script, "A a = new A();", "A", "A", 0, |
- [], [MessageKind.CANNOT_RESOLVE]); |
- |
- script = """class A { |
- int foo; |
- int bar; |
- A() : this.foo = bar; |
- }"""; |
- resolveConstructor(script, "A a = new A();", "A", "A", 3, |
- [], [MessageKind.NO_INSTANCE_AVAILABLE]); |
- |
- script = """class A { |
- int foo() => 42; |
- A() : foo(); |
- }"""; |
- resolveConstructor(script, "A a = new A();", "A", "A", 0, |
- [], [MessageKind.CONSTRUCTOR_CALL_EXPECTED]); |
- |
- script = """class A { |
- int i; |
- A.a() : this.b(0); |
- A.b(int i); |
- }"""; |
- resolveConstructor(script, "A a = new A.a();", "A", @"A$a", 1, |
- [], []); |
- |
- script = """class A { |
- int i; |
- A.a() : i = 42, this(0); |
- A(int i); |
- }"""; |
- resolveConstructor(script, "A a = new A.a();", "A", @"A$a", 2, |
- [], [MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER]); |
- |
- script = """class A { |
- int i; |
- A(i); |
- } |
- class B extends A { |
- B() : super(0); |
- }"""; |
- resolveConstructor(script, "B a = new B();", "B", "B", 1, |
- [], []); |
- |
- script = """class A { |
- int i; |
- A(i); |
- } |
- class B extends A { |
- B() : super(0), super(1); |
- }"""; |
- resolveConstructor(script, "B b = new B();", "B", "B", 2, |
- [], [MessageKind.DUPLICATE_SUPER_INITIALIZER]); |
- |
- script = ""; |
- final String CORELIB_WITH_INVALID_OBJECT = |
- '''print(var obj) {} |
- class int {} |
- class double {} |
- class bool {} |
- class String {} |
- class num {} |
- class Function {} |
- class List {} |
- class Closure {} |
- class Null {} |
- class Dynamic {} |
- class Object { Object() : super(); }'''; |
- resolveConstructor(script, "Object o = new Object();", "Object", "Object", 1, |
- [], [MessageKind.SUPER_INITIALIZER_IN_OBJECT], |
- corelib: CORELIB_WITH_INVALID_OBJECT); |
-} |
- |
-map(ResolverVisitor visitor) { |
- TreeElementMapping elements = visitor.mapping; |
- return elements.map; |
-} |
- |
-length(Link link) => link.isEmpty() ? 0 : length(link.tail) + 1; |
- |
-at(Link link, int index) => (index == 0) ? link.head : at(link.tail, index - 1); |
- |
-List<String> asSortedStrings(Link link) { |
- List<String> result = <String>[]; |
- for (; !link.isEmpty(); link = link.tail) result.add(link.head.toString()); |
- result.sort((s1, s2) => s1.compareTo(s2)); |
- return result; |
-} |