Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Unified Diff: compiler/javatests/com/google/dart/compiler/resolver/ResolverCompilerTest.java

Issue 8747016: Fix for resolving interface constructors in factory, issue 521. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweaks for error messages. Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: compiler/javatests/com/google/dart/compiler/resolver/ResolverCompilerTest.java
diff --git a/compiler/javatests/com/google/dart/compiler/resolver/ResolverCompilerTest.java b/compiler/javatests/com/google/dart/compiler/resolver/ResolverCompilerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6c073b5130d0080bcf0d76c08be8501dc620711c
--- /dev/null
+++ b/compiler/javatests/com/google/dart/compiler/resolver/ResolverCompilerTest.java
@@ -0,0 +1,433 @@
+// Copyright (c) 2011, 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.
+package com.google.dart.compiler.resolver;
+
+import com.google.common.base.Joiner;
+import com.google.dart.compiler.CompilerTestCase;
+import com.google.dart.compiler.DartCompilationError;
+import com.google.dart.compiler.ast.DartInvocation;
+import com.google.dart.compiler.ast.DartNewExpression;
+import com.google.dart.compiler.ast.DartNode;
+import com.google.dart.compiler.ast.DartNodeTraverser;
+import com.google.dart.compiler.ast.DartUnit;
+
+import java.util.List;
+
+/**
+ * Variant of {@link ResolverTest}, which is based on {@link CompilerTestCase}. It is probably
+ * slower, not actually unit test, but easier to use if you need access to DartNode's.
+ */
+public class ResolverCompilerTest extends CompilerTestCase {
+ /**
+ * @return the {@link DartInvocation} with given source. This is inaccurate approach, but good
+ * enough for specific tests.
+ */
+ private static DartNewExpression findNewExpression(DartNode rootNode, final String sampleSource) {
+ final DartNewExpression result[] = new DartNewExpression[1];
+ rootNode.accept(new DartNodeTraverser<Void>() {
+ @Override
+ public Void visitNewExpression(DartNewExpression node) {
+ if (node.toSource().equals(sampleSource)) {
+ result[0] = node;
+ }
+ return super.visitInvocation(node);
+ }
+ });
+ return result[0];
+ }
+
+ /**
+ * We should be able to resolve implicit default constructor.
+ */
+ public void test_resolveConstructor_implicit() throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "class F {",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new F();",
+ " }",
+ "}"));
+ assertErrors(libraryResult.getCompilationErrors());
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ DartNewExpression newExpression = findNewExpression(unit, "new F()");
+ ConstructorElement constructorElement = newExpression.getSymbol();
+ assertNotNull(constructorElement);
+ assertNull(constructorElement.getNode());
+ }
+
+ public void test_resolveConstructor_noSuchConstructor() throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "class A {",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new A.foo();",
+ " }",
+ "}"));
+ assertErrors(
+ libraryResult.getCompilationErrors(),
+ errEx(ResolverErrorCode.NEW_EXPRESSION_NOT_CONSTRUCTOR, 5, 9, 5));
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ DartNewExpression newExpression = findNewExpression(unit, "new A.foo()");
+ ConstructorElement constructorElement = newExpression.getSymbol();
+ assertNull(constructorElement);
+ }
+
+ /**
+ * We should be able to resolve implicit default constructor.
+ */
+ public void test_resolveInterfaceConstructor_implicitDefault_noInterface_noFactory()
+ throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ "}",
+ "class F implements I {",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I();",
+ " }",
+ "}"));
+ assertErrors(libraryResult.getCompilationErrors());
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ DartNewExpression newExpression = findNewExpression(unit, "new I()");
+ ConstructorElement constructorElement = newExpression.getSymbol();
+ assertNotNull(constructorElement);
+ assertNull(constructorElement.getNode());
+ }
+
+ /**
+ * We should be able to resolve implicit default constructor.
+ */
+ public void test_resolveInterfaceConstructor_implicitDefault_hasInterface_noFactory()
+ throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ "}",
+ "class F implements I {",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I();",
+ " }",
+ "}"));
+ assertErrors(libraryResult.getCompilationErrors());
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ DartNewExpression newExpression = findNewExpression(unit, "new I()");
+ ConstructorElement constructorElement = newExpression.getSymbol();
+ assertNotNull(constructorElement);
+ assertNull(constructorElement.getNode());
+ }
+
+ /**
+ * We should be able to resolve implicit default constructor.
+ */
+ public void test_resolveInterfaceConstructor_implicitDefault_noInterface_hasFactory()
+ throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ "}",
+ "class F implements I {",
+ " F();",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I();",
+ " }",
+ "}"));
+ assertErrors(libraryResult.getCompilationErrors());
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ DartNewExpression newExpression = findNewExpression(unit, "new I()");
+ DartNode constructorNode = newExpression.getSymbol().getNode();
+ assertEquals(true, constructorNode.toSource().contains("F()"));
+ }
+
+ /**
+ * If "const I()" is used, then constructor should be "const".
+ */
+ public void test_resolveInterfaceConstructor_const() throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ " I(int x);",
+ "}",
+ "class F implements I {",
+ " F(int y) {}",
+ "}",
+ "class Test {",
+ " foo() {",
+ " const I(0);",
+ " }",
+ "}"));
+ assertErrors(
+ libraryResult.getCompilationErrors(),
+ errEx(ResolverErrorCode.CONST_AND_NONCONST_CONSTRUCTOR, 9, 5, 10));
+ }
+
+ /**
+ * From specification 0.05, 11/14/2011.
+ * <p>
+ * A constructor kI of I corresponds to a constructor kF of its factory class F if either
+ * <ul>
+ * <li>F does not implement I and kI and kF have the same name, OR
+ * <li>F implements I and either
+ * <ul>
+ * <li>kI is named NI and kF is named NF, OR
+ * <li>kI is named NI.id and kF is named NF.id.
+ * </ul>
+ * </ul>
+ * <p>
+ * http://code.google.com/p/dart/issues/detail?id=521
+ */
+ public void test_resolveInterfaceConstructor_whenFactoryImplementsInterface_nameIsIdentifier()
+ throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ " I(int x);",
+ "}",
+ "class F implements I {",
+ " F(int y) {}",
+ " factory I(int y) {}",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I(0);",
+ " }",
+ "}"));
+ assertErrors(libraryResult.getCompilationErrors());
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ DartNewExpression newExpression = findNewExpression(unit, "new I(0)");
+ DartNode constructorNode = newExpression.getSymbol().getNode();
+ assertEquals(true, constructorNode.toSource().contains("F(int y)"));
+ }
+
+ /**
+ * From specification 0.05, 11/14/2011.
+ * <p>
+ * A constructor kI of I corresponds to a constructor kF of its factory class F if either
+ * <ul>
+ * <li>F does not implement I and kI and kF have the same name, OR
+ * <li>F implements I and either
+ * <ul>
+ * <li>kI is named NI and kF is named NF , OR
+ * <li>kI is named NI.id and kF is named NF.id.
+ * </ul>
+ * </ul>
+ * <p>
+ * http://code.google.com/p/dart/issues/detail?id=521
+ */
+ public void test_resolveInterfaceConstructor_whenFactoryImplementsInterface_nameIsQualified()
+ throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ " I.foo(int x);",
+ "}",
+ "class F implements I {",
+ " F.foo(int y) {}",
+ " factory I.foo(int y) {}",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I.foo(0);",
+ " }",
+ "}"));
+ assertErrors(libraryResult.getCompilationErrors());
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ // "new I.foo()" - good
+ {
+ DartNewExpression newExpression = findNewExpression(unit, "new I.foo(0)");
+ DartNode constructorNode = newExpression.getSymbol().getNode();
+ assertEquals(true, constructorNode.toSource().contains("F.foo(int y)"));
+ }
+ }
+
+ /**
+ * From specification 0.05, 11/14/2011.
+ * <p>
+ * A constructor kI of I corresponds to a constructor kF of its factory class F if either
+ * <ul>
+ * <li>F does not implement I and kI and kF have the same name, OR
+ * <li>F implements I and either
+ * <ul>
+ * <li>kI is named NI and kF is named NF , OR
+ * <li>kI is named NI.id and kF is named NF.id.
+ * </ul>
+ * </ul>
+ * <p>
+ * http://code.google.com/p/dart/issues/detail?id=521
+ */
+ public void test_resolveInterfaceConstructor_whenFactoryImplementsInterface_negative()
+ throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ " I(int x);",
+ " I.foo(int x);",
+ "}",
+ "class F implements I {",
+ " factory I.foo(int x) {}",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I(0);",
+ " new I.foo(0);",
+ " }",
+ "}"));
+ // Check errors.
+ {
+ List<DartCompilationError> errors = libraryResult.getCompilationErrors();
+ assertErrors(
+ errors,
+ errEx(ResolverErrorCode.NEW_EXPRESSION_FACTORY_CONSTRUCTOR, 10, 9, 1),
+ errEx(ResolverErrorCode.NEW_EXPRESSION_FACTORY_CONSTRUCTOR, 11, 9, 5));
+ {
+ String message = errors.get(0).getMessage();
+ assertTrue(message, message.contains("'F'"));
+ assertTrue(message, message.contains("'F'"));
+ }
+ {
+ String message = errors.get(1).getMessage();
+ assertTrue(message, message.contains("'F.foo'"));
+ assertTrue(message, message.contains("'F'"));
+ }
+ }
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ // "new I()" - no such constructor, has other constructors, so no implicit default.
+ {
+ DartNewExpression newExpression = findNewExpression(unit, "new I(0)");
+ assertEquals(null, newExpression.getSymbol());
+ }
+ // "new I.foo()" - would be valid, if not "F implements I", but here invalid
+ {
+ DartNewExpression newExpression = findNewExpression(unit, "new I.foo(0)");
+ assertEquals(null, newExpression.getSymbol());
+ }
+ }
+
+ /**
+ * From specification 0.05, 11/14/2011.
+ * <p>
+ * A constructor kI of I corresponds to a constructor kF of its factory class F if either
+ * <ul>
+ * <li>F does not implement I and kI and kF have the same name, OR
+ * <li>F implements I and either
+ * <ul>
+ * <li>kI is named NI and kF is named NF , OR
+ * <li>kI is named NI.id and kF is named NF.id.
+ * </ul>
+ * </ul>
+ * <p>
+ * http://code.google.com/p/dart/issues/detail?id=521
+ */
+ public void test_resolveInterfaceConstructor_noFactoryImplementsInterface() throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ " I(int x);",
+ " I.foo(int x);",
+ "}",
+ "class F {",
+ " F.foo(int y) {}",
+ " factory I(int y) {}",
+ " factory I.foo(int y) {}",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I(0);",
+ " new I.foo(0);",
+ " }",
+ "}"));
+ assertErrors(libraryResult.getCompilationErrors());
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ // "new I()"
+ {
+ DartNewExpression newExpression = findNewExpression(unit, "new I(0)");
+ DartNode constructorNode = newExpression.getSymbol().getNode();
+ assertEquals(true, constructorNode.toSource().contains("I(int y)"));
+ }
+ // "new I.foo()"
+ {
+ DartNewExpression newExpression = findNewExpression(unit, "new I.foo(0)");
+ DartNode constructorNode = newExpression.getSymbol().getNode();
+ assertEquals(true, constructorNode.toSource().contains("I.foo(int y)"));
+ }
+ }
+
+ /**
+ * From specification 0.05, 11/14/2011.
+ * <p>
+ * A constructor kI of I corresponds to a constructor kF of its factory class F if either
+ * <ul>
+ * <li>F does not implement I and kI and kF have the same name, OR
+ * <li>F implements I and either
+ * <ul>
+ * <li>kI is named NI and kF is named NF , OR
+ * <li>kI is named NI.id and kF is named NF.id.
+ * </ul>
+ * </ul>
+ * <p>
+ * http://code.google.com/p/dart/issues/detail?id=521
+ */
+ public void test_resolveInterfaceConstructor_noFactoryImplementsInterface_negative()
+ throws Exception {
+ AnalyzeLibraryResult libraryResult =
+ analyzeLibrary(
+ "Test.dart",
+ Joiner.on("\n").join(
+ "interface I factory F {",
+ " I.foo(int x);",
+ "}",
+ "class F {",
+ "}",
+ "class Test {",
+ " foo() {",
+ " new I.foo(0);",
+ " }",
+ "}"));
+ // Check errors.
+ {
+ List<DartCompilationError> errors = libraryResult.getCompilationErrors();
+ assertErrors(errors, errEx(ResolverErrorCode.NEW_EXPRESSION_FACTORY_CONSTRUCTOR, 8, 9, 5));
+ {
+ String message = errors.get(0).getMessage();
+ assertTrue(message, message.contains("'I.foo'"));
+ assertTrue(message, message.contains("'F'"));
+ }
+ }
+ DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next();
+ // "new I.foo()"
+ {
+ DartNewExpression newExpression = findNewExpression(unit, "new I.foo(0)");
+ assertEquals(null, newExpression.getSymbol());
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698