Index: compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java |
diff --git a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java |
index c66eae959a58254022fbf5e7afbbfa62e7832162..4d2dd7264ed2c4cea65757233df058954adb22e3 100644 |
--- a/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java |
+++ b/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java |
@@ -248,4 +248,193 @@ public class TypeAnalyzerCompilerTest extends CompilerTestCase { |
assertErrors(libraryResult.getCompilationErrors()); |
assertErrors(libraryResult.getTypeErrors()); |
} |
+ |
+ /** |
+ * In contrast, if A is intended to be concrete, the checker should warn about all unimplemented |
+ * methods, but allow clients to instantiate it freely. |
+ */ |
+ public void test_warnAbstract_onConcreteClassDeclaration_whenHasUnimplementedMethods() |
+ throws Exception { |
+ AnalyzeLibraryResult libraryResult = |
+ analyzeLibrary( |
+ getName(), |
+ makeCode( |
+ "interface Foo {", |
+ " int fooA;", |
+ " void fooB();", |
+ "}", |
+ "interface Bar {", |
+ " void barA();", |
+ "}", |
+ "class A implements Foo, Bar {", |
+ "}", |
+ "class C {", |
+ " foo() {", |
+ " return new A();", |
+ " }", |
+ "}")); |
+ assertErrors( |
+ libraryResult.getTypeErrors(), |
+ errEx(TypeErrorCode.ABSTRACT_CLASS_WITHOUT_ABSTRACT_MODIFIER, 8, 7, 1), |
+ errEx(TypeErrorCode.INSTANTIATION_OF_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 12, 16, 1)); |
+ { |
+ DartCompilationError typeError = libraryResult.getTypeErrors().get(0); |
+ String message = typeError.getMessage(); |
+ assertTrue(message.contains("# From Foo:")); |
+ assertTrue(message.contains("int fooA")); |
+ assertTrue(message.contains("void fooB()")); |
+ assertTrue(message.contains("# From Bar:")); |
+ assertTrue(message.contains("void barA()")); |
+ } |
+ } |
+ |
+ /** |
+ * From specification 0.05, 11/14/2011. |
+ * <p> |
+ * In contrast, if A is intended to be concrete, the checker should warn about all unimplemented |
+ * methods, but allow clients to instantiate it freely. |
+ */ |
+ public void test_warnAbstract_onConcreteClassDeclaration_whenHasInheritedUnimplementedMethod() |
+ throws Exception { |
+ AnalyzeLibraryResult libraryResult = |
+ analyzeLibrary( |
+ getName(), |
+ makeCode( |
+ "class A {", |
+ " abstract void foo();", |
+ "}", |
+ "class B extends A {", |
+ "}", |
+ "class C {", |
+ " foo() {", |
+ " return new B();", |
+ " }", |
+ "}")); |
+ assertErrors( |
+ libraryResult.getTypeErrors(), |
+ errEx(TypeErrorCode.ABSTRACT_CLASS_WITHOUT_ABSTRACT_MODIFIER, 4, 7, 1), |
+ errEx(TypeErrorCode.INSTANTIATION_OF_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 8, 16, 1)); |
+ { |
+ DartCompilationError typeError = libraryResult.getTypeErrors().get(0); |
+ String message = typeError.getMessage(); |
+ assertTrue(message.contains("# From A:")); |
+ assertTrue(message.contains("void foo()")); |
+ } |
+ } |
+ |
+ /** |
+ * From specification 0.05, 11/14/2011. |
+ * <p> |
+ * If A is intended to be abstract, we want the static checker to warn about any attempt to |
+ * instantiate A, and we do not want the checker to complain about unimplemented methods in A. |
+ * <p> |
+ * Here: |
+ * <ul> |
+ * <li>"A" has unimplemented methods, but we don't show warnings, because it is explicitly marked |
+ * as abstract.</li> |
+ * <li>When we try to create instance of "A", we show warning that it is abstract.</li> |
+ * </ul> |
+ */ |
+ public void test_warnAbstract_onAbstractClass_whenInstantiate_normalConstructor() |
+ throws Exception { |
+ AnalyzeLibraryResult libraryResult = |
+ analyzeLibrary( |
+ getName(), |
+ makeCode( |
+ "interface Foo {", |
+ " int fooA;", |
+ " void fooB();", |
+ "}", |
+ "abstract class A implements Foo {", |
+ "}", |
+ "class C {", |
+ " foo() {", |
+ " return new A();", |
+ " }", |
+ "}")); |
+ assertErrors( |
+ libraryResult.getTypeErrors(), |
+ errEx(TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS, 9, 16, 1)); |
+ } |
+ |
+ /** |
+ * Variant of {@link #test_warnAbstract_onAbstractClass_whenInstantiate_normalConstructor()}. |
+ * <p> |
+ * An abstract class is either a class that is explicitly declared with the abstract modifier, or |
+ * a class that declares at least one abstract method (7.1.1). |
+ */ |
+ public void test_warnAbstract_onClassWithAbstractMethod_whenInstantiate_normalConstructor() |
+ throws Exception { |
+ AnalyzeLibraryResult libraryResult = |
+ analyzeLibrary( |
+ getName(), |
+ makeCode( |
+ "interface Foo {", |
+ " void foo();", |
+ "}", |
+ "class A implements Foo {", |
+ " abstract void bar();", |
+ "}", |
+ "class C {", |
+ " foo() {", |
+ " return new A();", |
+ " }", |
+ "}")); |
+ assertErrors( |
+ libraryResult.getTypeErrors(), |
+ errEx(TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS, 9, 16, 1)); |
+ } |
+ |
+ /** |
+ * Variant of {@link #test_warnAbstract_onAbstractClass_whenInstantiate_normalConstructor()}. |
+ * <p> |
+ * An abstract class is either a class that is explicitly declared with the abstract modifier, or |
+ * a class that declares at least one abstract method (7.1.1). |
+ */ |
+ public void test_warnAbstract_onClassWithAbstractGetter_whenInstantiate_normalConstructor() |
+ throws Exception { |
+ AnalyzeLibraryResult libraryResult = |
+ analyzeLibrary( |
+ getName(), |
+ makeCode( |
+ "interface Foo {", |
+ " void foo();", |
+ "}", |
+ "class A implements Foo {", |
+ " abstract get x();", |
+ "}", |
+ "class C {", |
+ " foo() {", |
+ " return new A();", |
+ " }", |
+ "}")); |
+ assertErrors( |
+ libraryResult.getTypeErrors(), |
+ errEx(TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS, 9, 16, 1)); |
+ } |
+ |
+ /** |
+ * Factory constructor can instantiate any class and return it non-abstract class instance, but |
+ * spec requires warnings, so we provide it, but using different constant. |
+ */ |
+ public void test_warnAbstract_onAbstractClass_whenInstantiate_factoryConstructor() |
+ throws Exception { |
+ AnalyzeLibraryResult libraryResult = |
+ analyzeLibrary( |
+ getName(), |
+ makeCode( |
+ "abstract class A {", |
+ " factory A() {", |
+ " return null;", |
+ " }", |
+ "}", |
+ "class C {", |
+ " foo() {", |
+ " return new A();", |
+ " }", |
+ "}")); |
+ assertErrors( |
+ libraryResult.getTypeErrors(), |
+ errEx(TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS_USING_FACTORY, 8, 16, 1)); |
+ } |
} |