| 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));
|
| - }
|
| -}
|
|
|