Index: dart/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java |
diff --git a/dart/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java b/dart/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java |
deleted file mode 100644 |
index f016f2a7b3fd91d2878e0803b86c67a8bdb31611..0000000000000000000000000000000000000000 |
--- a/dart/compiler/javatests/com/google/dart/compiler/type/TypeAnalyzerCompilerTest.java |
+++ /dev/null |
@@ -1,6545 +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. |
-package com.google.dart.compiler.type; |
- |
-import com.google.common.collect.Iterables; |
-import com.google.common.collect.Sets; |
-import com.google.dart.compiler.CommandLineOptions.CompilerOptions; |
-import com.google.dart.compiler.CompilerTestCase; |
-import com.google.dart.compiler.DartCompilationError; |
-import com.google.dart.compiler.DartCompilerErrorCode; |
-import com.google.dart.compiler.DefaultCompilerConfiguration; |
-import com.google.dart.compiler.ast.ASTVisitor; |
-import com.google.dart.compiler.ast.DartArrayAccess; |
-import com.google.dart.compiler.ast.DartBinaryExpression; |
-import com.google.dart.compiler.ast.DartClass; |
-import com.google.dart.compiler.ast.DartCommentNewName; |
-import com.google.dart.compiler.ast.DartCommentRefName; |
-import com.google.dart.compiler.ast.DartDeclaration; |
-import com.google.dart.compiler.ast.DartExprStmt; |
-import com.google.dart.compiler.ast.DartExpression; |
-import com.google.dart.compiler.ast.DartField; |
-import com.google.dart.compiler.ast.DartFieldDefinition; |
-import com.google.dart.compiler.ast.DartForInStatement; |
-import com.google.dart.compiler.ast.DartFunctionExpression; |
-import com.google.dart.compiler.ast.DartIdentifier; |
-import com.google.dart.compiler.ast.DartInvocation; |
-import com.google.dart.compiler.ast.DartMapLiteralEntry; |
-import com.google.dart.compiler.ast.DartMethodDefinition; |
-import com.google.dart.compiler.ast.DartMethodInvocation; |
-import com.google.dart.compiler.ast.DartNewExpression; |
-import com.google.dart.compiler.ast.DartNode; |
-import com.google.dart.compiler.ast.DartPropertyAccess; |
-import com.google.dart.compiler.ast.DartSuperConstructorInvocation; |
-import com.google.dart.compiler.ast.DartTypeNode; |
-import com.google.dart.compiler.ast.DartUnaryExpression; |
-import com.google.dart.compiler.ast.DartUnit; |
-import com.google.dart.compiler.ast.DartUnqualifiedInvocation; |
-import com.google.dart.compiler.parser.ParserErrorCode; |
-import com.google.dart.compiler.resolver.ClassElement; |
-import com.google.dart.compiler.resolver.ConstructorElement; |
-import com.google.dart.compiler.resolver.ConstructorNodeElement; |
-import com.google.dart.compiler.resolver.Element; |
-import com.google.dart.compiler.resolver.ElementKind; |
-import com.google.dart.compiler.resolver.EnclosingElement; |
-import com.google.dart.compiler.resolver.FieldElement; |
-import com.google.dart.compiler.resolver.LibraryElement; |
-import com.google.dart.compiler.resolver.MethodElement; |
-import com.google.dart.compiler.resolver.ResolverErrorCode; |
-import com.google.dart.compiler.resolver.TypeErrorCode; |
-import com.google.dart.compiler.resolver.VariableElement; |
- |
-import static com.google.dart.compiler.common.ErrorExpectation.assertErrors; |
-import static com.google.dart.compiler.common.ErrorExpectation.errEx; |
-import static com.google.dart.compiler.type.TypeQuality.EXACT; |
-import static com.google.dart.compiler.type.TypeQuality.INFERRED; |
-import static com.google.dart.compiler.type.TypeQuality.INFERRED_EXACT; |
- |
-import java.net.URI; |
-import java.util.List; |
-import java.util.Set; |
-import java.util.concurrent.atomic.AtomicInteger; |
- |
-/** |
- * Variant of {@link TypeAnalyzerTest}, 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 TypeAnalyzerCompilerTest extends CompilerTestCase { |
- |
- /** |
- * Top-level "main" function should not have parameters. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3271 |
- */ |
- public void test_topLevelMainFunction() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main(var p) {}", |
- "class A {", |
- " main(var p) {}", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.MAIN_FUNCTION_PARAMETERS, 2, 1, 4)); |
- } |
- |
- /** |
- * A setter definition that is prefixed with the static modifier defines a static setter. |
- * Otherwise, it defines an instance setter. The name of a setter is obtained by appending the |
- * string `=' to the identifier given in its signature. |
- * <p> |
- * Hence, a setter name can never conflict with, override or be overridden by a getter or method. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5153 |
- */ |
- public void test_setterNameImplicitEquals() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " set foo(x) {}", |
- " foo(x) {}", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a.foo = 0;", |
- " a.foo(0);", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4785 |
- */ |
- public void test_labelForBlockInSwitchCase() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " switch (0) {", |
- " case 0: qwerty: {", |
- " break qwerty;", |
- " }", |
- " break;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * We should support resolving to the method "call". |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=1355 |
- */ |
- public void test_resolveCallMethod() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " call() => 42;", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a();", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // find a() |
- DartIdentifier aVar = findNode(DartIdentifier.class, "a()"); |
- assertNotNull(aVar); |
- DartUnqualifiedInvocation invocation = (DartUnqualifiedInvocation) aVar.getParent(); |
- // analyze a() element |
- MethodElement element = (MethodElement) invocation.getElement(); |
- assertNotNull(element); |
- assertEquals("call", element.getName()); |
- assertEquals( |
- libraryResult.source.indexOf("call() => 42"), |
- element.getNameLocation().getOffset()); |
- } |
- |
- /** |
- * If a type I includes a method named call(), and the type of call() is the function type F, then |
- * I is considered to be a subtype of F. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=7271 |
- */ |
- public void test_classWithCallMethod_isFunction() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class X {", |
- " call() => 42;", |
- "}", |
- "", |
- "class Y {", |
- " call(int x) => 87;", |
- "}", |
- "", |
- "typedef F(int x);", |
- "typedef G(String y);", |
- "", |
- "main() {", |
- " X x = new X();", |
- " Y y = new Y();", |
- " Function f = x;", // OK |
- " Function g = y;", // OK |
- " F f0 = x;", // WARN |
- " F f1 = y;", // OK |
- " G g0 = x;", // WARN |
- " G g1 = y;", // WARN |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 18, 10, 1), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 20, 10, 1), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 21, 10, 1)); |
- } |
- |
- /** |
- * It is a compile-time error if a typedef refers to itself via a chain of references that does |
- * not include a class or interface type. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3534 |
- */ |
- public void test_functionTypeAlias_selfRerences_direct() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "typedef A A();", |
- "typedef B(B b);", |
- "typedef C([C c]);", |
- "typedef D({D d});", |
- "typedef E<T extends E>();", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 2, 1, 14), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 3, 1, 15), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 4, 1, 17), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 5, 1, 17), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 6, 1, 25)); |
- } |
- |
- /** |
- * It is a compile-time error if a typedef refers to itself via a chain of references that does |
- * not include a class or interface type. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3534 |
- */ |
- public void test_functionTypeAlias_selfRerences_indirect() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "typedef B1 A1();", |
- "typedef A1 B1();", |
- "typedef B2 A2();", |
- "typedef B2(A2 a);", |
- "typedef B3 A3();", |
- "typedef B3([A3 a]);", |
- "typedef B4 A4();", |
- "typedef B4({A4 a});", |
- "typedef A5<T extends B5>();", |
- "typedef B5(A5 a);", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 2, 1, 16), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 3, 1, 16), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 4, 1, 16), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 5, 1, 17), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 6, 1, 16), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 7, 1, 19), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 8, 1, 16), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 9, 1, 19), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 10, 1, 27), |
- errEx(TypeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 11, 1, 17)); |
- } |
- |
- /** |
- * Type parameters should not conflict with formal parameters. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5302 |
- */ |
- public void test_functionTypeAlias_typePaarameter_scope() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "typedef f<f>(f);", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * It is a compile-time error if initializer list contains an initializer for a variable that |
- * is not an instance variable declared in the immediately surrounding class. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3181 |
- */ |
- public void test_initializerForNotField() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "var x;", |
- "class A {", |
- " A() : x = 5 {}", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.INIT_FIELD_ONLY_IMMEDIATELY_SURROUNDING_CLASS, 4, 9, 1)); |
- } |
- |
- /** |
- * Tests that we correctly provide {@link Element#getEnclosingElement()} for method of class. |
- */ |
- public void test_resolveClassMethod() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class Object {}", |
- "class Test {", |
- " foo() {", |
- " f();", |
- " }", |
- " f() {", |
- " }", |
- "}"); |
- DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next(); |
- // find f() invocation |
- DartInvocation invocation = findInvocationSimple(unit, "f()"); |
- assertNotNull(invocation); |
- // referenced Element should be resolved to MethodElement |
- Element methodElement = invocation.getElement(); |
- assertNotNull(methodElement); |
- assertSame(ElementKind.METHOD, methodElement.getKind()); |
- assertEquals("f", ((MethodElement) methodElement).getOriginalName()); |
- // enclosing Element of MethodElement is ClassElement |
- Element classElement = methodElement.getEnclosingElement(); |
- assertNotNull(classElement); |
- assertSame(ElementKind.CLASS, classElement.getKind()); |
- assertEquals("Test", ((ClassElement) classElement).getOriginalName()); |
- } |
- |
- /** |
- * Test that local {@link DartFunctionExpression} has {@link Element} with enclosing |
- * {@link Element}. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=145 |
- */ |
- public void test_resolveLocalFunction() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class Object {}", |
- "class Test {", |
- " foo() {", |
- " f() {", |
- " }", |
- " f();", |
- " }", |
- "}"); |
- DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next(); |
- // find f() invocation |
- DartInvocation invocation = findInvocationSimple(unit, "f()"); |
- assertNotNull(invocation); |
- // referenced Element should be resolved to MethodElement |
- Element functionElement = invocation.getElement(); |
- assertNotNull(functionElement); |
- assertSame(ElementKind.FUNCTION_OBJECT, functionElement.getKind()); |
- assertEquals("f", ((MethodElement) functionElement).getOriginalName()); |
- // enclosing Element of this FUNCTION_OBJECT is enclosing method |
- MethodElement methodElement = (MethodElement) functionElement.getEnclosingElement(); |
- assertNotNull(methodElement); |
- assertSame(ElementKind.METHOD, methodElement.getKind()); |
- assertEquals("foo", methodElement.getName()); |
- // use EnclosingElement methods implementations in MethodElement |
- assertEquals(false, methodElement.isInterface()); |
- assertEquals(true, Iterables.isEmpty(methodElement.getMembers())); |
- assertEquals(null, methodElement.lookupLocalElement("f")); |
- } |
- |
- /** |
- * It is a static warning if the type of "switch expression" may not be assigned to the type of |
- * "case expression". |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3269 |
- */ |
- public void test_switchExpression_case_switchTypeMismatch() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " int v = 1;", |
- " switch (v) {", |
- " case 0: break;", |
- " }", |
- " switch (v) {", |
- " case 'a': break;", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 8, 10, 3)); |
- } |
- |
- /** |
- * It is a compile-time error if the values of the case expressions are not compile-time |
- * constants. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4553 |
- */ |
- public void test_switchExpression_case_anyConst() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " const A();", |
- "}", |
- "const A CONST_1 = const A();", |
- "const A CONST_2 = const A();", |
- "foo(var v) {", |
- " switch (v) {", |
- " case 0: break;", |
- " }", |
- " switch (v) {", |
- " case '0': break;", |
- " }", |
- " switch (v) {", |
- " case 0.0: break;", |
- " }", |
- " switch (v) {", |
- " case CONST_1: break;", |
- " case CONST_2: break;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * It is a compile-time error if the values of the case expressions are not compile-time |
- * constants. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4553 |
- */ |
- public void test_switchExpression_case_notConst() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "foo(var v) {", |
- " A notConst = new A();", |
- " switch (v) {", |
- " case notConst: break;", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.EXPECTED_CONSTANT_EXPRESSION, 6, 10, 8)); |
- } |
- |
- /** |
- * It is a compile-time error if the class C implements the operator ==. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4553 |
- */ |
- public void test_switchExpression_case_hasOperatorEquals() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " const C();", |
- " operator ==(other) => false;", |
- "}", |
- "const C CONST = const C();", |
- "foo(var v) {", |
- " switch (v) {", |
- " case CONST: break;", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CASE_EXPRESSION_TYPE_SHOULD_NOT_HAVE_EQUALS, 9, 10, 5)); |
- } |
- |
- /** |
- * It is a compile-time error if the values of the case expressions do not all have the same type. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3528 |
- */ |
- public void test_switchExpression_case_differentTypes() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "foo(var v) {", |
- " switch (v) {", |
- " case 0: break;", |
- " case 'a': break;", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CASE_EXPRESSIONS_SHOULD_BE_SAME_TYPE, 5, 10, 3)); |
- } |
- |
- public void test_switchExpression_case_constLocalVariable() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "foo(var v) {", |
- " const int VALUE = 0;", |
- " switch (v) {", |
- " case VALUE: break;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=2862 |
- */ |
- public void test_switchCase_fallThrough() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "foo(int x) {", |
- " while (true) {", |
- " switch (x) {", |
- " case 0:", |
- " break;", |
- " case 1:", |
- " continue;", |
- " case 2:", |
- " return;", |
- " case 3:", |
- " throw new Exception();", |
- " case 4:", |
- " bar();", |
- " default:", |
- " bar();", |
- " }", |
- " }", |
- "}", |
- "bar() {}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.SWITCH_CASE_FALL_THROUGH, 14, 9, 6)); |
- } |
- |
- /** |
- * Language specification requires that factory should be declared in class. However declaring |
- * factory on top level should not cause exceptions in compiler. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=345 |
- */ |
- public void test_badTopLevelFactory() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary("factory foo() {}"); |
- DartUnit unit = libraryResult.getLibraryUnitResult().getUnits().iterator().next(); |
- DartMethodDefinition factory = (DartMethodDefinition) unit.getTopLevelNodes().get(0); |
- assertNotNull(factory); |
- // this factory has name, which is allowed for normal method |
- assertEquals(true, factory.getName() instanceof DartIdentifier); |
- assertEquals("foo", ((DartIdentifier) factory.getName()).getName()); |
- // compilation error expected |
- assertBadTopLevelFactoryError(libraryResult); |
- } |
- |
- /** |
- * Asserts that given {@link AnalyzeLibraryResult} contains {@link DartCompilationError} for |
- * invalid factory on top level. |
- */ |
- private void assertBadTopLevelFactoryError(AnalyzeLibraryResult libraryResult) { |
- List<DartCompilationError> compilationErrors = libraryResult.getCompilationErrors(); |
- assertEquals(1, compilationErrors.size()); |
- DartCompilationError compilationError = compilationErrors.get(0); |
- assertEquals(ParserErrorCode.FACTORY_CANNOT_BE_TOP_LEVEL, compilationError.getErrorCode()); |
- assertEquals(1, compilationError.getLineNumber()); |
- assertEquals(1, compilationError.getColumnNumber()); |
- assertEquals("factory".length(), compilationError.getLength()); |
- } |
- |
- /** |
- * @return the {@link DartInvocation} with given source. This is inaccurate approach, but good |
- * enough for specific tests. |
- */ |
- private static DartInvocation findInvocationSimple(DartNode rootNode, |
- final String invocationString) { |
- final DartInvocation invocationRef[] = new DartInvocation[1]; |
- rootNode.accept(new ASTVisitor<Void>() { |
- @Override |
- public Void visitInvocation(DartInvocation node) { |
- if (node.toSource().equals(invocationString)) { |
- invocationRef[0] = node; |
- } |
- return super.visitInvocation(node); |
- } |
- }); |
- return invocationRef[0]; |
- } |
- |
- /** |
- * 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_hasUnimplemented_method_fromInterface() |
- throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "abstract class Foo {", |
- " int fooA;", |
- " void fooB();", |
- "}", |
- "abstract class Bar {", |
- " void barA();", |
- "}", |
- "class A implements Foo, Bar {", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 8, 7, 1)); |
- { |
- DartCompilationError typeError = libraryResult.getErrors().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()")); |
- } |
- } |
- |
- /** |
- * 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_hasUnimplemented_method_inherited() |
- throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "abstract class A {", |
- " void foo();", |
- "}", |
- "class B extends A {", |
- "}", |
- "main() {", |
- " new B();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 4, 7, 1)); |
- { |
- DartCompilationError typeError = libraryResult.getErrors().get(0); |
- String message = typeError.getMessage(); |
- assertTrue(message.contains("# From A:")); |
- assertTrue(message.contains("void foo()")); |
- } |
- } |
- |
- /** |
- * 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_hasUnimplemented_method_self() |
- throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " void foo();", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 1, 7, 1)); |
- { |
- DartCompilationError typeError = libraryResult.getErrors().get(0); |
- String message = typeError.getMessage(); |
- assertTrue(message.contains("# From A:")); |
- assertTrue(message.contains("void foo()")); |
- } |
- } |
- |
- /** |
- * When class implements "noSuchMethod", we presume that it will handle unimplemented methods. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6964 |
- */ |
- public void test_warnAbstract_onConcreteClassDeclaration_hasUnimplementedMethod_noSuchMethod() |
- throws Exception { |
- // report by default |
- { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " void foo();", |
- " noSuchMethod(Invocation m) {}", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 1, 7, 1)); |
- } |
- // disable warnings if has "noSuchMethod" |
- { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean reportNoMemberWhenHasInterceptor() { |
- return false; |
- } |
- }); |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " void foo();", |
- " noSuchMethod(Invocation m) {}", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- } |
- |
- public void test_warnAbstract_onConcreteClassDeclaration_hasUnimplemented_getter() |
- throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " get x;", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 1, 7, 1)); |
- } |
- |
- public void test_warnAbstract_onConcreteClassDeclaration_hasUnimplemented_mixin() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class A {", |
- " foo();", |
- "}", |
- "class B extends Object with A {", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 5, 7, 1)); |
- } |
- |
- /** |
- * Class "B" has implementation for "bVal" and "bVal=", so we don't need any warning. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=7605 |
- */ |
- public void test_warnAbstract_onConcreteClassDeclaration_inheritedGetter_abstractGetter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class A {", |
- " get bVal {}", |
- " set bVal(var val);", |
- "}", |
- "class B extends A {", |
- " set bVal(var val) {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * There was bug that implementing setter still caused warning. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5327 |
- */ |
- public void test_warnAbstract_whenInstantiate_implementSetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "abstract class I {", |
- " set foo(x);", |
- "}", |
- "class A implements I {", |
- " set foo(x) {}", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * When both getter and setter were abstract and only getter implemented, we should report error. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5327 |
- */ |
- public void test_warnAbstract_whenInstantiate_implementsOnlyGetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "abstract class I {", |
- " get foo;", |
- " set foo(x);", |
- "}", |
- "class A implements I {", |
- " get foo => 0;", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 5, 7, 1)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5327 |
- */ |
- public void test_warnAbstract_whenInstantiate_implementsSetter_inSuperClass() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "abstract class I {", |
- " get foo;", |
- " set foo(x);", |
- "}", |
- "abstract class A implements I {", |
- " get foo;", |
- " set foo(x) {}", |
- "}", |
- "class B extends A {", |
- " get foo => 0;", |
- "}", |
- "main() {", |
- " new B();", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_warnAbstract_onAbstractClass_whenInstantiate_normalConstructor() |
- throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "abstract class A {", |
- " void bar();", |
- "}", |
- "main() {", |
- " new A();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS, 5, 7, 1)); |
- } |
- |
- /** |
- * Factory constructor can instantiate any class and return it non-abstract class instance, Even |
- * thought this is an abstract class, there should be no warnings for the invocation of the |
- * factory constructor. |
- */ |
- public void test_warnAbstract_onAbstractClass_whenInstantiate_factoryConstructor() |
- throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "abstract class A {", // explicitly abstract |
- " factory A() {", |
- " return null;", |
- " }", |
- "}", |
- "class C {", |
- " foo() {", |
- " return new A();", // no error - factory constructor |
- " }", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * Factory constructor can instantiate any class and return it non-abstract class instance, Even |
- * thought this is an abstract class, there should be no warnings for the invocation of the |
- * factory constructor. |
- */ |
- public void test_wanrAbstract_onAbstractClass_whenInstantiate_factoryConstructor2() |
- throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "abstract class A {", // class is abstract |
- " factory A() {", |
- " return null;", |
- " }", |
- " method();", |
- "}", |
- "class C {", |
- " foo() {", |
- " return new A();", // no error, factory constructor |
- " }", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * Spec 7.3 It is a static warning if a setter declares a return type other than void. |
- */ |
- public void testWarnOnNonVoidSetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " void set foo(bool a) {}", |
- " set bar(bool a) {}", |
- " dynamic set baz(bool a) {}", |
- " bool set bob(bool a) {}", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.SETTER_RETURN_TYPE, 4, 3, 7), |
- errEx(TypeErrorCode.SETTER_RETURN_TYPE, 5, 3, 4)); |
- } |
- |
- public void test_callUnknownFunction() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " foo();", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors(), errEx(ResolverErrorCode.CANNOT_RESOLVE_METHOD, 3, 3, 3)); |
- } |
- |
- /** |
- * We should be able to call <code>Function</code> even if it is in the field. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=933 |
- */ |
- public void test_callFunctionFromField() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class WorkElement {", |
- " Function run;", |
- "}", |
- "foo(WorkElement e) {", |
- " e.run();", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * When we attempt to use function as type, we should report only one error. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3309 |
- */ |
- public void test_useFunctionAsType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "func() {}", |
- "main() {", |
- " new func();", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors(), errEx(TypeErrorCode.NOT_A_TYPE, 4, 7, 4)); |
- } |
- |
- /** |
- * There was problem that {@link DartForInStatement} visits "iterable" two times. At first time we |
- * set {@link MethodElement}, because we resolve it to getter. However because of this at second |
- * time we can not resolve. Solution - don't try to resolve second time, we already done at first |
- * time. Note: double getter is important. |
- */ |
- public void test_doubleGetterAccess_inForEach() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "class Test {", |
- " Iterable get iter {}", |
- "}", |
- "Test get test {}", |
- "f() {", |
- " for (var v in test.iter) {}", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * Test for errors and warnings related to positional and named arguments for required and |
- * optional parameters. |
- */ |
- public void test_invocationArguments() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "/* 01 */ foo() {", |
- "/* 02 */ f_0_0();", |
- "/* 03 */ f_0_0(-1);", |
- "/* 04 */", |
- "/* 05 */ f_1_0();", |
- "/* 06 */ f_1_0(-1);", |
- "/* 07 */ f_1_0(-1, -2, -3);", |
- "/* 08 */", |
- "/* 09 */ f_2_0();", |
- "/* 10 */", |
- "/* 11 */ f_0_1();", |
- "/* 12 */ f_0_1(1);", |
- "/* 13 */ f_0_1(0, 0);", |
- "/* 14 */ f_0_1(n1: 1);", |
- "/* 15 */ f_0_1(x: 1);", |
- "/* 16 */ f_0_1(n1: 1, n1: 2);", |
- "}", |
- "", |
- "f_0_0() {}", |
- "f_1_0(r1) {}", |
- "f_2_0(r1, r2) {}", |
- "f_0_1({n1}) {}", |
- "f_0_2({n1, n2}) {}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.EXTRA_ARGUMENT, 3, 18, 2), |
- errEx(TypeErrorCode.MISSING_ARGUMENT, 5, 12, 5), |
- errEx(TypeErrorCode.EXTRA_ARGUMENT, 7, 22, 2), |
- errEx(TypeErrorCode.EXTRA_ARGUMENT, 7, 26, 2), |
- errEx(TypeErrorCode.MISSING_ARGUMENT, 9, 12, 5), |
- errEx(TypeErrorCode.EXTRA_ARGUMENT, 12, 18, 1), |
- errEx(TypeErrorCode.EXTRA_ARGUMENT, 13, 18, 1), |
- errEx(TypeErrorCode.EXTRA_ARGUMENT, 13, 21, 1), |
- errEx(TypeErrorCode.NO_SUCH_NAMED_PARAMETER, 15, 18, 4), |
- errEx(ResolverErrorCode.DUPLICATE_NAMED_ARGUMENT, 16, 25, 5)); |
- } |
- |
- /** |
- * Test that optional positional and named parameters are handled separately. |
- */ |
- public void test_invocationArguments2() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "func([int np1, int np2, int np3]) {}", |
- "main() {", |
- " func(np1: 1, np2: 2, np3: 2);", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NO_SUCH_NAMED_PARAMETER, 4, 8, 6), |
- errEx(TypeErrorCode.NO_SUCH_NAMED_PARAMETER, 4, 16, 6), |
- errEx(TypeErrorCode.NO_SUCH_NAMED_PARAMETER, 4, 24, 6)); |
- } |
- |
- /** |
- * We should return correct {@link Type} for {@link DartNewExpression}. |
- */ |
- public void test_DartNewExpression_getType() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " A() {}", |
- " A.foo() {}", |
- "}", |
- "var a1 = new A();", |
- "var a2 = new A.foo();", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // new A() |
- { |
- DartNewExpression newExpression = (DartNewExpression) getTopLevelFieldInitializer(testUnit, 1); |
- Type newType = newExpression.getType(); |
- assertEquals("A", newType.getElement().getName()); |
- } |
- // new A.foo() |
- { |
- DartNewExpression newExpression = (DartNewExpression) getTopLevelFieldInitializer(testUnit, 2); |
- Type newType = newExpression.getType(); |
- assertEquals("A", newType.getElement().getName()); |
- } |
- } |
- |
- /** |
- * Expects that given {@link DartUnit} has {@link DartFieldDefinition} as <code>index</code> top |
- * level node and return initializer of first {@link DartField}. |
- */ |
- private static DartExpression getTopLevelFieldInitializer(DartUnit unit, int index) { |
- DartFieldDefinition fieldDefinition = (DartFieldDefinition) unit.getTopLevelNodes().get(index); |
- DartField field = fieldDefinition.getFields().get(0); |
- return field.getValue(); |
- } |
- |
- /** |
- * If property has only setter, no getter, then attempt to use getter should cause static type |
- * warning. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=1251 |
- */ |
- public void test_setterOnlyProperty_noGetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class SetOnly {", |
- " set foo(arg) {}", |
- "}", |
- "class SetOnlyWrapper {", |
- " SetOnly setOnly;", |
- "}", |
- "", |
- "main() {", |
- " SetOnly setOnly = new SetOnly();", |
- " setOnly.foo = 1;", // 10: OK, use setter |
- " setOnly.foo += 2;", // 11: ERR, no getter |
- " print(setOnly.foo);", // 12: ERR, no getter |
- " var bar;", |
- " bar = setOnly.foo;", // 14: ERR, assignment, but we are not LHS |
- " bar = new SetOnlyWrapper().setOnly.foo;", // 15: ERR, even in chained expression |
- " new SetOnlyWrapper().setOnly.foo = 3;", // 16: OK |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.FIELD_HAS_NO_GETTER, 11, 11, 3), |
- errEx(TypeErrorCode.FIELD_HAS_NO_GETTER, 12, 17, 3), |
- errEx(TypeErrorCode.FIELD_HAS_NO_GETTER, 14, 17, 3), |
- errEx(TypeErrorCode.FIELD_HAS_NO_GETTER, 15, 38, 3)); |
- } |
- |
- public void test_setterOnlyProperty_normalField() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " var foo;", |
- "}", |
- "", |
- "main() {", |
- " A a = new A();", |
- " a.foo = 1;", |
- " a.foo += 2;", |
- " print(a.foo);", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_setterOnlyProperty_getterInSuper() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " get foo {}", |
- "}", |
- "class B extends A {", |
- " set foo(arg) {}", |
- "}", |
- "", |
- "main() {", |
- " B b = new B();", |
- " b.foo = 1;", |
- " b.foo += 2;", |
- " print(b.foo);", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_setterOnlyProperty_getterInInterface() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "abstract class A {", |
- " get foo {}", |
- "}", |
- "abstract class B implements A {", |
- " set foo(arg) {}", |
- "}", |
- "", |
- "main() {", |
- " B b = new B();", |
- " b.foo = 1;", |
- " b.foo += 2;", |
- " print(b.foo);", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS, 9, 13, 1)); |
- } |
- |
- public void test_getterOnlyProperty_noSetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class GetOnly {", |
- " get foo {}", |
- "}", |
- "class GetOnlyWrapper {", |
- " GetOnly getOnly;", |
- "}", |
- "", |
- "main() {", |
- " GetOnly getOnly = new GetOnly();", |
- " print(getOnly.foo);", // 10: OK, use getter |
- " getOnly.foo = 1;", // 11: ERR, no setter |
- " getOnly.foo += 2;", // 12: ERR, no setter |
- " var bar;", |
- " bar = getOnly.foo;", // 14: OK, use getter |
- " new GetOnlyWrapper().getOnly.foo = 3;", // 15: ERR, no setter |
- " bar = new GetOnlyWrapper().getOnly.foo;", // 16: OK, use getter |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.FIELD_HAS_NO_SETTER, 11, 11, 3), |
- errEx(TypeErrorCode.FIELD_HAS_NO_SETTER, 12, 11, 3), |
- errEx(TypeErrorCode.FIELD_HAS_NO_SETTER, 15, 32, 3)); |
- } |
- |
- public void test_getterOnlyProperty_setterInSuper() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "class A {", |
- " set foo(arg) {}", |
- "}", |
- "class B extends A {", |
- " get foo {}", |
- "}", |
- "", |
- "main() {", |
- " B b = new B();", |
- " b.foo = 1;", |
- " b.foo += 2;", |
- " print(b.foo);", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_getterOnlyProperty_setterInInterface() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "abstract class A {", |
- " set foo(arg) {}", |
- "}", |
- "abstract class B implements A {", |
- " get foo {}", |
- "}", |
- "", |
- "main() {", |
- " B b = new B();", |
- " b.foo = 1;", |
- " b.foo += 2;", |
- " print(b.foo);", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.INSTANTIATION_OF_ABSTRACT_CLASS, 9, 13, 1)); |
- } |
- |
- public void test_assert_notUserFunction() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " assert(true);", |
- " assert(false);", |
- " assert('message');", // not 'bool' |
- " assert('null');", // not 'bool' |
- " assert(0);", // not 'bool' |
- " assert(f1);", // OK, dynamic |
- " assert(f2);", // OK, '() -> bool' |
- " assert(f3);", // OK, 'Object' compatible with 'bool' |
- " assert(f4);", // not '() -> bool', return type |
- " assert(f5);", // not '() -> bool', parameter |
- " assert(true, false);", // not single argument |
- " assert;", // incomplete |
- "}", |
- "f1() {}", |
- "bool f2() {}", |
- "Object f3() {}", |
- "String f4() {}", |
- "bool f5(x) {}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ParserErrorCode.EXPECTED_TOKEN, 13, 10, 4), |
- errEx(ParserErrorCode.EXPECTED_TOKEN, 14, 9, 1), |
- errEx(TypeErrorCode.ASSERT_BOOL, 5, 10, 9), |
- errEx(TypeErrorCode.ASSERT_BOOL, 6, 10, 6), |
- errEx(TypeErrorCode.ASSERT_BOOL, 7, 10, 1), |
- errEx(TypeErrorCode.ASSERT_BOOL, 11, 10, 2), |
- errEx(TypeErrorCode.ASSERT_BOOL, 12, 10, 2)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3264 |
- */ |
- public void test_initializingFormalType_useFieldType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " final double f;", |
- " A(this.f);", |
- "}", |
- "class B {", |
- " B(this.f);", |
- " final double f;", |
- "}", |
- "", |
- "main() {", |
- " new A('0');", |
- " new B('0');", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 12, 9, 3), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 13, 9, 3)); |
- } |
- |
- /** |
- * If "this.field" parameter has declared type, it should be assignable to the field. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3264 |
- */ |
- public void test_initializingFormalType_compatilityWithFieldType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " final double f;", |
- " A.useDynamic(dynamic this.f);", |
- " A.useNum(num this.f);", |
- " A.useString(String this.f);", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 6, 15, 13)); |
- } |
- |
- public void test_finalField_inClass() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " final f = 0;", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a.f = 0;", // 6: ERR, is final |
- " a.f += 1;", // 7: ERR, is final |
- " print(a.f);", // 8: OK, can read |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.FIELD_IS_FINAL, 7, 5, 1), |
- errEx(TypeErrorCode.FIELD_IS_FINAL, 8, 5, 1)); |
- } |
- |
- public void test_notFinalField() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var f;", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a.f = 0;", // 6: OK, field "f" is not final |
- " a.f += 1;", // 7: OK, field "f" is not final |
- " print(a.f);", // 8: OK, can read |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_constField() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const f = 1;", |
- "class A {", |
- " const f = 1;", |
- " method() {", |
- " f = 2;", |
- " this.f = 2;", |
- " }", |
- "}", |
- "main() {", |
- " f = 2;", |
- " A a = new A();", |
- " a.f = 2;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 6, 5, 1), |
- errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 7, 5, 6), |
- errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 11, 3, 1), |
- errEx(TypeErrorCode.FIELD_IS_FINAL, 13, 5, 1)); |
- } |
- |
- public void test_assignConst_topLevelVariable() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const f = 1;", |
- "main() {", |
- " f = 2;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 4, 3, 1)); |
- } |
- |
- public void test_assignFinal_topLevelVariable() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "final f = 1;", |
- "main() {", |
- " f = 2;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL, 4, 3, 1)); |
- } |
- |
- public void test_assignFinal_instanceVariable_inConstructor() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " final f = 1;", |
- " A() {", |
- " f = 2;", |
- " f += 3;", |
- " print(f);", |
- " }", |
- "", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL_ERROR, 5, 5, 1), |
- errEx(ResolverErrorCode.CANNOT_ASSIGN_TO_FINAL_ERROR, 6, 5, 1)); |
- } |
- |
- public void test_identicalFunction() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const A = 1;", |
- "const B = 2;", |
- "const C = identical(A, B);", |
- "const D = !identical(A, B);", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_constantEvaluationException_divZero() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const C1 = 1 ~/ 0;", |
- "const C2 = 1 % 0;", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CONSTANTS_EVALUATION_EXCEPTION, 2, 12, 6), |
- errEx(ResolverErrorCode.CONSTANTS_EVALUATION_EXCEPTION, 3, 12, 5)); |
- } |
- |
- /** |
- * It is a compile-time error to use type variables in "const" instance creation. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=2379 |
- */ |
- public void test_constInstantiation_withTypeVariable() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " const A();", |
- " const A.name();", |
- "}", |
- "class B<U> {", |
- " test() {", |
- " const A<U>();", |
- " const A<U>.name();", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CONST_WITH_TYPE_VARIABLE, 8, 13, 1), |
- errEx(ResolverErrorCode.CONST_WITH_TYPE_VARIABLE, 9, 13, 1)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3182 |
- */ |
- public void test_extendNotType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "int A;", |
- "class B extends A {", |
- "}", |
- "", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.NOT_A_TYPE, 3, 17, 1)); |
- } |
- |
- public void test_constInstanceCreation_noSuchType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " const NoSuchType();", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.NO_SUCH_TYPE_CONST, 3, 9, 10)); |
- } |
- |
- public void test_constInstanceCreation_noSuchConstructor() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "main() {", |
- " const A.noSuchName();", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.NEW_EXPRESSION_NOT_CONST_CONSTRUCTOR, 4, 11, 10)); |
- } |
- |
- public void test_constInstanceCreation_notType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "var notType;", |
- "main() {", |
- " const notType();", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.NOT_A_TYPE, 4, 9, 7)); |
- } |
- |
- /** |
- * Test for variants of {@link DartMethodDefinition} return types. |
- */ |
- public void test_methodReturnTypes() throws Exception { |
- AnalyzeLibraryResult libraryResult = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "int fA() {}", |
- "dynamic fB() {}", |
- "void fC() {}", |
- "fD() {}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- { |
- DartMethodDefinition fA = (DartMethodDefinition) testUnit.getTopLevelNodes().get(0); |
- assertEquals("int", fA.getElement().getReturnType().getElement().getName()); |
- } |
- { |
- DartMethodDefinition fB = (DartMethodDefinition) testUnit.getTopLevelNodes().get(1); |
- assertEquals("dynamic", fB.getElement().getReturnType().getElement().getName()); |
- } |
- { |
- DartMethodDefinition fC = (DartMethodDefinition) testUnit.getTopLevelNodes().get(2); |
- assertEquals("void", fC.getElement().getReturnType().getElement().getName()); |
- } |
- { |
- DartMethodDefinition fD = (DartMethodDefinition) testUnit.getTopLevelNodes().get(3); |
- assertEquals("dynamic", fD.getElement().getReturnType().getElement().getName()); |
- } |
- } |
- |
- public void test_bindToLibraryFunctionFirst() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "foo() {}", |
- "class A {", |
- " foo() {}", |
- "}", |
- "class B extends A {", |
- " bar() {", |
- " foo();", |
- " }", |
- "}", |
- ""); |
- // Find foo() invocation. |
- DartUnqualifiedInvocation invocation; |
- { |
- DartClass classB = (DartClass) testUnit.getTopLevelNodes().get(2); |
- DartMethodDefinition methodBar = (DartMethodDefinition) classB.getMembers().get(0); |
- DartExprStmt stmt = (DartExprStmt) methodBar.getFunction().getBody().getStatements().get(0); |
- invocation = (DartUnqualifiedInvocation) stmt.getExpression(); |
- } |
- // Check that unqualified foo() invocation is resolved to the top-level (library) function. |
- Element element = invocation.getTarget().getElement(); |
- assertNotNull(element); |
- assertTrue(element.getEnclosingElement() instanceof LibraryElement); |
- } |
- |
- /** |
- * If there was <code>import</code> with invalid {@link URI}, it should be reported as error, not |
- * as an exception. |
- */ |
- public void test_invalidImportUri() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "library test;", |
- "import 'badURI';", |
- ""); |
- assertErrors(libraryResult.getErrors(), errEx(DartCompilerErrorCode.MISSING_SOURCE, 3, 1, 16)); |
- } |
- |
- /** |
- * If there was <code>part</code> with invalid {@link URI}, it should be reported as error, not |
- * as an exception. |
- */ |
- public void test_invalidSourceUri() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "library test;", |
- "part 'badURI';", |
- ""); |
- assertErrors(libraryResult.getErrors(), errEx(DartCompilerErrorCode.MISSING_SOURCE, 3, 1, 14)); |
- } |
- |
- public void test_mapLiteralKeysUnique() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "var m = {'a' : 0, 'b': 1, 'a': 2};", |
- ""); |
- assertErrors(libraryResult.getErrors(), errEx(TypeErrorCode.MAP_LITERAL_KEY_UNIQUE, 2, 27, 3)); |
- } |
- |
- /** |
- * No required parameter "x". |
- */ |
- public void test_implementsAndOverrides_noRequiredParameter() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "abstract class I {", |
- " foo(x);", |
- "}", |
- "class C implements I {", |
- " foo() {}", |
- "}"); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_OVERRIDE_METHOD_NUM_REQUIRED_PARAMS, 5, 3, 3)); |
- } |
- |
- /** |
- * It is OK to add more named parameters, if list prefix is same as in "super". |
- */ |
- public void test_implementsAndOverrides_additionalNamedParameter() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "abstract class I {", |
- " foo({x});", |
- "}", |
- "class C implements I {", |
- " foo({x,y}) {}", |
- "}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_implementsAndOverrides_lessNamedParameter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "abstract class A {", |
- " foo({x, y});", |
- "}", |
- "abstract class B extends A {", |
- " foo({x});", |
- "}"); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_OVERRIDE_METHOD_NAMED_PARAMS, 5, 3, 3)); |
- } |
- |
- /** |
- * We override "foo" with method that has named parameter. So, this method is not abstract and |
- * class is not abstract too, so no warning. |
- */ |
- public void test_implementsAndOverrides_additionalNamedParameter_notAbstract() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "abstract class A {", |
- " foo();", |
- "}", |
- "class B extends A {", |
- " foo({x}) {}", |
- "}", |
- "bar() {", |
- " new B();", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_implementsAndOverrides_lessOptionalPositionalParameter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "abstract class A {", |
- " foo([x, y]);", |
- "}", |
- "abstract class B extends A {", |
- " foo([x]);", |
- "}"); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_OVERRIDE_METHOD_OPTIONAL_PARAMS, 5, 3, 3)); |
- } |
- |
- public void test_implementsAndOverrides_moreOptionalPositionalParameter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "abstract class A {", |
- " foo([x]);", |
- "}", |
- "abstract class B extends A {", |
- " foo([a, b]);", |
- "}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * No required parameter "x". Named parameter "x" is not enough. |
- */ |
- public void test_implementsAndOverrides_extraRequiredParameter() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "abstract class I {", |
- " foo();", |
- "}", |
- "class C implements I {", |
- " foo(x) {}", |
- "}"); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_OVERRIDE_METHOD_NUM_REQUIRED_PARAMS, 5, 3, 3)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3183 |
- */ |
- public void test_implementsAndOverrides_differentDefaultValue_optional() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " f1([x]) {}", |
- " f2([x = 1]) {}", |
- " f3([x = 1]) {}", |
- " f4([x = 1]) {}", |
- "}", |
- "class B extends A {", |
- " f1([x = 2]) {}", |
- " f2([x]) {}", |
- " f3([x = 2]) {}", |
- " f4([x = '2']) {}", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 10, 7, 1), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 11, 7, 5), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 12, 7, 7)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3183 |
- */ |
- public void test_implementsAndOverrides_differentDefaultValue_named() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " f1({x}) {}", |
- " f2({x: 1}) {}", |
- " f3({x: 1}) {}", |
- " f4({x: 1}) {}", |
- "}", |
- "class B extends A {", |
- " f1({x: 2}) {}", |
- " f2({x]) {}", |
- " f3({x: 2}) {}", |
- " f4({x: '2'}) {}", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 10, 7, 1), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 11, 7, 4), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_DEFAULT_VALUE, 12, 7, 6)); |
- } |
- |
- /** |
- * It is a compile-time error if an instance method m1 overrides an instance member m2 and m1 does |
- * not declare all the named parameters declared by m2 in the same order. |
- * <p> |
- * Here: no "y" parameter. |
- */ |
- public void test_implementsAndOverrides_noNamedParameter() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "abstract class I {", |
- " foo({x,y});", |
- "}", |
- "class C implements I {", |
- " foo({x}) {}", |
- "}"); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_OVERRIDE_METHOD_NAMED_PARAMS, 5, 3, 3)); |
- } |
- |
- public void test_metadataCommentOverride_OK_method() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " foo() {}", |
- "}", |
- "class B extends A {", |
- " // @override", |
- " foo() {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_metadataCommentOverride_Bad_method() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const override = 0;", |
- "class A {", |
- "}", |
- "class B extends A {", |
- " @override", |
- " foo() {}", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.INVALID_OVERRIDE_METADATA, 7, 3, 3)); |
- } |
- |
- public void testImplementsAndOverrides5() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "abstract class I {", |
- " foo({y,x});", |
- "}", |
- "class C implements I {", |
- " foo({x,y}) {}", |
- "}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=1936 |
- */ |
- public void test_propertyAccess_whenExtendsUnknown() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C extends Unknown {", |
- " foo() {", |
- " this.elements;", |
- " }", |
- "}"); |
- assertErrors(result.getErrors(), errEx(ResolverErrorCode.NO_SUCH_TYPE, 2, 17, 7)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3860 |
- */ |
- public void test_setterGetterDifferentStatic() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " static get field => 0;", |
- " set field(var v) {}", |
- "}", |
- "class B {", |
- " get field => 0;", |
- " static set field(var v) {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), |
- errEx(TypeErrorCode.FIELD_GETTER_SETTER_SAME_STATIC, 4, 14, 5), |
- errEx(TypeErrorCode.FIELD_GETTER_SETTER_SAME_STATIC, 8, 14, 5)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=380 |
- */ |
- public void test_setterGetterDifferentType() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {} ", |
- "class B extends A {}", |
- "class C {", |
- " A getterField; ", |
- " B setterField; ", |
- " A get field { return getterField; }", |
- " void set field(B arg) { setterField = arg; }", |
- "}", |
- "main() {", |
- " C instance = new C();", |
- " instance.field = new B();", |
- " A resultA = instance.field;", |
- " instance.field = new A();", |
- " B resultB = instance.field;", |
- "}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=7597 |
- */ |
- public void test_setterIsNotOverriddenByMethod() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " set foo(var v) {}", |
- "}", |
- "class C extends A {", |
- " foo(value) {}", |
- "}", |
- "main() {", |
- " C c = new C();", |
- " c.foo(1);", |
- " c.foo = 1;", |
- "}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- |
- public void test_setterGetterAssignable1() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {} ", |
- "A topGetterField; ", |
- "var topSetterField; ", |
- "A get topField { return topGetterField; }", |
- "void set topField(arg) { topSetterField = arg; }", |
- "class C {", |
- " A getterField; ", |
- " var setterField; ", |
- " A get field { return getterField; }", |
- " void set field(arg) { setterField = arg; }", |
- "}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_setterGetterAssignable2() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {} ", |
- "var topGetterField; ", |
- "A topSetterField; ", |
- "get topField { return topGetterField; }", |
- "void set topField(A arg) { topSetterField = arg; }", |
- "class C {", |
- " var getterField; ", |
- " A setterField; ", |
- " get field { return getterField; }", |
- " void set field(A arg) { setterField = arg; }", |
- "}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_setterGetterNotAssignable() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {} ", |
- "class B {}", |
- "A topGetterField; ", |
- "B topSetterField; ", |
- "A get topField { return topGetterField; }", |
- "void set topField(B arg) { topSetterField = arg; }", |
- "class C {", |
- " A getterField; ", |
- " B setterField; ", |
- " A get field { return getterField; }", |
- " void set field(B arg) { setterField = arg; }", |
- "}"); |
- assertErrors(result.getErrors(), |
- errEx(TypeErrorCode.SETTER_TYPE_MUST_BE_ASSIGNABLE, 7, 19, 5), |
- errEx(TypeErrorCode.SETTER_TYPE_MUST_BE_ASSIGNABLE, 12, 18, 5)); |
- } |
- |
- public void test_setterInvokedAsMethod() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " void set foo(String arg) {}", |
- "} ", |
- "method() {", |
- " C c = new C();", |
- " c.foo(1);", |
- "}"); |
- /* This could probably use a better error message. The user likely intends |
- * to set the property foo, but it is invoking foo as a getter and |
- * invoking the result. |
- */ |
- assertErrors(result.getErrors(), |
- errEx(TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, 7, 4, 3)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3221 |
- */ |
- public void test_conditionalExpressionType() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " bool x = (true ? 1 : 2.0);", |
- "}", ""); |
- List<DartCompilationError> errors = result.getErrors(); |
- assertErrors(errors, errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 3, 12, 16)); |
- { |
- String message = errors.get(0).getMessage(); |
- assertTrue(message.contains("'num'")); |
- assertTrue(message.contains("'bool'")); |
- } |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4394 |
- */ |
- public void test_conditionalExpressionType_genericInterface() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> { const A(); }", |
- "class B<T> extends A<T> { const B(); }", |
- "class C<T> implements B<T> { const C(); }", |
- "class D<T> implements B<T> { const D(); }", |
- "main() {", |
- " B<int> test = true ? new C<int>() : const D<int>();", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * https://codereview.chromium.org/12787002/ |
- */ |
- public void test_typeVariableBounds_12787002() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " m() {", |
- " B a = this;", |
- " }", |
- "}", |
- "class B extends A<String> {}"); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_typeVariableBoundsMismatch() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class I<T extends num> { }", |
- "class A<T extends num> implements I<T> { }", |
- "class B<T> implements I<T> { }"); // static type error B.T not assignable to num |
- assertErrors(result.getErrors(), errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 4, 25, 1)); |
- } |
- |
- public void test_typeVariableBoundsMismatch2() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C<T extends num> { }", |
- "class A<T extends num> extends C<T> { }", |
- "class B<T> extends C<T> { }"); // static type error B.T not assignable to num |
- assertErrors(result.getErrors(), errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 4, 22, 1)); |
- } |
- |
- public void test_typeVariableBoundsCheckNew() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "class Object {}", |
- "class A { }", |
- "class B { }", |
- "class C<T extends A> { }", |
- "method() {", |
- " new C<B>();", // B not assignable to A |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 6, 9, 1)); |
- } |
- |
- /** |
- * When we check getter/setter compatibility, we should compare propagated type variables. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3067 |
- */ |
- public void test_typeVariables_getterSetter() throws Exception { |
- AnalyzeLibraryResult result = |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Base1<T1> {", |
- " T1 get val {}", |
- "}", |
- "class Base2<T2> extends Base1<T2> {", |
- "}", |
- "class Sub<T3> extends Base2<T3> {", |
- " void set val(T3 value) {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_inferredTypes_noMemberWarnings() throws Exception { |
- // disabled by default |
- { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "foo(A a) {", |
- " var v = a;", |
- " v.f = 0;", |
- " v.m();", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- // use CompilerConfiguration to enable |
- { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean typeChecksForInferredTypes() { |
- return true; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "foo(A a) {", |
- " var v = a;", |
- " v.f = 0;", |
- " v.m();", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.NOT_A_MEMBER_OF_INFERRED, 5, 5, 1), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED_INFERRED, 6, 5, 1)); |
- } |
- } |
- |
- /** |
- * There was bug that for-in loop did not mark type of variable as inferred, so we produced |
- * warnings even when this is disabled. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4460 |
- */ |
- public void test_inferredTypes_noMemberWarnings_forInLoop() throws Exception { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean typeChecksForInferredTypes() { |
- return false; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "foo() {", |
- " List<A> values;", |
- " for (var v in values) {", |
- " v.bar();", |
- " }", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_inferredTypes_whenInvocationArgument_checkAssignable() throws Exception { |
- // disabled by default |
- { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B {}", |
- "foo(A a) {}", |
- "main() {", |
- " var v = new B();", |
- " foo(v);", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- // use CompilerConfiguration to enable |
- { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean typeChecksForInferredTypes() { |
- return true; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B {}", |
- "foo(A a) {}", |
- "main() {", |
- " var v = new B();", |
- " foo(v);", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE_INFERRED, 7, 7, 1)); |
- } |
- } |
- |
- /** |
- * When we resolved method from inferred type, it is possible that arguments of invocation |
- * don't is not assignable to the parameters. So, we report warning. But if we would not infer |
- * types, there would be no warnings. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4849 |
- */ |
- public void test_inferredTypes_invocationOfMethodFromInferredType_arguments() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " foo(int p) {}", |
- "}", |
- "main() {", |
- " var a = new A();", |
- " a.foo('');", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_typesPropagation_assignAtDeclaration() throws Exception { |
- analyzeLibrary( |
- "f() {", |
- " var v0 = true;", |
- " var v1 = true && false;", |
- " var v2 = 1;", |
- " var v3 = 1 + 2;", |
- " var v4 = 1.0;", |
- " var v5 = 1.0 + 2.0;", |
- " var v6 = new Map<String, int>();", |
- " var v7 = new Map().length;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v0", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v4", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v5", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v6", "Map<String, int>", INFERRED); |
- assertInferredElementTypeString(testUnit, "v7", "int", INFERRED); |
- } |
- |
- public void test_typesPropagation_arrayAccess() throws Exception { |
- analyzeLibrary( |
- "class A {}", |
- "class B extends A {}", |
- "List<A> list() => [new B()];", |
- "main() {", |
- " var v0 = list();", |
- " var v1 = list();", |
- " var v2 = v1[0];", |
- "}", |
- ""); |
- { |
- DartExpression expr = findNode(DartUnqualifiedInvocation.class, "list();"); |
- assertInferredElementTypeString(expr.getType(), "v0", "List<A>", EXACT); |
- } |
- assertInferredElementTypeString(testUnit, "v1", "List<A>", INFERRED); |
- { |
- DartExpression expr = findNode(DartArrayAccess.class, "v1[0]"); |
- assertInferredElementTypeString(expr.getType(), "v2", "A", INFERRED); |
- } |
- } |
- |
- /** |
- * We should infer types only if variable declared without type. |
- */ |
- public void test_typesPropagation_dontChangeDeclaredType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B extends A {}", |
- "main() {", |
- " B v = new B();", |
- " var v1 = v;", |
- " v = new A();", |
- " var v2 = v;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- assertInferredElementTypeString(testUnit, "v1", "B", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "B", INFERRED_EXACT); |
- } |
- |
- public void test_typesPropagation_multiAssign() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v = true;", |
- " var v1 = v;", |
- " v = 0;", |
- " var v2 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "int", INFERRED_EXACT); |
- } |
- |
- public void test_typesPropagation_multiAssign_noInitialValue() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v;", |
- " v = 0;", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT); |
- } |
- |
- public void test_typesPropagation_multiAssign_IfThen() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v = true;", |
- " var v1 = v;", |
- " if (true) {", |
- " v = 0;", |
- " var v2 = v;", |
- " }", |
- " var v3 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "Object", INFERRED); |
- } |
- |
- public void test_typesPropagation_multiAssign_IfThenElse() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var a = true;", |
- " var b = true;", |
- " var c = true;", |
- " var d = true;", |
- " if (true) {", |
- " a = 0;", |
- " b = 0;", |
- " } else {", |
- " a = 0;", |
- " c = 0;", |
- " }", |
- " var a1 = a;", |
- " var b1 = b;", |
- " var c1 = c;", |
- " var d1 = d;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "a1", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "b1", "Object", INFERRED); |
- assertInferredElementTypeString(testUnit, "c1", "Object", INFERRED); |
- assertInferredElementTypeString(testUnit, "d1", "bool", INFERRED_EXACT); |
- } |
- |
- public void test_typesPropagation_multiAssign_IfThenElse_whenAsTypeCondition() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (v is String) {", |
- " var v1 = v;", |
- " v = null;", |
- " } else {", |
- " var v2 = v;", |
- " }", |
- " var v3 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_multiAssign_While() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v = true;", |
- " var v1 = v;", |
- " while (true) {", |
- " var v2 = v;", |
- " v = 0;", |
- " var v3 = v;", |
- " }", |
- " var v4 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v4", "Object", INFERRED); |
- } |
- |
- public void test_typesPropagation_multiAssign_DoWhile() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v = true;", |
- " var v1 = v;", |
- " do {", |
- " var v2 = v;", |
- " v = 0;", |
- " var v3 = v;", |
- " } while (true);", |
- " var v4 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v4", "int", INFERRED_EXACT); |
- } |
- |
- public void test_typesPropagation_multiAssign_For() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v = true;", |
- " var v1 = v;", |
- " for (int i = 0; i < 10; i++) {", |
- " var v2 = v;", |
- " v = 0;", |
- " var v3 = v;", |
- " }", |
- " var v4 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v4", "Object", INFERRED); |
- } |
- |
- public void test_typesPropagation_multiAssign_ForIn() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v = true;", |
- " var v1 = v;", |
- " List<String> names = [];", |
- " for (var name in names) {", |
- " var v2 = v;", |
- " v = 0;", |
- " var v3 = v;", |
- " }", |
- " var v4 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "bool", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v4", "Object", INFERRED); |
- } |
- |
- /** |
- * We should understand type with type arguments and choose the most generic version. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4792 |
- */ |
- public void test_typesPropagation_multiAssign_withGenerics_type_type() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var a = new List<String>();", |
- " var b = <Object>[];", |
- " if (true) {", |
- " a = <Object>[];", |
- " b = new List<String>();", |
- " }", |
- " var a1 = a;", |
- " var b1 = b;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "a1", "List<Object>", INFERRED); |
- assertInferredElementTypeString(testUnit, "b1", "List<Object>", INFERRED); |
- } |
- |
- /** |
- * Prefer specific type, not "dynamic" type argument. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4792 |
- */ |
- public void test_typesPropagation_multiAssign_withGenerics_type_dynamic() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var a = new List<String>();", |
- " var b = [];", |
- " if (true) {", |
- " a = [];", |
- " b = new List<String>();", |
- " }", |
- " var a1 = a;", |
- " var b1 = b;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "a1", "List<String>", INFERRED); |
- assertInferredElementTypeString(testUnit, "b1", "List<String>", INFERRED); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4791 |
- */ |
- public void test_typesPropagation_multiAssign_type_null() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v = null;", |
- " var v1 = v;", |
- " if (true) {", |
- " v = '';", |
- " var v2 = v;", |
- " }", |
- " var v3 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "String", INFERRED); |
- } |
- |
- /** |
- * There was bug that when we analyze assignment in initializer, we don't have context. |
- */ |
- public void test_typesPropagation_multiAssign_assignmentOutsideFunction() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " A(p) {}", |
- "}", |
- "class B extends A {", |
- " B(p) : super(p = 0) {}", |
- "}", |
- ""); |
- // no exceptions |
- } |
- |
- /** |
- * When we can not identify type of assigned value we should keep "dynamic" as type of variable. |
- */ |
- public void test_typesPropagation_assign_newUnknownType() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f() {", |
- " var v1 = new Unknown();", |
- " var v2 = new Unknown.name();", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifAsType() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if ((v as String).length != 0) {", |
- " var v1 = v;", |
- " }", |
- " var v2 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "dynamic", EXACT); |
- } |
- |
- /** |
- * Even if there is negation, we still apply "as" cast, so visit "then" statement only if cast was |
- * successful. |
- */ |
- public void test_typesPropagation_ifAsType_negation() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (!(v as String).isEmpty()) {", |
- " var v1 = v;", |
- " }", |
- " var v2 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifIsType() throws Exception { |
- analyzeLibrary( |
- "f(var v) {", |
- " if (v is List<String>) {", |
- " var v1 = v;", |
- " }", |
- " if (v is Map<int, String>) {", |
- " var v2 = v;", |
- " }", |
- " var v3 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "List<String>", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "Map<int, String>", INFERRED); |
- assertInferredElementTypeString(testUnit, "v3", "dynamic", EXACT); |
- } |
- |
- /** |
- * We should not make variable type less specific, even if there is such (useless) user code. |
- */ |
- public void test_typesPropagation_ifIsType_mostSpecific() throws Exception { |
- analyzeLibrary( |
- "f() {", |
- " int a;", |
- " num b;", |
- " if (a is num) {", |
- " var a1 = a;", |
- " }", |
- " if (a is dynamic) {", |
- " var a2 = a;", |
- " }", |
- " if (b is int) {", |
- " var b1 = b;", |
- " }", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "a1", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "a2", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "b1", "int", INFERRED); |
- } |
- |
- /** |
- * When single variable has conflicting type constraints, we use union of types. |
- */ |
- public void test_typesPropagation_ifIsType_conflictingTypes() throws Exception { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean typeChecksForInferredTypes() { |
- return true; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(int v) {", |
- " if (v is String) {", |
- " var v1 = v;", |
- " // should be OK because 'v' is String", |
- " v.abs; // from num", |
- " v.length; // from String", |
- " processInt(v);", |
- " processString(v);", |
- " }", |
- "}", |
- "processInt(int p) {}", |
- "processString(String p) {}", |
- ""); |
- // should be no errors, we because "v" is String |
- assertErrors(result.getErrors()); |
- assertInferredElementTypeString(testUnit, "v1", "[int, String]", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsType_negation() throws Exception { |
- analyzeLibrary( |
- "f(var v) {", |
- " if (v is! String) {", |
- " var v1 = v;", |
- " }", |
- " if (!(v is String)) {", |
- " var v2 = v;", |
- " }", |
- " if (!!(v is String)) {", |
- " var v3 = v;", |
- " }", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsType_and() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var a, var b) {", |
- " if (a is String && b is List<String>) {", |
- " var a1 = a;", |
- " var b1 = b;", |
- " }", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "a1", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "b1", "List<String>", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsType_or() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (true || v is String) {", |
- " var v1 = v;", |
- " }", |
- " if (v is String || true) {", |
- " var v2 = v;", |
- " }", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_whileIsType() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " var v = null;", |
- " while (v is String) {", |
- " var v1 = v;", |
- " }", |
- " var v2 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_forIsType() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " var v = null;", |
- " for (; v is String; () {var v2 = v;} ()) {", |
- " var v1 = v;", |
- " }", |
- " var v3 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "v3", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_forEach() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " List<String> values = [];", |
- " for (var v in values) {", |
- " var v1 = v;", |
- " }", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_withElse() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (v is! String) {", |
- " var v1 = v;", |
- " } else {", |
- " var v2 = v;", |
- " }", |
- " var v3 = v;", |
- "}", |
- ""); |
- // we don't know type, but not String |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- // we know that String |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED); |
- // again, we don't know after "if" |
- assertInferredElementTypeString(testUnit, "v3", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_hasThenReturn() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " var v1 = v;", |
- " if (v is! String) {", |
- " return;", |
- " }", |
- " var v2 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_hasThenThrow() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (v is! String) {", |
- " throw new Exception();", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_emptyThen() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (v is! String) {", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_otherThen() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (v is! String) {", |
- " ;", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_hasThenThrow_withCatch() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " try {", |
- " if (v is! String) {", |
- " throw new Exception();", |
- " }", |
- " } catch (var e) {", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_hasThenContinue() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " for (var v in <Object>[1, 'two', 3]) {", |
- " var v1 = v;", |
- " if (v is! String) {", |
- " continue;", |
- " }", |
- " var v2 = v;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- assertInferredElementTypeString(testUnit, "v1", "Object", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_hasThenBreak() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " for (var v in <Object>[1, 'two', 3]) {", |
- " var v1 = v;", |
- " if (v is! String) {", |
- " break;", |
- " }", |
- " var v2 = v;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- assertInferredElementTypeString(testUnit, "v1", "Object", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_or() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var p1, var p2) {", |
- " if (p1 is! int || p2 is! String) {", |
- " return;", |
- " }", |
- " var v1 = p1;", |
- " var v2 = p2;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_and() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (v is! String && true) {", |
- " return;", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_not() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (!(v is! String)) {", |
- " return;", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_ifIsNotType_not2() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (!!(v is! String)) {", |
- " return;", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- } |
- |
- public void test_typesPropagation_ifNotIsType() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(var v) {", |
- " if (!(v is String)) {", |
- " return;", |
- " }", |
- " var v1 = v;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "String", INFERRED); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4410 |
- */ |
- public void test_typesPropagation_assertIsType() throws Exception { |
- analyzeLibrary( |
- "f(var v) {", |
- " if (true) {", |
- " var v1 = v;", |
- " assert(v is String);", |
- " var v2 = v;", |
- " {", |
- " var v3 = v;", |
- " }", |
- " var v4 = v;", |
- " }", |
- " var v5 = v;", |
- "}", |
- ""); |
- // we don't know type initially |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- // after "assert" all next statements know type |
- assertInferredElementTypeString(testUnit, "v2", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "v3", "String", INFERRED); |
- // type is set to unknown only when we exit control Block, not just any Block |
- assertInferredElementTypeString(testUnit, "v4", "String", INFERRED); |
- // we exited "if" Block, so "assert" may be was not executed, so we don't know type |
- assertInferredElementTypeString(testUnit, "v5", "dynamic", EXACT); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4410 |
- */ |
- public void test_typesPropagation_assertIsType_twoVariables() throws Exception { |
- analyzeLibrary( |
- "f(a, b) {", |
- " while (true) {", |
- " var a1 = a;", |
- " var b1 = b;", |
- " assert(a is String);", |
- " assert(b is String);", |
- " var a2 = a;", |
- " var b2 = b;", |
- " }", |
- " var a3 = a;", |
- " var b3 = b;", |
- "}", |
- ""); |
- // we don't know type initially |
- assertInferredElementTypeString(testUnit, "a1", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "b1", "dynamic", EXACT); |
- // after "assert" all next statements know type |
- assertInferredElementTypeString(testUnit, "a2", "String", INFERRED); |
- assertInferredElementTypeString(testUnit, "b2", "String", INFERRED); |
- // we exited "if" Block, so "assert" may be was not executed, so we don't know type |
- assertInferredElementTypeString(testUnit, "a3", "dynamic", EXACT); |
- assertInferredElementTypeString(testUnit, "b3", "dynamic", EXACT); |
- } |
- |
- /** |
- * When variable has explicit type, we should not fall to 'dynamic', we need to keep this type. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6399 |
- */ |
- public void test_typesPropagation_assertIsType_hasExplicitType() throws Exception { |
- analyzeLibrary( |
- "class A {}", |
- "class B extends A {}", |
- "class C extends B {}", |
- "main() {", |
- " B v;", |
- " if (v is A) {", |
- " var v1 = v;", |
- " }", |
- " if (v is B) {", |
- " var v2 = v;", |
- " }", |
- " if (v is C) {", |
- " var v3 = v;", |
- " }", |
- " if (v is String) {", |
- " var v4 = v;", |
- " }", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "B", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "B", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "C", INFERRED); |
- assertInferredElementTypeString(testUnit, "v4", "[B, String]", INFERRED); |
- } |
- |
- public void test_typesPropagation_field_inClass_final() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " final v1 = 123;", |
- " final v2 = 1 + 2.0;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT); |
- } |
- |
- public void test_typesPropagation_field_inClass_const() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " const v1 = 123;", |
- " final v2 = 1 + 2.0;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT); |
- } |
- |
- /** |
- * If field is not final, we don't know if is will be assigned somewhere else, may be even not in |
- * there same unit, so we cannot be sure about its type. |
- */ |
- public void test_typesPropagation_field_inClass_notFinal() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var v1 = 123;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_field_topLevel_final() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "final v1 = 123;", |
- "final v2 = 1 + 2.0;", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT); |
- } |
- |
- public void test_typesPropagation_field_topLevel_const() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const v1 = 123;", |
- "const v2 = 1 + 2.0;", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "double", INFERRED_EXACT); |
- } |
- |
- /** |
- * If field is not final, we don't know if is will be assigned somewhere else, may be even not in |
- * there same unit, so we cannot be sure about its type. |
- */ |
- public void test_typesPropagation_field_topLevel_notFinal() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "var v1 = 123;", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "dynamic", EXACT); |
- } |
- |
- public void test_typesPropagation_FunctionAliasType() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "typedef F();", |
- "foo(F f) {", |
- " var v = f;", |
- " v();", |
- "}", |
- "", |
- ""); |
- assertInferredElementTypeString(testUnit, "v", "F", INFERRED_EXACT); |
- } |
- |
- /** |
- * When we pass "function literal" into invocation on some method, we may know exact |
- * <code>Function</code> type expected by this method, so we know types of "function literal" |
- * parameters. So, if these types are not specified in "function literal", we can use "expected" |
- * types. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3712 |
- */ |
- public void test_typesPropagation_parameterOfClosure_invocationNormalParameter() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "typedef void EventListener(Event event);", |
- "foo(EventListener listener) {", |
- "}", |
- "main() {", |
- " foo((e) {", |
- " var v = e;", |
- " });", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v", "Event", INFERRED); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3712 |
- */ |
- public void test_typesPropagation_parameterOfClosure_invocationNamedPositionalParameter() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "typedef void EventListener(Event event);", |
- "foo([EventListener listener]) {", |
- "}", |
- "main() {", |
- " foo((e) {", |
- " var v = e;", |
- " });", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v", "Event", INFERRED); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3712 |
- */ |
- public void test_typesPropagation_parameterOfClosure_invocationNamedParameter() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "typedef void EventListener(Event event);", |
- "foo({EventListener listener}) {", |
- "}", |
- "main() {", |
- " foo(listener: (e) {", |
- " var v = e;", |
- " });", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v", "Event", INFERRED); |
- } |
- |
- /** |
- * http://code.google.com/p/dart/issues/detail?id=3712 |
- */ |
- public void test_typesPropagation_parameterOfClosure_invocationOfMethod() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "typedef void EventListener(Event event);", |
- "class Button {", |
- " onClick(EventListener listener) {", |
- " }", |
- "}", |
- "main() {", |
- " Button button = new Button();", |
- " button.onClick((e) {", |
- " var v = e;", |
- " });", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v", "Event", INFERRED); |
- } |
- |
- /** |
- * We should infer closure parameter types even in {@link FunctionType} is specified directly, |
- * without using {@link FunctionAliasType}. |
- */ |
- public void test_typesPropagation_parameterOfClosure_functionType() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "class Button<T> {", |
- " onClick(listener(T e)) {", |
- " }", |
- "}", |
- "main() {", |
- " var button = new Button<Event>();", |
- " button.onClick((e) {", |
- " var v = e;", |
- " });", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v", "Event", INFERRED); |
- } |
- |
- public void test_typesPropagation_parameterOfClosure_assignVariable() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "typedef void EventListener(Event event);", |
- "main() {", |
- " // local variable assign", |
- " {", |
- " EventListener listener;", |
- " listener = (e) {", |
- " var v1 = e;", |
- " };", |
- " }", |
- " // local variable declare", |
- " {", |
- " EventListener listener = (e) {", |
- " var v2 = e;", |
- " };", |
- " }", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "Event", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "Event", INFERRED); |
- } |
- |
- public void test_typesPropagation_parameterOfClosure_assignField() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "typedef void EventListener(Event event);", |
- "class Button {", |
- " EventListener listener;", |
- "}", |
- "EventListener topLevelListener;", |
- "main() {", |
- " // top-level field", |
- " {", |
- " topLevelListener = (e) {", |
- " var v1 = e;", |
- " };", |
- " }", |
- " // member field", |
- " {", |
- " Button button = new Button();", |
- " button.listener = (e) {", |
- " var v2 = e;", |
- " };", |
- " }", |
- "}", |
- "EventListener topLevelListener2 = (e) {", |
- " var v3 = e;", |
- "};", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "Event", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "Event", INFERRED); |
- assertInferredElementTypeString(testUnit, "v3", "Event", INFERRED); |
- } |
- |
- /** |
- * Sometimes inferred type is too generic - such as "Object" or "Collection", so there are no |
- * reason to reports problems. |
- */ |
- public void deprecatedCollection_test_typesPropagation_dontWant_ifTooGeneric() throws Exception { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean typeChecksForInferredTypes() { |
- return true; |
- } |
- }); |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "typedef void HandlerObject(Object o);", |
- "typedef void HandlerCollection(Collection o);", |
- "fObject(HandlerObject h) {}", |
- "fCollection(HandlerCollection h) {}", |
- "main() {", |
- " fObject((x) {", |
- " x.myNoSuchField;", |
- " x.myNoSuchMethod();", |
- " });", |
- " fCollection((x) {", |
- " x.myNoSuchField;", |
- " x.myNoSuchMethod();", |
- " });", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * Helpful (but not perfectly satisfying Specification) type of "conditional" is intersection of |
- * then/else types, not just their "least upper bounds". And this corresponds runtime behavior. |
- */ |
- public void test_typesPropagation_conditional() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class I1 {", |
- " f1();", |
- "}", |
- "abstract class I2 {", |
- " f2();", |
- "}", |
- "class A implements I1, I2 {", |
- " f1() => 11;", |
- " f2() => 12;", |
- "}", |
- "class B implements I1, I2 {", |
- " f1() => 21;", |
- " f2() => 22;", |
- "}", |
- "main() {", |
- " var v = true ? new A() : new B();", |
- " v.f1();", |
- " v.f2();", |
- "}", |
- ""); |
- // no errors, because both f1() and f2() invocations were resolved |
- assertErrors(libraryResult.getErrors()); |
- // v.f1() was resolved |
- { |
- DartExpression expression = findNodeBySource(testUnit, "v.f1()"); |
- assertNotNull(expression); |
- assertNotNull(expression.getElement()); |
- } |
- // v.f2() was resolved |
- { |
- DartExpression expression = findNodeBySource(testUnit, "v.f1()"); |
- assertNotNull(expression); |
- assertNotNull(expression.getElement()); |
- } |
- } |
- |
- public void test_getType_binaryExpression() throws Exception { |
- analyzeLibrary( |
- "f(var arg) {", |
- " var v1 = 1 + 2;", |
- " var v2 = 1 - 2;", |
- " var v3 = 1 * 2;", |
- " var v4 = 1 ~/ 2;", |
- " var v5 = 1 % 2;", |
- " var v6 = 1 / 2;", |
- " var v7 = 1.0 + 2;", |
- " var v8 = 1 + 2.0;", |
- " var v9 = 1 - 2.0;", |
- " var v10 = 1.0 - 2;", |
- " var v11 = 1 * 2.0;", |
- " var v12 = 1.0 * 2;", |
- " var v13 = 1.0 / 2;", |
- " var v14 = 1 / 2.0;", |
- " var v15 = 1.0 ~/ 2.0;", |
- " var v16 = 1.0 ~/ 2;", |
- " var v17 = arg as int", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v2", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v3", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v4", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v5", "int", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v6", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v7", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v8", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v9", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v10", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v11", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v12", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v13", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v14", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v15", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v16", "double", INFERRED_EXACT); |
- assertInferredElementTypeString(testUnit, "v17", "int", INFERRED); |
- } |
- |
- /** |
- * It was requested that even if Editor can be helpful and warn about types incompatibility, it |
- * should not do this to completely satisfy specification. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3223 |
- * <p> |
- * This feature was requested by users, so we introduce it again, but disabled to command line. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4518 |
- */ |
- public void test_typesPropagation_noExtraWarnings() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "f(int v) {}", |
- "f1() {", |
- " var v = true;", |
- " f(v);", |
- "}", |
- "f2(var v) {", |
- " if (v is bool) {", |
- " f(v);", |
- " }", |
- "}", |
- "f3(var v) {", |
- " while (v is bool) {", |
- " f(v);", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * There was problem that using <code>() -> bool</code> getter in negation ('!') caused assignment |
- * warnings. Actual reason was that with negation getter access is visited twice and on the second |
- * time type of getter method, instead of return type, was returned. |
- */ |
- public void test_getType_getterInNegation() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "class A {", |
- " int get intProperty => 42;", |
- " bool get boolProperty => true;", |
- "}", |
- "f() {", |
- " var a = new A();", |
- " var v1 = a.intProperty;", |
- " var v2 = a.boolProperty;", |
- " if (a.boolProperty) {", |
- " }", |
- " if (!a.boolProperty) {", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- assertInferredElementTypeString(testUnit, "v1", "int", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "bool", INFERRED); |
- } |
- |
- public void test_getType_getterInNegation_generic() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "class A<T> {", |
- " T field;", |
- " T get prop => null;", |
- "}", |
- "f() {", |
- " var a = new A<bool>();", |
- " var v1 = a.field;", |
- " var v2 = a.prop;", |
- " if (a.field) {", |
- " }", |
- " if (!a.field) {", |
- " }", |
- " if (a.prop) {", |
- " }", |
- " if (!a.prop) {", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- assertInferredElementTypeString(testUnit, "v1", "bool", INFERRED); |
- assertInferredElementTypeString(testUnit, "v2", "bool", INFERRED); |
- } |
- |
- public void test_getType_getterInSwitch_default() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "int get foo {}", |
- "f() {", |
- " switch (true) {", |
- " default:", |
- " int v = foo;", |
- " break;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3515 |
- */ |
- public void test_getType_getterInSwitchExpression_topLevel() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "int get foo => 42;", |
- "f() {", |
- " switch (foo) {", |
- " case 2:", |
- " break;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3515 |
- */ |
- public void test_getType_getterInSwitchExpression_inClass() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " T get foo => null;", |
- "}", |
- "f() {", |
- " A<int> a = new A<int>();", |
- " switch (a.foo) {", |
- " case 2:", |
- " break;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3272 |
- */ |
- public void test_assignVoidToDynamic() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "void foo() {}", |
- "main() {", |
- " var v = foo();", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5114 |
- */ |
- public void test_lowerCaseDynamicType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " dynamic v = null;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=7980 |
- */ |
- public void test_whenVariableNamedDynamic() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " var dynamic = 42;", |
- " new List<dynamic>();", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NOT_A_TYPE, 4, 12, 7)); |
- } |
- |
- /** |
- * It is a static warning if the return type of the user-declared operator == is explicitly |
- * declared and not bool. |
- */ |
- public void test_equalsOperator_type() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " bool operator ==(other) {}", |
- "}", |
- "class B {", |
- " String operator ==(other) {}", |
- "}", |
- "class C {", |
- " Object operator ==(other) {}", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE, 6, 19, 2), |
- errEx(TypeErrorCode.OPERATOR_EQUALS_BOOL_RETURN_TYPE, 6, 3, 6), |
- errEx(TypeErrorCode.OPERATOR_EQUALS_BOOL_RETURN_TYPE, 9, 3, 6)); |
- } |
- |
- /** |
- * We should be able to resolve "a == b" to the "equals" operator. |
- */ |
- public void test_equalsOperator_resolving() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " operator ==(other) => false;", |
- "}", |
- "main() {", |
- " new C() == new C();", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // find == expression |
- DartExpression expression = findNodeBySource(testUnit, "new C() == new C()"); |
- assertNotNull(expression); |
- // validate == element |
- MethodElement equalsElement = (MethodElement) expression.getElement(); |
- assertNotNull(equalsElement); |
- } |
- |
- /** |
- * We can not override getter. But setter has name "setter=", so there are no conflict. |
- */ |
- public void test_supertypeHasMethod() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "abstract class I {", |
- " foo();", |
- " bar();", |
- "}", |
- "abstract class J implements I {", |
- " get foo;", |
- " set bar(x);", |
- "}"); |
- assertErrors(libraryResult.getErrors(), |
- errEx(TypeErrorCode.SUPERTYPE_HAS_METHOD, 8, 7, 3)); |
- } |
- |
- /** |
- * Ensure that "operator call()" is parsed, and "operator" is not considered as return type. This |
- * too weak test, but for now we are interested only in parsing. |
- */ |
- public void test_callOperator_parsing() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " operator call() => 42;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * The spec in the section 10.28 says: |
- * "It is a compile-time error to use a built-in identifier other than dynamic as a type annotation." |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3307 |
- */ |
- public void test_builtInIdentifier_asTypeAnnotation() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " abstract v01;", |
- " as v02;", |
- " dynamic v03;", |
- " export v04;", |
- " external v05;", |
- " factory v06;", |
- " get v07;", |
- " implements v08;", |
- " import v09;", |
- " library v10;", |
- " operator v11;", |
- " part v12;", |
- " set v13;", |
- " static v14;", |
- "// typedef v15;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 3, 3, 8), // abstract |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 4, 3, 2), // as |
- // dynamic |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 6, 3, 6), // export |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 7, 3, 8), // external |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 8, 3, 7), // factory |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 9, 3, 3), // get |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 10, 3, 10), // implements |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 11, 3, 6), // import |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 12, 3, 7), // library |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 13, 3, 8), // operator |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 14, 3, 4), // part |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 15, 3, 3), // set |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 16, 3, 6) // static |
-// ,errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 17, 3, 7) // typedef |
- ); |
- } |
- |
- public void test_supertypeHasField() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var foo;", |
- " var bar;", |
- "}", |
- "class B extends A {", |
- " foo() {}", |
- " bar() {}", |
- "}"); |
- assertErrors(libraryResult.getErrors(), |
- errEx(TypeErrorCode.SUPERTYPE_HAS_FIELD, 7, 3, 3), |
- errEx(TypeErrorCode.SUPERTYPE_HAS_FIELD, 8, 3, 3)); |
- } |
- |
- /** |
- * We can not override getter. But setter has name "setter=", so there are no conflict. |
- */ |
- public void test_supertypeHasGetterSetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " get foo => 0;", |
- " set bar(x) {}", |
- "}", |
- "class B extends A {", |
- " foo() {}", |
- " bar() {}", |
- "}"); |
- assertErrors(libraryResult.getErrors(), |
- errEx(TypeErrorCode.SUPERTYPE_HAS_FIELD, 7, 3, 3)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3280 |
- */ |
- public void test_typeVariableExtendsFunctionAliasType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "typedef void F();", |
- "class C<T extends F> {", |
- " test() {", |
- " new C<T>();", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3344 |
- */ |
- public void test_typeVariableExtendsTypeVariable() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T, U extends T> {", |
- " f1(U u) {", |
- " T t = u;", |
- " }", |
- " f2(T t) {", |
- " U u = t;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_staticMemberAccessThroughInstance() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " static var x;", |
- " static y() {}", |
- " static method() {", |
- " var a = new A();", |
- " a.x = 1;", |
- " var foo = a.x;", |
- " a.y();", |
- " a.y = 1;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors(), |
- errEx(TypeErrorCode.STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE, 7, 7, 1), |
- errEx(TypeErrorCode.STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE, 8, 17, 1), |
- errEx(TypeErrorCode.IS_STATIC_METHOD_IN, 9, 7, 1), |
- errEx(TypeErrorCode.STATIC_MEMBER_ACCESSED_THROUGH_INSTANCE, 10, 7, 1), |
- errEx(TypeErrorCode.CANNOT_ASSIGN_TO, 10, 5, 3)); |
- } |
- |
- public void testExpectedPositionalArgument() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "method1(a, [b]) {}", |
- "method2() {", |
- " method1(b:1);", |
- "}"); |
- assertErrors(libraryResult.getErrors(), |
- errEx(TypeErrorCode.EXPECTED_POSITIONAL_ARGUMENT, 4, 11, 3)); |
- } |
- |
- public void test_cannotResolveMethod_unqualified() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " f() {", |
- " foo();", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 4, 5, 3)); |
- } |
- |
- public void test_canNotResolveMethod_qualified() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a.foo();", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 6, 5, 3)); |
- } |
- |
- public void test_operatorLocation() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a + 0;", |
- " -a;", |
- " a--;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 6, 5, 1), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 7, 3, 1), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 8, 4, 2)); |
- } |
- |
- /** |
- * It is a static warning if T does not denote a type available in the current lexical scope. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=2373 |
- */ |
- public void test_asType_unknown() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " null as T;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NO_SUCH_TYPE, 3, 11, 1)); |
- } |
- |
- /** |
- * It is a compile-time error if T is a parameterized type of the form G < T1; : : : ; Tn > and G |
- * is not a generic type with n type parameters. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=2373 |
- */ |
- public void test_asType_wrongNumberOfTypeArguments() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "main() {", |
- " null as A<int, bool>;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 4, 11, 12)); |
- } |
- |
- /** |
- * It is a static warning if T does not denote a type available in the current lexical scope. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=2373 |
- */ |
- public void test_isType_unknown() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " null is T;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NO_SUCH_TYPE, 3, 11, 1)); |
- } |
- |
- public void test_incompatibleTypesInHierarchy1() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class Interface<T> {", |
- " T m();", |
- "}", |
- "abstract class A implements Interface {", |
- "}", |
- "class C extends A implements Interface<int> {", |
- " int m() => 0;", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors()); |
- } |
- |
- public void test_incompatibleTypesInHierarchy2() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class Interface<T> {", |
- " T m();", |
- "}", |
- "abstract class A implements Interface<String> {", |
- "}", |
- "class C extends A implements Interface<int> {", |
- " int m() => 0;", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_METHOD_NOT_SUBTYPE, 8, 7, 1), |
- errEx(TypeErrorCode.INCOMPATIBLE_TYPES_IN_HIERARCHY, 7, 7, 1)); |
- } |
- |
- public void test_variableUsedAsType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "var func;", |
- "func i;"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NOT_A_TYPE, 3, 1, 4)); |
- } |
- |
- public void test_metadataComment_deprecated_1() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const deprecated = 0;", |
- "@deprecated", |
- "ttt() {}", |
- "@deprecated", |
- "get topLevelGet => 42;", |
- "class A {", |
- " var @deprecated fff;", |
- " @deprecated", |
- " mmmm() {}", |
- " @deprecated", |
- " operator + (other) {}", |
- "}", |
- "method() {", |
- " ttt();", |
- " print(topLevelGet);", |
- " A a = new A();", |
- " a.fff = 0;", |
- " a.mmmm();", |
- " a + 0;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 16, 9, 11), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 15, 3, 3), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 18, 5, 3), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 19, 5, 4), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 20, 5, 1)); |
- } |
- |
- public void test_metadataComment_deprecated_2() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const deprecated = 0;", |
- "@deprecated", |
- "class A {", |
- " A.named() {}", |
- " @deprecated", |
- " A.depreca() {}", |
- "}", |
- "method() {", |
- " new A.named();", |
- " new A.depreca();", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 10, 7, 1), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 11, 7, 1), |
- errEx(TypeErrorCode.DEPRECATED_ELEMENT, 11, 9, 7)); |
- } |
- |
- public void test_metadata_resolving() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const test = 0;", |
- "", |
- "@test", |
- "class A {", |
- " @test", |
- " m(@test p) {", |
- " @test var v = 0;", |
- " }", |
- "}", |
- "", |
- "f(@test p) {}", |
- "", |
- "@test typedef F();", |
- "", |
- ""); |
- // @deprecated should be resolved at every place, so no errors |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_assignMethod() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " method() { }", |
- "}", |
- "main () {", |
- " new C().method = f;", |
- "}", |
- "f() {}", |
- ""); |
- assertErrors(libraryResult.getErrors(), errEx(TypeErrorCode.CANNOT_ASSIGN_TO, 6, 3, 14)); |
- } |
- |
- public void test_assignSetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " set method(arg) { }", |
- "}", |
- "main () {", |
- " new C().method = f;", |
- "}", |
- "f() {}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_assignGetter() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " get method { }", |
- "}", |
- "main () {", |
- " new C().method = f;", |
- "}", |
- "f() {}", |
- ""); |
- assertErrors(libraryResult.getErrors(), errEx(TypeErrorCode.FIELD_HAS_NO_SETTER, 6, 11, 6)); |
- } |
- |
- /** |
- * Test for "operator []=". |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4881 |
- */ |
- public void test_assignArrayElement() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {" + |
- " get method { }", |
- " operator []=(k, v) {}", |
- "}", |
- "main () {", |
- " new C()[0] = 1;", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors()); |
- } |
- |
- /** |
- * Test for resolving variants of array access and unary/binary expressions. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5042 |
- */ |
- public void test_opAssignArrayElement() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " B operator [](k) => new B();", |
- " operator []=(k, v) { }", |
- "}", |
- "class B {", |
- " B operator +(x) => new B();", |
- "}", |
- "main () {", |
- " var a = new A();", |
- " process( a[2] );", |
- " a[0]++;", |
- " ++a[0];", |
- " a[0] += 1;", |
- " a[0] = 1;", |
- "}", |
- "process(x) {}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // print( a[2] ) |
- { |
- DartArrayAccess access = findNode(DartArrayAccess.class, "a[2]"); |
- // a[2] is invocation of method "[]" |
- assertHasMethodElement(access, "A", "[]"); |
- } |
- // a[0]++ |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "a[0]++"); |
- // a[0]++ is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // a[0] is invocation of method [] |
- assertHasMethodElement(unary.getArg(), "A", "[]"); |
- } |
- // ++a[0] |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "++a[0]"); |
- // ++a[0] is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // a[0] is invocation of method [] |
- assertHasMethodElement(unary.getArg(), "A", "[]"); |
- } |
- // a[0] += 1 |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "a[0] += 1"); |
- // a[0] += 1 is invocation of method "+" |
- assertHasMethodElement(binary, "B", "+"); |
- // a[0] is invocation of method [] |
- assertHasMethodElement(binary.getArg1(), "A", "[]"); |
- } |
- // a[0] = 1 |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "a[0] = 1"); |
- // a[0] = 1 is invocation of method "[]=" |
- assertHasMethodElement(binary, "A", "[]="); |
- // a[0] is invocation of method []= |
- assertHasMethodElement(binary.getArg1(), "A", "[]="); |
- } |
- } |
- |
- /** |
- * Test for resolving variants of property access and unary/binary expressions. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5049 |
- */ |
- public void test_opAssignPropertyAccess_instance() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " B get b => new B();", |
- " set b(B x) {}", |
- "}", |
- "class B {", |
- " B operator +(x) => new B();", |
- "}", |
- "main () {", |
- " A a = new A();", |
- " process( a.b );", |
- " a.b++;", |
- " ++a.b;", |
- " a.b += 1;", |
- " a.b = null;", |
- "}", |
- "process(x) {}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // print( a.b ) |
- { |
- DartPropertyAccess access = findNode(DartPropertyAccess.class, "a.b"); |
- // a.b is field "A.b" |
- assertHasFieldElement(access, "A", "b"); |
- } |
- // a.b++ |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "a.b++"); |
- // a.b++ is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // a.b is field "A.b" |
- assertHasFieldElement(unary.getArg(), "A", "b"); |
- } |
- // ++a.b |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "++a.b"); |
- // ++a.b is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // a.b is field "A.b" |
- assertHasFieldElement(unary.getArg(), "A", "b"); |
- } |
- // a.b += 1 |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "a.b += 1"); |
- // a.b += 1 is invocation of method "+" |
- assertHasMethodElement(binary, "B", "+"); |
- // a.b is field "A.b" |
- assertHasFieldElement(binary.getArg1(), "A", "b"); |
- } |
- // a.b = null |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "a.b = null"); |
- // a.b = null has no Element |
- assertSame(null, binary.getElement()); |
- // a.b is field "A.b" |
- assertHasFieldElement(binary.getArg1(), "A", "b"); |
- } |
- } |
- |
- /** |
- * Test for resolving variants of static property access and unary/binary expressions. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5049 |
- */ |
- public void test_opAssignPropertyAccess_static() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " static B get b => new B();", |
- " static set b(B x) {}", |
- "}", |
- "class B {", |
- " B operator +(x) => new B();", |
- "}", |
- "main () {", |
- " process( A.b );", |
- " A.b++;", |
- " ++A.b;", |
- " A.b += 1;", |
- " A.b = null;", |
- "}", |
- "process(x) {}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // print( A.b ) |
- { |
- DartPropertyAccess access = findNode(DartPropertyAccess.class, "A.b"); |
- // A.b is field "A.b" |
- assertHasFieldElement(access, "A", "b"); |
- } |
- // A.b++ |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "A.b++"); |
- // A.b++ is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // A.b is field "A.b" |
- assertHasFieldElement(unary.getArg(), "A", "b"); |
- } |
- // ++A.b |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "++A.b"); |
- // ++A.b is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // A.b is field "A.b" |
- assertHasFieldElement(unary.getArg(), "A", "b"); |
- } |
- // A.b += 1 |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "A.b += 1"); |
- // A.b += 1 is invocation of method "+" |
- assertHasMethodElement(binary, "B", "+"); |
- // A.b is field "A.b" |
- assertHasFieldElement(binary.getArg1(), "A", "b"); |
- } |
- // A.b = null |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "A.b = null"); |
- // A.b = null has no Element |
- assertSame(null, binary.getElement()); |
- // A.b is field "A.b" |
- assertHasFieldElement(binary.getArg1(), "A", "b"); |
- } |
- } |
- |
- /** |
- * Test for resolving variants of top-level property access and unary/binary expressions. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5049 |
- */ |
- public void test_opAssignPropertyAccess_topLevel() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "B get field => new B();", |
- " set field(B x) {}", |
- "class B {", |
- " B operator +(x) => new B();", |
- "}", |
- "main () {", |
- " process( field );", |
- " field++;", |
- " ++field;", |
- " field += 1;", |
- " field = null;", |
- "}", |
- "process(x) {}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // print( field ) |
- { |
- DartIdentifier access = findNode(DartIdentifier.class, "field );"); |
- // "field" is top-level field |
- assertHasFieldElement(access, "<library>", "field"); |
- } |
- // field++ |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "field++"); |
- // field++ is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // "field" is top-level field |
- assertHasFieldElement(unary.getArg(), "<library>", "field"); |
- } |
- // ++field |
- { |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "++field"); |
- // ++field is invocation of method "+" |
- assertHasMethodElement(unary, "B", "+"); |
- // "field" is top-level field |
- assertHasFieldElement(unary.getArg(), "<library>", "field"); |
- } |
- // field += 1 |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "field += 1"); |
- // field += 1 is invocation of method "+" |
- assertHasMethodElement(binary, "B", "+"); |
- // "field" is top-level field |
- assertHasFieldElement(binary.getArg1(), "<library>", "field"); |
- } |
- // field = null |
- { |
- DartBinaryExpression binary = findNode(DartBinaryExpression.class, "field = null"); |
- // field = null is no Element |
- assertSame(null, binary.getElement()); |
- // "field" is top-level field |
- assertHasFieldElement(binary.getArg1(), "<library>", "field"); |
- } |
- } |
- |
- private static void assertHasFieldElement(DartNode node, String className, String fieldName) { |
- Element element = node.getElement(); |
- assertTrue("" + node + " " + element, element instanceof FieldElement); |
- FieldElement fieldElement = (FieldElement) element; |
- assertHasFieldElement(fieldElement, className, fieldName); |
- } |
- |
- private static void assertHasFieldElement(FieldElement element, String className, String fieldName) { |
- EnclosingElement enclosingElement = element.getEnclosingElement(); |
- String enclosingName; |
- if (enclosingElement instanceof LibraryElement) { |
- enclosingName = "<library>"; |
- } else { |
- enclosingName = enclosingElement.getName(); |
- } |
- assertEquals(className, enclosingName); |
- // |
- String elementName = element.getName(); |
- assertEquals(fieldName, elementName); |
- } |
- |
- private static void assertHasMethodElement(DartNode node, String className, String methodName) { |
- Element element = node.getElement(); |
- assertTrue("" + node + " " + element, element instanceof MethodElement); |
- MethodElement methodElement = (MethodElement) element; |
- assertMethodElement(methodElement, className, methodName); |
- } |
- |
- private static void assertMethodElement(MethodElement element, String className, String methodName) { |
- EnclosingElement enclosingElement = element.getEnclosingElement(); |
- String enclosingName; |
- if (enclosingElement instanceof LibraryElement) { |
- enclosingName = "<library>"; |
- } else { |
- enclosingName = enclosingElement.getName(); |
- } |
- assertEquals(className, enclosingName); |
- // |
- String elementName = element.getName(); |
- if (element.getModifiers().isGetter()) { |
- elementName = "get " + elementName; |
- } |
- if (element.getModifiers().isSetter()) { |
- elementName = "set " + elementName; |
- } |
- assertEquals(methodName, elementName); |
- } |
- |
- public void test_invokeStaticFieldAsMethod() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " static foo() { }", |
- "}", |
- "main () {", |
- " var a = new C().foo();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.IS_STATIC_METHOD_IN, 6, 19, 3)); |
- } |
- |
- public void test_invokeNonFunction() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " String foo;", |
- " method() {", |
- " foo();", |
- " }", |
- "}", |
- "method() {", |
- " String foo;", |
- " foo();", |
- " (1 + 5)();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NOT_A_METHOD_IN, 5, 5, 3), |
- errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 10, 3, 3), |
- errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 11, 3, 9)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3223 |
- */ |
- public void test_invokeNonFunction_inferred() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "method() {", |
- " var v = 1;", |
- " v();", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_invokeNonFunction_getter() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " int get foo => 0;", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a.foo();", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE_FIELD, 7, 5, 3)); |
- } |
- |
- public void test_wrongOperandTypeForUnaryExpression() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class C {", |
- " operator -(String arg) {}", |
- " operator +(String arg) {}", |
- "}", |
- "method1(arg) {}", |
- "method2() {", |
- " C foo = new C();", |
- " method1(++foo);", |
- " method1(--foo);", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.OPERATOR_WRONG_OPERAND_TYPE, 9, 11, 5), |
- errEx(TypeErrorCode.OPERATOR_WRONG_OPERAND_TYPE, 10, 11, 5)); |
- } |
- |
- /** |
- * Missing value in {@link DartMapLiteralEntry} is parsing error, but should not cause exception. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3931 |
- */ |
- public void test_mapLiteralEntry_noValue() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " var v = {'key' : /*no value*/};", |
- "}", |
- ""); |
- // has some errors |
- assertTrue(libraryResult.getErrors().size() != 0); |
- } |
- |
- public void test_fieldOverrideWrongType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " int foo;", |
- "}", |
- "class B extends A {", |
- " String foo;", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CANNOT_OVERRIDE_TYPED_MEMBER, 6, 10, 3)); |
- } |
- |
- public void test_overrideInstanceMember() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "class A {", |
- " var field;", |
- " method() {}", |
- "}", |
- "class B extends A {", |
- " static var field;", |
- " static method() {}", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_OVERRIDE_INSTANCE_MEMBER, 6, 14, 5), |
- errEx(ResolverErrorCode.CANNOT_OVERRIDE_INSTANCE_MEMBER, 7, 10, 6)); |
- } |
- |
- public void test_overrideStaticMember() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " static var foo;", |
- " static bar() {}", |
- "}", |
- "class B extends A {", |
- " var foo;", |
- " bar() {}", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.OVERRIDING_STATIC_MEMBER, 7, 7, 3), |
- errEx(TypeErrorCode.OVERRIDING_STATIC_MEMBER, 8, 3, 3)); |
- } |
- |
- public void test_rethrowNotInCatch() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "class Object {}", |
- "method() {", |
- " throw;", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.RETHROW_NOT_IN_CATCH, 3, 3, 5)); |
- } |
- |
- public void test_externalKeyword_OK() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "external topFunction();", |
- "external get topGetter;", |
- "external set topSetter(var v);", |
- "class A {", |
- " external const A.con();", |
- " external A();", |
- " external factory A.named();", |
- " external classMethod();", |
- " external static classMethodStatic();", |
- " external get classGetter;", |
- " external set classSetter(var v);", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // all method-like nodes here are "external" |
- final AtomicInteger methodCounter = new AtomicInteger(); |
- testUnit.accept(new ASTVisitor<Void>() { |
- @Override |
- public Void visitMethodDefinition(DartMethodDefinition node) { |
- methodCounter.incrementAndGet(); |
- assertTrue(node.getModifiers().isExternal()); |
- return null; |
- } |
- }); |
- assertEquals(10, methodCounter.get()); |
- } |
- |
- /** |
- * Modifier "external" can be applied only to method-like elements. |
- */ |
- public void test_externalKeyword_bad_field() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "external var topVar1;", |
- "external int topVar2;", |
- "class A {", |
- " external var field1;", |
- " external int field2;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ParserErrorCode.EXTERNAL_ONLY_METHOD, 2, 14, 7), |
- errEx(ParserErrorCode.EXTERNAL_ONLY_METHOD, 3, 14, 7), |
- errEx(ParserErrorCode.EXTERNAL_ONLY_METHOD, 5, 16, 6), |
- errEx(ParserErrorCode.EXTERNAL_ONLY_METHOD, 6, 16, 6)); |
- } |
- |
- /** |
- * Methods with "external" cannot have body. |
- */ |
- public void test_externalKeyword_bad_body() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "external topFunction() {}", |
- "abstract class A {", |
- " external A() {}", |
- " external factory A.named() {}", |
- " external classMethod() {}", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ParserErrorCode.EXTERNAL_METHOD_BODY, 2, 24, 2), |
- errEx(ParserErrorCode.EXTERNAL_METHOD_BODY, 4, 16, 2), |
- errEx(ParserErrorCode.EXTERNAL_METHOD_BODY, 5, 30, 2), |
- errEx(ParserErrorCode.EXTERNAL_METHOD_BODY, 6, 26, 2)); |
- } |
- |
- public void test_cascade_type() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " String s = '';", |
- " var v = s..length;", |
- "}", |
- ""); |
- assertInferredElementTypeString(testUnit, "v", "String", INFERRED); |
- } |
- |
- /** |
- * There should be no problem reported, because assignment of "a" cascade to "b" with type "B" |
- * implicitly set type of "a" to "B". |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6107 |
- */ |
- public void test_cascade_inferType_varDeclaration() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B extends A {", |
- " bMethod() {}", |
- "}", |
- "main() {", |
- " A a = new B();", |
- " B b = a..bMethod();", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * There should be no problem reported, because assignment of "a" cascade to "b" with type "B" |
- * implicitly set type of "a" to "B". |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6107 |
- */ |
- public void test_cascade_inferType_varAssignment() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B extends A {", |
- " bMethod() {}", |
- "}", |
- "main() {", |
- " A a = new B();", |
- " B b = null;", |
- " b = a..bMethod();", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * We assign "a" to field "Holder.b" of type "B", so implicitly set type of "a" to "B". |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6107 |
- */ |
- public void test_cascade_inferType_fieldDeclaration() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Holder {", |
- " B b = getA()..bMethod();", |
- "}", |
- "class A {}", |
- "class B extends A {", |
- " bMethod() {}", |
- "}", |
- "A getA() => new B();", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * We assign "a" to field "Holder.b" of type "B", so implicitly set type of "a" to "B". |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6107 |
- */ |
- public void test_cascade_inferType_fieldAssignment() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Holder {", |
- " B b;", |
- "}", |
- "class A {}", |
- "class B extends A {", |
- " bMethod() {}", |
- "}", |
- "main() {", |
- " A a = new B();", |
- " Holder holder = new Holder();", |
- " holder.b = a..bMethod();", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4315 |
- */ |
- public void test_cascade_propertyAccess() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " int f;", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a", |
- " ..f = 1", |
- " ..f = 2;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- { |
- DartPropertyAccess access = findNode(DartPropertyAccess.class, "..f = 1"); |
- assertNotNull(access.getElement()); |
- } |
- { |
- DartPropertyAccess access = findNode(DartPropertyAccess.class, "..f = 2"); |
- assertNotNull(access.getElement()); |
- } |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4315 |
- */ |
- public void test_cascade_methodInvocation() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " int m(p) {}", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a", |
- " ..m(1)", |
- " ..m(2);", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- { |
- DartMethodInvocation invocation = findNode(DartMethodInvocation.class, "..m(1)"); |
- assertNotNull(invocation.getElement()); |
- } |
- { |
- DartMethodInvocation invocation = findNode(DartMethodInvocation.class, "..m(2)"); |
- assertNotNull(invocation.getElement()); |
- } |
- } |
- |
- /** |
- * Test that we already support cascaded calls in initializers. No implementation was changed. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6955 |
- */ |
- public void test_cascade_inInitializer() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var f;", |
- " A() : f = ''..length;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * Source is invalid, but should not cause {@link NullPointerException}. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4354 |
- */ |
- public void test_switchCase_withoutExpression() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " switch (0) {", |
- " case }", |
- " }", |
- "}", |
- ""); |
- // has some errors, no exception |
- assertTrue(libraryResult.getErrors().size() != 0); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6836 |
- */ |
- public void test_unresolvedIdentifier_inStatic_notPropertyAccess() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "process(x) {}", |
- "", |
- "class A {", |
- " static foo() {", |
- " unknown = 0;", |
- " }", |
- "}", |
- "", |
- "main() {", |
- " unknown = 0;", |
- " process(unknown);", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 6, 5, 7), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 11, 3, 7), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 12, 11, 7)); |
- } |
- |
- /** |
- * If "unknown" is separate identifier, it is handled as "this.unknown", but "this" is not |
- * accessible in static context. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3084 |
- */ |
- public void test_unresolvedIdentifier_inInstance_notPropertyAccess() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "process(x) {}", |
- "class A {", |
- " foo() {", |
- " unknown = 0;", |
- " process(unknown);", |
- " }", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 5, 7), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 6, 13, 7)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3084 |
- */ |
- public void test_unresolvedIdentifier_inStatic_inPropertyAccess() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "process(x) {}", |
- "main() {", |
- " Unknown.foo = 0;", |
- " process(Unknown.foo);", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 4, 3, 7), |
- errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 11, 7)); |
- } |
- |
- /** |
- * Unresolved constructor is warning. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3800 |
- */ |
- public void test_unresolvedConstructor() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "main() {", |
- " new A(); // OK", |
- " new A.noSuchConstructor(); // warning", |
- " new B(); // warning", |
- " new B.noSuchConstructor(); // warning", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.NEW_EXPRESSION_NOT_CONSTRUCTOR, 5, 9, 17), |
- errEx(TypeErrorCode.NO_SUCH_TYPE, 6, 7, 1), |
- errEx(TypeErrorCode.NO_SUCH_TYPE, 7, 7, 1), |
- errEx(TypeErrorCode.NEW_EXPRESSION_NOT_CONSTRUCTOR, 7, 9, 17)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4383 |
- */ |
- public void test_callFieldWithoutGetter_topLevel() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "set setOnlyField(v) {}", |
- "main() {", |
- " setOnlyField(0);", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.USE_ASSIGNMENT_ON_SETTER, 4, 3, 12)); |
- } |
- |
- /** |
- * Every {@link DartExpression} should have {@link Type} set. Just to don't guess this type at |
- * many other points in the Editor. |
- */ |
- public void test_typeForEveryExpression_variable() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "process(x) {}", |
- "main() {", |
- " A aaa = new A();", |
- " process(aaa);", |
- "}"); |
- testUnit.accept(new ASTVisitor<Void>() { |
- @Override |
- public Void visitIdentifier(DartIdentifier node) { |
- // ignore declaration |
- if (node.getParent() instanceof DartDeclaration) { |
- return null; |
- } |
- // check "aaa" |
- if (node.toString().equals("aaa")) { |
- Type type = node.getType(); |
- assertNotNull(type); |
- assertEquals("A", type.toString()); |
- } |
- return null; |
- } |
- }); |
- } |
- |
- /** |
- * Every {@link DartExpression} should have {@link Type} set. Just to don't guess this type at |
- * many other points in the Editor. |
- */ |
- public void test_typeForEveryExpression_typeNode() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class AAA {", |
- " static foo() {}", |
- "}", |
- "main() {", |
- " AAA.foo();", |
- "}"); |
- testUnit.accept(new ASTVisitor<Void>() { |
- @Override |
- public Void visitIdentifier(DartIdentifier node) { |
- // ignore declaration |
- if (node.getParent() instanceof DartDeclaration) { |
- return null; |
- } |
- // check "AAA" |
- if (node.toString().equals("AAA")) { |
- Type type = node.getType(); |
- assertNotNull(type); |
- assertEquals("AAA", type.toString()); |
- } |
- return null; |
- } |
- }); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4383 |
- */ |
- public void test_callFieldWithoutGetter_member() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " set setOnlyField(v) {}", |
- " foo() {", |
- " setOnlyField(0);", |
- " }", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " a.setOnlyField(0);", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, 5, 5, 12), |
- errEx(TypeErrorCode.USE_ASSIGNMENT_ON_SETTER, 10, 5, 12)); |
- } |
- |
- private abstract static class ArgumentsBindingTester { |
- static List<DartExpression> arguments; |
- void doTest(DartUnit unit) { |
- unit.accept(new ASTVisitor<Void>() { |
- int invocationIndex = 0; |
- @Override |
- public Void visitUnqualifiedInvocation(DartUnqualifiedInvocation node) { |
- arguments = node.getArguments(); |
- checkArgs(invocationIndex++); |
- return super.visitUnqualifiedInvocation(node); |
- } |
- }); |
- } |
- abstract void checkArgs(int invocationIndex); |
- void assertId(int index, String expectedParameterName) { |
- DartExpression argument = arguments.get(index); |
- String idString = argument.getInvocationParameterId().toString(); |
- assertEquals("PARAMETER " + expectedParameterName, idString); |
- } |
- } |
- |
- public void test_formalParameters_positional_optional() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "method(var a, var b, [var c = 3, var d = 4]) {}", |
- "main() {", |
- " method(10, 20);", |
- " method(10, 20, 30);", |
- " method(10, 20, 30, 40);", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- new ArgumentsBindingTester() { |
- @Override |
- void checkArgs(int invocationIndex) { |
- switch (invocationIndex) { |
- case 0: { |
- assertId(0, "a"); |
- assertId(1, "b"); |
- break; |
- } |
- case 1: { |
- assertId(0, "a"); |
- assertId(1, "b"); |
- assertId(2, "c"); |
- break; |
- } |
- case 3: { |
- assertId(0, "a"); |
- assertId(1, "b"); |
- assertId(2, "c"); |
- assertId(3, "d"); |
- break; |
- } |
- } |
- } |
- }.doTest(testUnit); |
- } |
- |
- public void test_formalParameters_positional_named() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "method(var a, var b, {var c : 3, var d : 4}) {}", |
- "main() {", |
- " method(10, 20);", |
- " method(10, 20, c: 30);", |
- " method(10, 20, d: 40);", |
- " method(10, 20, d: 40, c: 30);", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- new ArgumentsBindingTester() { |
- @Override |
- void checkArgs(int invocationIndex) { |
- switch (invocationIndex) { |
- case 0: { |
- assertId(0, "a"); |
- assertId(1, "b"); |
- break; |
- } |
- case 1: { |
- assertId(0, "a"); |
- assertId(1, "b"); |
- assertId(2, "c"); |
- break; |
- } |
- case 2: { |
- assertId(0, "a"); |
- assertId(1, "b"); |
- assertId(2, "d"); |
- break; |
- } |
- case 3: { |
- assertId(0, "a"); |
- assertId(1, "b"); |
- assertId(2, "d"); |
- assertId(3, "c"); |
- break; |
- } |
- } |
- } |
- }.doTest(testUnit); |
- } |
- |
- /** |
- * A constructor name always begins with the name of its immediately enclosing class, and may |
- * optionally be followed by a dot and an identifier id. It is a compile-time error if id is the |
- * name of a member declared in the immediately enclosing class. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3989 |
- */ |
- public void test_constructorName_sameAsMemberName() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " A.foo() {}", |
- " foo() {}", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CONSTRUCTOR_WITH_NAME_OF_MEMBER, 3, 3, 5)); |
- } |
- |
- /** |
- * It is a compile-time error if M is not the name of the immediately enclosing class. |
- * It is a static warning if M.id is not a constructor name. |
- */ |
- public void test_constructorName_factory_notEnclosingClassName() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B {", |
- " factory A() {}", |
- " factory A.name() {}", |
- " factory B() {}", |
- " factory B.name() {}", |
- "}"); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.CONSTRUCTOR_NAME_NOT_ENCLOSING_CLASS, 4, 11, 1), |
- errEx(ResolverErrorCode.CONSTRUCTOR_NAME_NOT_ENCLOSING_CLASS, 5, 11, 1), |
- errEx(ResolverErrorCode.CONSTRUCTOR_NAME_NOT_ENCLOSING_CLASS_ID, 5, 11, 6)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3904 |
- */ |
- public void test_reifiedClasses() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "process(x) {}", |
- "main() {", |
- " process(A);", |
- "}"); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=3968 |
- */ |
- public void test_redirectingFactoryConstructor() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " A() {}", |
- " A.named() {}", |
- "}", |
- "", |
- "class B {", |
- " factory B.foo() = A;", |
- " factory B.bar() = A.named;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- // prepare "class A" |
- ClassElement elementA = findNode(DartClass.class, "class A").getElement(); |
- Type typeA = elementA.getType(); |
- // = A; |
- { |
- DartTypeNode typeNode = findNode(DartTypeNode.class, "A;"); |
- Type type = typeNode.getType(); |
- assertSame(typeA, type); |
- } |
- // = A.named; |
- { |
- DartTypeNode typeNode = findNode(DartTypeNode.class, "A.named;"); |
- Type type = typeNode.getType(); |
- assertSame(typeA, type); |
- // .named |
- DartIdentifier nameNode = findNode(DartIdentifier.class, "named;"); |
- Element nameElement = nameNode.getElement(); |
- assertNotNull(nameElement); |
- assertSame(elementA.lookupConstructor("named"), nameElement); |
- } |
- } |
- |
- public void test_redirectingFactoryConstructor_cycle() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " factory A.nameA() = C.nameC;", |
- "}", |
- "class B {", |
- " factory B.nameB() = A.nameA;", |
- "}", |
- "class C {", |
- " factory C.nameC() = B.nameB;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.REDIRECTION_CONSTRUCTOR_CYCLE, 3, 11, 7), |
- errEx(ResolverErrorCode.REDIRECTION_CONSTRUCTOR_CYCLE, 6, 11, 7), |
- errEx(ResolverErrorCode.REDIRECTION_CONSTRUCTOR_CYCLE, 9, 11, 7)); |
- } |
- |
- public void test_redirectingFactoryConstructor_notConst_fromConst() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " A.named() {}", |
- "}", |
- "", |
- "class B {", |
- " const factory B.bar() = A.named;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(ResolverErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_CONST, 7, 29, 5)); |
- } |
- |
- public void test_redirectingFactoryConstructor_shouldBeSubType() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " A() {}", |
- " A.named(p0) {}", |
- "}", |
- "", |
- "class B {", |
- " factory B.foo(p0) = A;", |
- " factory B.bar() = A.named;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE, 8, 23, 1), |
- errEx(TypeErrorCode.REDIRECTION_CONSTRUCTOR_TARGET_MUST_BE_SUBTYPE, 9, 23, 5)); |
- } |
- |
- public void test_redirectingFactoryConstructor_shouldBeSubType2() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " A.named(T t) {}", |
- "}", |
- "", |
- "class B<T> {", |
- " factory B.foo(T t) = A<T>.named;", |
- "}", |
- "class B2<T, V> {", |
- " factory B2.foo(V v) = A<V>.named;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_redirectingFactoryConstructor_shouldBeSubType3() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " A(A<T> p) {}", |
- "}", |
- "", |
- "class B<T> {", |
- " factory B.foo(A<T> p) = A;", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- public void test_redirectingFactoryConstructor_notSubType_typeParameterBounds() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A1<T extends String> {", |
- " A1() {}", |
- "}", |
- "class A2<T> {", |
- " A2() {}", |
- "}", |
- "", |
- "class B {", |
- " factory B.name1() = A1<String>;", |
- " factory B.name2() = A1<int>;", |
- " factory B.name3() = A2<String>;", |
- " factory B.name4() = A2<int>;", |
- "}", |
- ""); |
- assertErrors( |
- libraryResult.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 11, 26, 3)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4778 |
- */ |
- public void test_unqualifiedAccessToGenericTypeField() throws Exception { |
- AnalyzeLibraryResult libraryResult = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Game {}", |
- "class GameRenderer<G extends Game> {", |
- " G get game => null;", |
- "}", |
- "class SpaceShooterGame extends Game {", |
- " int score;", |
- "}", |
- "class SpaceShooterRenderer extends GameRenderer<SpaceShooterGame> {", |
- " someMethod() {", |
- " var a = game.score;", |
- " }", |
- "}", |
- ""); |
- assertErrors(libraryResult.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=4900 |
- */ |
- public void test_forInLoop_fieldAsVariable() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "var v;", |
- "get l => v;", |
- "set l(x) {v = x;}", |
- "main() {", |
- " for (l in [1, 2, 3]) {", |
- " process(l);", |
- " }", |
- "}", |
- "process(x) {}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * Don't report "no such member" if class implements "noSuchMethod" method. |
- */ |
- public void test_dontReport_ifHas_noSuchMember_method() throws Exception { |
- String[] lines = { |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " noSuchMethod(Invocation invocation) {}", |
- "}", |
- "class B extends A {}", |
- "class C {}", |
- "main() {", |
- " new A().notExistingMethod();", |
- " new B().notExistingMethod();", |
- " new C().notExistingMethod();", |
- "}", |
- "process(x) {}", |
- ""}; |
- // report by default |
- { |
- AnalyzeLibraryResult result = analyzeLibrary(lines); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 8, 11, 17), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 9, 11, 17), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 10, 11, 17)); |
- } |
- // don't report |
- { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean reportNoMemberWhenHasInterceptor() { |
- return false; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary(lines); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 10, 11, 17)); |
- } |
- } |
- |
- /** |
- * Don't report "no such member" if class implements "noSuchMethod" method. |
- */ |
- public void test_dontReport_ifHas_noSuchMember_getter() throws Exception { |
- String[] lines = { |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " noSuchMethod(Invocation invocation) {}", |
- "}", |
- "class B extends A {}", |
- "class C {}", |
- "main() {", |
- " process( new A().notExistingGetter );", |
- " process( new B().notExistingGetter );", |
- " process( new C().notExistingGetter );", |
- "}", |
- "process(x) {}", |
- ""}; |
- // report by default |
- { |
- AnalyzeLibraryResult result = analyzeLibrary(lines); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.NOT_A_MEMBER_OF, 8, 20, 17), |
- errEx(TypeErrorCode.NOT_A_MEMBER_OF, 9, 20, 17), |
- errEx(TypeErrorCode.NOT_A_MEMBER_OF, 10, 20, 17)); |
- } |
- // don't report |
- { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean reportNoMemberWhenHasInterceptor() { |
- return false; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary(lines); |
- assertErrors(result.getErrors(), errEx(TypeErrorCode.NOT_A_MEMBER_OF, 10, 20, 17)); |
- } |
- } |
- |
- /** |
- * Don't report "is not a function type" if class implements "noSuchMethod" method. |
- */ |
- public void test_dontReport_ifHas_noSuchMember_isNotFunction() throws Exception { |
- String[] lines = { |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " noSuchMethod(Invocation invocation) {}", |
- "}", |
- "class B extends A {}", |
- "class C {}", |
- "main() {", |
- " A a = new A();", |
- " B b = new B();", |
- " C c = new C();", |
- " a();", |
- " b();", |
- " c();", |
- "}", |
- ""}; |
- // report by default |
- { |
- AnalyzeLibraryResult result = analyzeLibrary(lines); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 11, 3, 1), |
- errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 12, 3, 1), |
- errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 13, 3, 1)); |
- } |
- // don't report |
- { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean reportNoMemberWhenHasInterceptor() { |
- return false; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary(lines); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.NOT_A_FUNCTION_TYPE, 13, 3, 1)); |
- } |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5084 |
- */ |
- public void test_duplicateSuperInterface_errorInClassImplements() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B implements A, A {}", |
- ""); |
- assertErrors(result.getErrors(), errEx(ResolverErrorCode.DUPLICATE_IMPLEMENTS_TYPE, 3, 23, 1)); |
- } |
- |
- /** |
- * It is a compile-time error if the superclass of a class C appears in the implements clause of C. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=7469 |
- */ |
- public void test_superClass_imImplementsClause() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B extends A implements A {}", |
- ""); |
- assertErrors(result.getErrors(), errEx(ResolverErrorCode.SUPER_CLASS_IN_IMPLEMENTS, 3, 30, 1)); |
- } |
- |
- /** |
- * We should report only "no such type", but not duplicate. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5084 |
- */ |
- public void test_duplicateSuperInterface_whenNoSuchType() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class B implements X, Y {}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.NO_SUCH_TYPE, 2, 20, 1), |
- errEx(ResolverErrorCode.NO_SUCH_TYPE, 2, 23, 1)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5082 |
- */ |
- public void test_argumentDefinitionTest_type() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "foo(p) {", |
- " ?p;", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- DartUnaryExpression unary = findNode(DartUnaryExpression.class, "?p"); |
- Type type = unary.getType(); |
- assertNotNull(type); |
- assertEquals("bool", type.toString()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5082 |
- */ |
- public void test_argumentDefinitionTest_shouldBeFormalParameter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "foo(p) {", |
- " var v;", |
- " ?p;", |
- " ?v;", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.FORMAL_PARAMETER_NAME_EXPECTED, 5, 4, 1)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5148 |
- */ |
- public void test_errorIfNoBodyForStaticMethod() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " static foo();", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.STATIC_METHOD_MUST_HAVE_BODY, 3, 3, 13)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5162 |
- */ |
- public void test_initializeFinalInstanceVariable_atDeclaration_inInitializer() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " final f = 0;", |
- " A() : f = 1 {}", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.DUPLICATE_INITIALIZATION, 4, 9, 5)); |
- } |
- |
- public void test_getOverridden_method() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " foo() => 1;", |
- "}", |
- "class B extends A {", |
- " foo() => 2;", |
- "}", |
- ""); |
- DartMethodDefinition node = findNode(DartMethodDefinition.class, "foo() => 2"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "method A.foo"); |
- } |
- |
- public void test_getOverridden_methodAbstract() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " foo();", |
- "}", |
- ""); |
- DartMethodDefinition node = findNode(DartMethodDefinition.class, "foo();"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertTrue(superElements.isEmpty()); |
- } |
- |
- public void test_getOverridden_field_withGetterSetter() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var foo;", |
- "}", |
- "class B extends A {", |
- " get foo => 0;", |
- " set foo(x) {}", |
- "}", |
- ""); |
- // getter |
- { |
- DartMethodDefinition node = findNode(DartMethodDefinition.class, "get foo"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.foo"); |
- } |
- // setter |
- { |
- DartMethodDefinition node = findNode(DartMethodDefinition.class, "set foo"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.foo"); |
- } |
- } |
- |
- public void test_getOverridden_field_withGetter() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var foo;", |
- "}", |
- "class B extends A {", |
- " get foo => 0;", |
- " set foo(x) {}", |
- "}", |
- ""); |
- // getter |
- { |
- DartMethodDefinition node = findNode(DartMethodDefinition.class, "get foo"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.foo"); |
- } |
- } |
- |
- public void test_getOverridden_field_withSetter() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var foo;", |
- "}", |
- "class B extends A {", |
- " set foo(x) {}", |
- "}", |
- ""); |
- // setter |
- { |
- DartMethodDefinition node = findNode(DartMethodDefinition.class, "set foo"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.foo"); |
- } |
- } |
- |
- public void test_getOverridden_getterSetter_withField() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " get foo => 0;", |
- " set foo(x) {}", |
- "}", |
- "class B extends A {", |
- " var foo = 42;", |
- "}", |
- ""); |
- DartField node = findNode(DartField.class, "foo = 42"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.foo"); |
- } |
- |
- public void test_getOverridden_getter_withField() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " get foo => 0;", |
- "}", |
- "class B extends A {", |
- " var foo = 42;", |
- "}", |
- ""); |
- DartField node = findNode(DartField.class, "foo = 42"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.foo"); |
- } |
- |
- public void test_getOverridden_setter_withField() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " set foo(x) {}", |
- "}", |
- "class B extends A {", |
- " var foo = 42;", |
- "}", |
- ""); |
- DartField node = findNode(DartField.class, "foo = 42"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.setter foo"); |
- } |
- |
- public void test_getOverridden_setter_withSetter() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " set foo(x) {} // A", |
- "}", |
- "class B extends A {", |
- " set foo(x) {} // B", |
- "}", |
- ""); |
- DartField node = findNode(DartField.class, "set foo(x) {} // B"); |
- Set<Element> superElements = node.getElement().getOverridden(); |
- assertClassMembers(superElements, "field A.setter foo"); |
- } |
- |
- private static void assertClassMembers(Set<Element> superElements, String... expectedNames) { |
- Set<String> superNames = Sets.newHashSet(); |
- for (Element element : superElements) { |
- String name = element.getEnclosingElement().getName() + "." + element.getName(); |
- if (element instanceof FieldElement) { |
- superNames.add("field " + name); |
- } |
- if (element instanceof MethodElement) { |
- superNames.add("method " + name); |
- } |
- } |
- for (String name : expectedNames) { |
- assertTrue(name, superNames.remove(name)); |
- } |
- assertTrue(superNames.toString(), superNames.isEmpty()); |
- } |
- |
- public void test_fieldAccess_declared_noGetter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " static set f(x) {}", |
- "}", |
- "main() {", |
- " print(A.f);", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 6, 11, 1)); |
- } |
- |
- public void test_fieldAccess_notDeclared() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- "}", |
- "main() {", |
- " print(A.f);", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 11, 1)); |
- } |
- |
- public void test_fieldAssign_declared_noSetter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " static get f => 0;", |
- "}", |
- "main() {", |
- " A.f = 0;", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER, 6, 5, 1)); |
- } |
- |
- public void test_fieldAssign_notDeclared() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- "}", |
- "main() {", |
- " A.f = 0;", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 5, 5, 1)); |
- } |
- |
- public void test_field_unqualifiedAccess_read() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " set f(x) {}", |
- " run() {", |
- " var v = f;", |
- " }", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_GETTER, 5, 13, 1)); |
- } |
- |
- public void test_field_unqualifiedAccess_write() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " get f => 0;", |
- " run() {", |
- " f = 1;", |
- " }", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), errEx(ResolverErrorCode.FIELD_DOES_NOT_HAVE_A_SETTER, 5, 5, 1)); |
- } |
- |
- public void test_typeVariableScope_staticField() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " static T v;", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.TYPE_VARIABLE_IN_STATIC_CONTEXT, 3, 10, 1)); |
- } |
- |
- public void test_typeVariableScope_staticMethod() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " static foo() {", |
- " T v = null;", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.TYPE_VARIABLE_IN_STATIC_CONTEXT, 4, 5, 1)); |
- } |
- |
- public void test_typeVariableScope_instanceField() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A<T> {", |
- " final List<T> values = new List<T>();", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_unresolvedMethod_inFactoryConstructor() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " factory A() {", |
- " foo();", |
- " }", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_RESOLVE_METHOD, 4, 5, 3)); |
- } |
- |
- /** |
- * Developers unfamiliar with Dart frequently write (x/y).toInt() instead of x ~/ y. The editor |
- * should recognize that pattern. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5652 |
- */ |
- public void test_useEffectiveIntegerDivision_int() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " int x = 7;", |
- " int y = 2;", |
- " print( (x / y).toInt() );", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), errEx(TypeErrorCode.USE_INTEGER_DIVISION, 5, 10, 15)); |
- } |
- |
- /** |
- * We need to report warning only when arguments are integers. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5652 |
- */ |
- public void test_useEffectiveIntegerDivision_num() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " num x = 7;", |
- " num y = 2;", |
- " print( (x / y).toInt() );", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=5157 |
- */ |
- public void test_trySubTypeMember_forInferredType() throws Exception { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean typeChecksForInferredTypes() { |
- return true; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "class MouseEvent extends Event {", |
- " int clientX;", |
- " void stop() {}", |
- "}", |
- "typedef Listener(Event event);", |
- "class Button {", |
- " addListener(Listener listener) {}", |
- "}", |
- "main() {", |
- " Button button = new Button();", |
- " button.addListener((event) {", |
- " event.clientX;", |
- " event.stop();", |
- " });", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * We should resolve sub-type member only if there is only sub-type with such member. |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6776 |
- */ |
- public void test_trySubTypeMember_moreThanOneMember() throws Exception { |
- compilerConfiguration = new DefaultCompilerConfiguration(new CompilerOptions() { |
- @Override |
- public boolean typeChecksForInferredTypes() { |
- return true; |
- } |
- }); |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class Event {}", |
- "class MouseEvent extends Event {", |
- " int clientX;", |
- "}", |
- "class ScreenEvent extends Event {", |
- " int clientX;", |
- "}", |
- "typedef Listener(Event event);", |
- "class Button {", |
- " addListener(Listener listener) {}", |
- "}", |
- "main() {", |
- " Button button = new Button();", |
- " button.addListener((event) {", |
- " event.clientX;", |
- " });", |
- "}", |
- ""); |
- // don't report error, because there IS member, we just don't know which one |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6491 |
- */ |
- public void test_annotationOnGetter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "const myAnnotation = 0;", |
- "class A {", |
- " @myAnnotation bool get isEmpty => true;", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_resolveRefInComment_ofClass() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "/** This class [A] has method [foo]. */", |
- "class A {", |
- " foo() {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- // [A] |
- { |
- DartCommentRefName node = findNode(DartCommentRefName.class, "A]"); |
- ClassElement element = (ClassElement) node.getElement(); |
- assertEquals("A", element.getName()); |
- } |
- // [foo] |
- { |
- DartCommentRefName node = findNode(DartCommentRefName.class, "foo]"); |
- MethodElement element = (MethodElement) node.getElement(); |
- assertEquals("foo", element.getName()); |
- } |
- } |
- |
- public void test_resolveRefInComment_ofFunction() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "/** This function has parameter [aaa] of type [A] ans also [bbb]. */", |
- "foo(A aaa, bbb) {}", |
- ""); |
- assertErrors(result.getErrors()); |
- // [aaa] |
- { |
- DartCommentRefName node = findNode(DartCommentRefName.class, "aaa]"); |
- VariableElement element = (VariableElement) node.getElement(); |
- assertSame(ElementKind.PARAMETER, ElementKind.of(element)); |
- assertEquals("aaa", element.getName()); |
- } |
- // [A] |
- { |
- DartCommentRefName node = findNode(DartCommentRefName.class, "A]"); |
- ClassElement element = (ClassElement) node.getElement(); |
- assertEquals("A", element.getName()); |
- } |
- // [bbb] |
- { |
- DartCommentRefName node = findNode(DartCommentRefName.class, "bbb]"); |
- VariableElement element = (VariableElement) node.getElement(); |
- assertSame(ElementKind.PARAMETER, ElementKind.of(element)); |
- assertEquals("bbb", element.getName()); |
- } |
- } |
- |
- public void test_resolveRefInComment_ofMethod() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var fff;", |
- " /** Initializes [fff] and then calls [bar]. */", |
- " foo() {}", |
- " bar() {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- // [fff] |
- { |
- DartCommentRefName node = findNode(DartCommentRefName.class, "fff]"); |
- FieldElement element = (FieldElement) node.getElement(); |
- assertEquals("fff", element.getName()); |
- } |
- // [bar] |
- { |
- DartCommentRefName node = findNode(DartCommentRefName.class, "bar]"); |
- MethodElement element = (MethodElement) node.getElement(); |
- assertEquals("bar", element.getName()); |
- } |
- } |
- |
- public void test_resolveNewInComment() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " A() {}", |
- " A.named() {}", |
- "}", |
- "/** Creates [A] using [new A] or [new A.named] constructors. */", |
- "foo() {}", |
- ""); |
- assertErrors(result.getErrors()); |
- // [new A] |
- { |
- DartCommentNewName node = findNode(DartCommentNewName.class, "new A]"); |
- assertEquals("", node.getConstructorElement().getName()); |
- assertEquals("A", node.getClassElement().getName()); |
- } |
- // [new A.named] |
- { |
- DartCommentNewName node = findNode(DartCommentNewName.class, "new A.named]"); |
- assertEquals("named", node.getConstructorElement().getName()); |
- assertEquals("A", node.getClassElement().getName()); |
- } |
- } |
- |
- public void test_notGenerativeConstructor_default() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " factory A() {", |
- " return null;", |
- " }", |
- "}", |
- "class B extends A {", |
- " B() : super() {}", // explicit call of super constructor |
- "}", |
- "class C extends A {", |
- " C() {}", // implicit call of super constructor |
- "}", |
- "class D extends A {", // implicit call of super constructor |
- "}", |
- ""); |
- assertErrors(result.getErrors(), |
- errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 8, 9, 7), |
- errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 11, 3, 1), |
- errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 13, 7, 1)); |
- } |
- |
- public void test_notGenerativeConstructor_explicitNamed() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " factory A.named() {", |
- " return null;", |
- " }", |
- "}", |
- "class B extends A {", |
- " B() : super.named() {}", // explicit call of super constructor |
- "}", |
- ""); |
- assertErrors(result.getErrors(), |
- errEx(ResolverErrorCode.NOT_GENERATIVE_SUPER_CONSTRUCTOR, 8, 9, 13)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=6718 |
- */ |
- public void test_initializerInMethod() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " var x;", |
- " B() : x = 0 {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), |
- errEx(ResolverErrorCode.INITIALIZER_ONLY_IN_GENERATIVE_CONSTRUCTOR, 4, 9, 5)); |
- } |
- |
- public void test_variableReferencesItselfInInitializer() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " var x = x;", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), |
- errEx(ResolverErrorCode.VARIABLE_REFERENCES_SAME_NAME_IN_INITIALIZER, 3, 11, 1)); |
- } |
- |
- public void test_ForEachStatement_method() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " Iterator<int> iterator() {}", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " for (int v in a) {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- public void test_ForEachStatement_negative_method_invalidReturnType() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " int iterator() {}", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " for (int v in a) {}", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE, 7, 17, 1)); |
- } |
- |
- /** |
- * It was negative test, but in the new <code>Iterator</code> field should be also supported. |
- */ |
- public void test_ForEachStatement_field() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " Iterator iterator;", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " for (int v in a) {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
-// Map<String, ClassNodeElement> fieldNotMethod = loadSource( |
-// "class A {", |
-// " int iterator;", |
-// "}", |
-// "class B {", |
-// " main() { for (int i in new A()) {}}", |
-// "}"); |
-// analyzeClasses(fieldNotMethod, TypeErrorCode.FOR_IN_WITH_ITERATOR_FIELD); |
- } |
- |
- public void test_ForEachStatement_negative_field_invalidReturnType() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " int iterator;", |
- "}", |
- "main() {", |
- " A a = new A();", |
- " for (int v in a) {}", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), |
- errEx(TypeErrorCode.FOR_IN_WITH_INVALID_ITERATOR_RETURN_TYPE, 7, 17, 1)); |
- } |
- |
- public void test_builtInIdentifier_asType() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " abstract v_abstract;", |
- "}", |
- ""); |
- assertErrors(result.getErrors(), |
- errEx(ResolverErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, 3, 3, 8)); |
- } |
- |
- public void test_builtInIdentifier_asParameterizedType() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " abstract<int> v_01;", |
- " as<int> v_02;", |
- " export<int> v_03;", |
- " external<int> v_04;", |
- " factory<int> v_05;", |
- " get<int> v_06;", |
- " implements<int> v_07;", |
- " import<int> v_08;", |
- " library<int> v_09;", |
- " operator<int> v_q0;", |
- " part<int> v_11;", |
- " set<int> v_12;", |
- " static<int> v_13;", |
- " typedef<int> v_14;", |
- "}", |
- ""); |
- List<DartCompilationError> errors = result.getErrors(); |
- assertEquals(14, errors.size()); |
- for (DartCompilationError error : errors) { |
- assertSame(TypeErrorCode.NO_SUCH_TYPE, error.getErrorCode()); |
- assertEquals(3, error.getColumnNumber()); |
- } |
- } |
- |
- public void test_superConstructorInvocation_wrongPlace() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "topLevelMethod() : super() {}", |
- "", |
- "class A {", |
- " m() : super() {}", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.SUPER_OUTSIDE_OF_CONSTRUCTOR, 2, 20, 7), |
- errEx(ResolverErrorCode.SUPER_OUTSIDE_OF_CONSTRUCTOR, 5, 9, 7)); |
- } |
- |
- /** |
- * Test that we set {@link ConstructorElement} for {@link DartSuperConstructorInvocation}. |
- */ |
- public void test_superConstructorInvocation_resolveElement() throws Exception { |
- analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class A {", |
- " A.named() {}", |
- "}", |
- "abstract class B extends A {", |
- " B() : super.named();", |
- "}", |
- ""); |
- DartIdentifier nameInInvocation = findNode(DartIdentifier.class, "named();"); |
- DartSuperConstructorInvocation invocation = (DartSuperConstructorInvocation) nameInInvocation.getParent(); |
- ConstructorNodeElement expectedElement = invocation.getElement(); |
- assertNotNull(expectedElement); |
- assertSame(nameInInvocation.getElement(), expectedElement); |
- } |
- |
- public void test_mixin_1() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " foo() {}", |
- "}", |
- "class B extends Object with A {", // no unimplemented methods warning |
- "}", |
- "main() {", |
- " B b = new B();", |
- " A a = b;", // no 'not assignable' warning |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=8022 |
- */ |
- public void test_mixin_notObjectSuperclass() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {}", |
- "class B extends A {}", |
- "typedef C = Object with B;", |
- "class D extends Object with B {}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.ONLY_OBJECT_MIXIN_SUPERCLASS, 4, 25, 1), |
- errEx(ResolverErrorCode.ONLY_OBJECT_MIXIN_SUPERCLASS, 5, 29, 1)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=8025 |
- */ |
- public void test_mixin_withConstructor() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class M { M(); }", |
- "typedef A = Object with M;", |
- "class B extends Object with M {}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_CONSTRUCTOR, 3, 25, 1), |
- errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_CONSTRUCTOR, 4, 29, 1)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=8059 |
- */ |
- public void test_mixin_withSuperInvocation() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class M { foo() => super.toString(); }", |
- "typedef A = Object with M;", |
- "class B extends Object with M {}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_SUPER, 3, 25, 1), |
- errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_SUPER, 4, 29, 1)); |
- } |
- |
- /** |
- * <p> |
- * http://code.google.com/p/dart/issues/detail?id=8705 |
- */ |
- public void test_mixin_useInScope() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class M { foo() {} }", |
- "class A extends Object with M {", |
- " bar() {", |
- " foo();", |
- " }", |
- "}", |
- ""); |
- assertErrors(result.getErrors()); |
- } |
- |
- /** |
- * 20130122. Currently it is not allowed to have mixin with superclass other than Object. |
- */ |
- public void _test_mixin_dontAddSupertypes() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " methodA() {}", |
- "}", |
- "class B extends A {", |
- " methodB() {}", |
- "}", |
- "class C extends Object with B {", |
- "}", |
- "main() {", |
- " C c = new C();", |
- " A a = c;", // 'not assignable' warning - mixing is only "B" content |
- " B b = c;", // OK |
- " c.methodB();", // OK |
- " c.methodA();", // 'no such member' warning - mixing is only "B" content |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 12, 9, 1), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 15, 5, 7)); |
- } |
- |
- public void test_mixin_dontAddSupertypes2() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "abstract class A {", |
- " methodA();", |
- "}", |
- "abstract class B implements A {", |
- " methodB() {}", |
- "}", |
- "class C extends Object with B {", // no unimplemented methods warning |
- "}", |
- "main() {", |
- " C c = new C();", |
- " A a = c;", // 'not assignable' warning - mixing is only "B" content |
- " B b = c;", // OK |
- " c.methodB();", // OK |
- " c.methodA();", // 'no such member' warning - mixing is only "B" content |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 12, 9, 1), |
- errEx(TypeErrorCode.INTERFACE_HAS_NO_METHOD_NAMED, 15, 5, 7)); |
- } |
- |
- /** |
- * 20130122. Currently it is not allowed to have mixin with superclass other than Object. |
- */ |
- public void _test_mixin_dontAddSupertypes3() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " foo() {}", |
- "}", |
- "class B extends A {", |
- "}", |
- "abstract class C {", |
- " foo();", |
- "}", |
- "class D extends C with B {", // "foo" is not implemented, because NOT inherited from A |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.CONCRETE_CLASS_WITH_UNIMPLEMENTED_MEMBERS, 10, 7, 1)); |
- } |
- |
- /** |
- * 20130122. Currently it is not allowed to have mixin with superclass other than Object. |
- */ |
- public void _test_mixin_dontLookSupertype_getter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " get fA => 42;", |
- "}", |
- "class B extends A {", |
- " get fB => 42;", |
- "}", |
- "class C extends Object with B {", |
- "}", |
- "main() {", |
- " C c = new C();", |
- " print(c.fB);", |
- " print(c.fA);", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.NOT_A_MEMBER_OF, 13, 11, 2)); |
- } |
- |
- /** |
- * 20130122. Currently it is not allowed to have mixin with superclass other than Object. |
- */ |
- public void _test_mixin_dontLookSupertype_setter() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "class A {", |
- " set fA(x) {}", |
- "}", |
- "class B extends A {", |
- " set fB(x) {}", |
- "}", |
- "class C extends Object with B {", |
- "}", |
- "main() {", |
- " C c = new C();", |
- " c.fB = 1;", |
- " c.fA = 2;", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.NOT_A_MEMBER_OF, 13, 5, 2)); |
- } |
- |
- public void test_mixin_disallowMixinApplication_asMixin() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "typedef M = Object with M;", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(ResolverErrorCode.CANNOT_MIXIN_CLASS_WITH_MIXINS, 2, 25, 1)); |
- } |
- |
- public void test_StringPlus() throws Exception { |
- AnalyzeLibraryResult result = analyzeLibrary( |
- "// filler filler filler filler filler filler filler filler filler filler", |
- "main() {", |
- " var v1 = '1' + '2';", |
- " var v2 = '1' + 2;", |
- "}", |
- ""); |
- assertErrors( |
- result.getErrors(), |
- errEx(TypeErrorCode.TYPE_NOT_ASSIGNMENT_COMPATIBLE, 4, 18, 1)); |
- } |
-} |