Index: pkg/analyzer/test/src/task/dart_test.dart |
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart |
index b22902c58c8ffe89c28803b760cfa0cd38837ea0..1c94faf5499ec7b3dd27fc87e62a9d4548518cfd 100644 |
--- a/pkg/analyzer/test/src/task/dart_test.dart |
+++ b/pkg/analyzer/test/src/task/dart_test.dart |
@@ -15,6 +15,7 @@ import 'package:analyzer/src/generated/resolver.dart'; |
import 'package:analyzer/src/generated/scanner.dart'; |
import 'package:analyzer/src/generated/sdk.dart'; |
import 'package:analyzer/src/generated/source.dart'; |
+import 'package:analyzer/src/services/lint.dart'; |
import 'package:analyzer/src/task/dart.dart'; |
import 'package:analyzer/src/task/html.dart'; |
import 'package:analyzer/task/dart.dart'; |
@@ -48,6 +49,7 @@ main() { |
runReflectiveTests(GatherUsedImportedElementsTaskTest); |
runReflectiveTests(GatherUsedLocalElementsTaskTest); |
runReflectiveTests(GenerateHintsTaskTest); |
+ runReflectiveTests(GenerateLintsTaskTest); |
runReflectiveTests(InferInstanceMembersInUnitTaskTest); |
runReflectiveTests(InferStaticVariableTypesInUnitTaskTest); |
runReflectiveTests(InferStaticVariableTypeTaskTest); |
@@ -98,6 +100,7 @@ isInstanceOf isGatherUsedImportedElementsTask = |
isInstanceOf isGatherUsedLocalElementsTask = |
new isInstanceOf<GatherUsedLocalElementsTask>(); |
isInstanceOf isGenerateHintsTask = new isInstanceOf<GenerateHintsTask>(); |
+isInstanceOf isGenerateLintsTask = new isInstanceOf<GenerateLintsTask>(); |
isInstanceOf isInferInstanceMembersInUnitTask = |
new isInstanceOf<InferInstanceMembersInUnitTask>(); |
isInstanceOf isInferStaticVariableTypesInUnitTask = |
@@ -122,6 +125,8 @@ isInstanceOf isResolveVariableReferencesTask = |
isInstanceOf isScanDartTask = new isInstanceOf<ScanDartTask>(); |
isInstanceOf isVerifyUnitTask = new isInstanceOf<VerifyUnitTask>(); |
+final LintCode _testLintCode = new LintCode('test lint', 'test lint code'); |
+ |
@reflectiveTest |
class BuildCompilationUnitElementTaskTest extends _AbstractDartTaskTest { |
Source source; |
@@ -1876,6 +1881,62 @@ f(A a) { |
} |
@reflectiveTest |
+class GenerateLintsTaskTest extends _AbstractDartTaskTest { |
+ void enableLints() { |
+ AnalysisOptionsImpl options = context.analysisOptions; |
+ options.lint = true; |
+ context.analysisOptions = options; |
+ } |
+ |
+ @override |
+ void setUp() { |
+ super.setUp(); |
+ enableLints(); |
+ } |
+ |
+ @override |
+ void tearDown() { |
+ LintGenerator.LINTERS.clear(); |
+ super.tearDown(); |
+ } |
+ |
+ test_camel_case_types() { |
+ Source source = newSource( |
+ '/test.dart', |
+ ''' |
+class a { } |
+'''); |
+ |
+ LintGenerator.LINTERS.clear(); |
+ LintGenerator.LINTERS.add(new GenerateLintsTaskTest_TestLinter()); |
+ |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, LINTS, matcher: isGenerateLintsTask); |
+ // validate |
+ _fillErrorListener(LINTS); |
+ errorListener.assertErrorsWithCodes(<ErrorCode>[_testLintCode]); |
+ } |
+} |
+ |
+class GenerateLintsTaskTest_AstVisitor extends SimpleAstVisitor { |
+ Linter linter; |
+ GenerateLintsTaskTest_AstVisitor(this.linter); |
+ |
+ @override |
+ visitClassDeclaration(ClassDeclaration node) { |
+ if (!new RegExp(r'^([_]*)([A-Z]+[a-z0-9]*)+$') |
+ .hasMatch(node.name.toString())) { |
+ linter.reporter.reportErrorForNode(_testLintCode, node, []); |
+ } |
+ } |
+} |
+ |
+class GenerateLintsTaskTest_TestLinter extends Linter { |
+ @override |
+ AstVisitor getVisitor() => new GenerateLintsTaskTest_AstVisitor(this); |
+} |
+ |
+@reflectiveTest |
class InferInstanceMembersInUnitTaskTest extends _AbstractDartTaskTest { |
void test_perform() { |
enableStrongMode(); |
@@ -1973,6 +2034,23 @@ class C { |
@reflectiveTest |
class InferStaticVariableTypesInUnitTaskTest extends _AbstractDartTaskTest { |
+ void test_perform_const_field() { |
+ enableStrongMode(); |
+ AnalysisTarget source = newSource( |
+ '/test.dart', |
+ ''' |
+class M { |
+ static const X = ""; |
+} |
+'''); |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6, |
+ matcher: isInferStaticVariableTypesInUnitTask); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT6]; |
+ VariableDeclaration declaration = getFieldInClass(unit, 'M', 'X'); |
+ InterfaceType stringType = context.typeProvider.stringType; |
+ expect(declaration.element.type, stringType); |
+ } |
+ |
void test_perform_nestedDeclarations() { |
enableStrongMode(); |
AnalysisTarget source = newSource( |
@@ -2050,23 +2128,6 @@ var Y = () { |
InterfaceType intType = context.typeProvider.intType; |
expect(expression.staticType, intType); |
} |
- |
- void test_perform_const_field() { |
- enableStrongMode(); |
- AnalysisTarget source = newSource( |
- '/test.dart', |
- ''' |
-class M { |
- static const X = ""; |
-} |
-'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6, |
- matcher: isInferStaticVariableTypesInUnitTask); |
- CompilationUnit unit = outputs[RESOLVED_UNIT6]; |
- VariableDeclaration declaration = getFieldInClass(unit, 'M', 'X'); |
- InterfaceType stringType = context.typeProvider.stringType; |
- expect(declaration.element.type, stringType); |
- } |
} |
@reflectiveTest |
@@ -2128,31 +2189,6 @@ class C { |
expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); |
} |
- void test_perform_reresolution() { |
- AnalysisTarget source = newSource( |
- '/test.dart', |
- ''' |
-const topLevel = ''; |
-class C { |
- String field = topLevel; |
-} |
-'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5); |
- CompilationUnit unit = outputs[RESOLVED_UNIT5]; |
- VariableDeclaration topLevelDecl = getTopLevelVariable(unit, 'topLevel'); |
- VariableDeclaration fieldDecl = getFieldInClass(unit, 'C', 'field'); |
- VariableElement topLevel = topLevelDecl.name.staticElement; |
- VariableElement field = fieldDecl.name.staticElement; |
- |
- computeResult(field, INFERRED_STATIC_VARIABLE, |
- matcher: isInferStaticVariableTypeTask); |
- InterfaceType stringType = context.typeProvider.stringType; |
- expect(topLevel.type, stringType); |
- expect(field.type, stringType); |
- expect(fieldDecl.initializer.staticType, stringType); |
- expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); |
- } |
- |
void test_perform_const() { |
AnalysisTarget source = newSource( |
'/test.dart', |
@@ -2231,6 +2267,31 @@ var a = null; |
expect(a.type.isDynamic, isTrue); |
expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); |
} |
+ |
+ void test_perform_reresolution() { |
+ AnalysisTarget source = newSource( |
+ '/test.dart', |
+ ''' |
+const topLevel = ''; |
+class C { |
+ String field = topLevel; |
+} |
+'''); |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT5]; |
+ VariableDeclaration topLevelDecl = getTopLevelVariable(unit, 'topLevel'); |
+ VariableDeclaration fieldDecl = getFieldInClass(unit, 'C', 'field'); |
+ VariableElement topLevel = topLevelDecl.name.staticElement; |
+ VariableElement field = fieldDecl.name.staticElement; |
+ |
+ computeResult(field, INFERRED_STATIC_VARIABLE, |
+ matcher: isInferStaticVariableTypeTask); |
+ InterfaceType stringType = context.typeProvider.stringType; |
+ expect(topLevel.type, stringType); |
+ expect(field.type, stringType); |
+ expect(fieldDecl.initializer.staticType, stringType); |
+ expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); |
+ } |
} |
@reflectiveTest |
@@ -2594,372 +2655,307 @@ class C { |
} |
@reflectiveTest |
-class StrongModeInferenceTest extends _AbstractDartTaskTest { |
+class ResolveLibraryTypeNamesTaskTest extends _AbstractDartTaskTest { |
+ test_perform() { |
+ Source sourceLib = newSource( |
+ '/my_lib.dart', |
+ ''' |
+library my_lib; |
+part 'my_part.dart'; |
+class A {} |
+class B extends A {} |
+'''); |
+ newSource( |
+ '/my_part.dart', |
+ ''' |
+part of my_lib; |
+class C extends A {} |
+'''); |
+ computeResult(sourceLib, LIBRARY_ELEMENT5, |
+ matcher: isResolveLibraryTypeNamesTask); |
+ // validate |
+ LibraryElement library = outputs[LIBRARY_ELEMENT5]; |
+ { |
+ ClassElement classB = library.getType('B'); |
+ expect(classB.supertype.displayName, 'A'); |
+ } |
+ { |
+ ClassElement classC = library.getType('C'); |
+ expect(classC.supertype.displayName, 'A'); |
+ } |
+ } |
- @override |
- void setUp() { |
- super.setUp(); |
- enableStrongMode(); |
+ test_perform_external() { |
+ Source sourceA = newSource( |
+ '/a.dart', |
+ ''' |
+library a; |
+import 'b.dart'; |
+class A extends B {} |
+'''); |
+ newSource( |
+ '/b.dart', |
+ ''' |
+library b; |
+class B {} |
+'''); |
+ // The reference A to B should be resolved, but there's no requirement that |
+ // the full class hierarchy be resolved. |
+ computeResult(sourceA, LIBRARY_ELEMENT5, |
+ matcher: isResolveLibraryTypeNamesTask); |
+ // validate |
+ LibraryElement library = outputs[LIBRARY_ELEMENT5]; |
+ { |
+ ClassElement clazz = library.getType('A'); |
+ expect(clazz.displayName, 'A'); |
+ clazz = clazz.supertype.element; |
+ expect(clazz.displayName, 'B'); |
+ } |
} |
+} |
- // Check that even within a static variable cycle, inferred |
- // types get propagated to the members of the cycle. |
- void test_perform_cycle() { |
- AnalysisTarget source = newSource( |
+@reflectiveTest |
+class ResolveUnitTypeNamesTaskTest extends _AbstractDartTaskTest { |
+ test_perform() { |
+ Source source = newSource( |
'/test.dart', |
''' |
-var piFirst = true; |
-var pi = piFirst ? 3.14 : tau / 2; |
-var tau = piFirst ? pi * 2 : 6.28; |
+class A {} |
+class B extends A {} |
+int f(String p) => p.length; |
'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
- CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- VariableElement piFirst = |
- getTopLevelVariable(unit, 'piFirst').name.staticElement; |
- VariableElement pi = getTopLevelVariable(unit, 'pi').name.staticElement; |
- VariableElement tau = getTopLevelVariable(unit, 'tau').name.staticElement; |
- Expression piFirstUse = (getTopLevelVariable(unit, 'tau').initializer |
- as ConditionalExpression).condition; |
- |
- expect(piFirstUse.staticType, context.typeProvider.boolType); |
- expect(piFirst.type, context.typeProvider.boolType); |
- expect(pi.type.isDynamic, isTrue); |
- expect(tau.type.isDynamic, isTrue); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, RESOLVED_UNIT3, matcher: isResolveUnitTypeNamesTask); |
+ // validate |
+ CompilationUnit unit = outputs[RESOLVED_UNIT3]; |
+ { |
+ ClassDeclaration nodeA = unit.declarations[0]; |
+ ClassDeclaration nodeB = unit.declarations[1]; |
+ DartType extendsType = nodeB.extendsClause.superclass.type; |
+ expect(extendsType, nodeA.element.type); |
+ } |
+ { |
+ FunctionDeclaration functionNode = unit.declarations[2]; |
+ DartType returnType = functionNode.returnType.type; |
+ List<FormalParameter> parameters = |
+ functionNode.functionExpression.parameters.parameters; |
+ expect(returnType.displayName, 'int'); |
+ expect(parameters[0].element.type.displayName, 'String'); |
+ } |
} |
- void test_perform_local_explicit_disabled() { |
- AnalysisTarget source = newSource( |
+ test_perform_errors() { |
+ Source source = newSource( |
'/test.dart', |
''' |
- test() { |
- int x = 3; |
- x = "hi"; |
- } |
+NoSuchClass f() => null; |
'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
- CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- |
- InterfaceType intType = context.typeProvider.intType; |
- InterfaceType stringType = context.typeProvider.stringType; |
- |
- List<Statement> statements = getStatementsInTopLevelFunction(unit, "test"); |
- VariableDeclaration decl = |
- (statements[0] as VariableDeclarationStatement).variables.variables[0]; |
- expect(decl.element.type, intType); |
- expect(decl.initializer.staticType, intType); |
- |
- ExpressionStatement statement = statements[1]; |
- AssignmentExpression assgn = statement.expression; |
- expect(assgn.leftHandSide.staticType, intType); |
- expect(assgn.rightHandSide.staticType, stringType); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, RESOLVE_TYPE_NAMES_ERRORS, |
+ matcher: isResolveUnitTypeNamesTask); |
+ // validate |
+ _fillErrorListener(RESOLVE_TYPE_NAMES_ERRORS); |
+ errorListener |
+ .assertErrorsWithCodes(<ErrorCode>[StaticWarningCode.UNDEFINED_CLASS]); |
} |
- void assertVariableDeclarationTypes( |
- VariableDeclaration decl, DartType varType, DartType initializerType) { |
- expect(decl.element.type, varType); |
- expect(decl.initializer.staticType, initializerType); |
- } |
- |
- void assertVariableDeclarationStatementTypes( |
- Statement stmt, DartType varType, DartType initializerType) { |
- VariableDeclaration decl = |
- (stmt as VariableDeclarationStatement).variables.variables[0]; |
- assertVariableDeclarationTypes(decl, varType, initializerType); |
- } |
- |
- void assertAssignmentStatementTypes( |
- Statement stmt, DartType leftType, DartType rightType) { |
- AssignmentExpression assgn = (stmt as ExpressionStatement).expression; |
- expect(assgn.leftHandSide.staticType, leftType); |
- expect(assgn.rightHandSide.staticType, rightType); |
- } |
- |
- // Test that local variables in method bodies are inferred appropriately |
- void test_perform_inference_local_variables() { |
- AnalysisTarget source = newSource( |
+ test_perform_typedef() { |
+ Source source = newSource( |
'/test.dart', |
''' |
- test() { |
- int x = 3; |
- x = "hi"; |
- var y = 3; |
- y = "hi"; |
- } |
+typedef int F(G g); |
+typedef String G(int p); |
'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
- CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- |
- InterfaceType intType = context.typeProvider.intType; |
- InterfaceType stringType = context.typeProvider.stringType; |
- |
- List<Statement> statements = getStatementsInTopLevelFunction(unit, "test"); |
- |
- assertVariableDeclarationStatementTypes(statements[0], intType, intType); |
- assertAssignmentStatementTypes(statements[1], intType, stringType); |
- assertVariableDeclarationStatementTypes(statements[2], intType, intType); |
- assertAssignmentStatementTypes(statements[3], intType, stringType); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, RESOLVED_UNIT3, matcher: isResolveUnitTypeNamesTask); |
+ // validate |
+ CompilationUnit unit = outputs[RESOLVED_UNIT3]; |
+ FunctionTypeAlias nodeF = unit.declarations[0]; |
+ FunctionTypeAlias nodeG = unit.declarations[1]; |
+ { |
+ FormalParameter parameter = nodeF.parameters.parameters[0]; |
+ DartType parameterType = parameter.element.type; |
+ Element returnTypeElement = nodeF.returnType.type.element; |
+ expect(returnTypeElement.displayName, 'int'); |
+ expect(parameterType.element, nodeG.element); |
+ } |
+ { |
+ FormalParameter parameter = nodeG.parameters.parameters[0]; |
+ DartType parameterType = parameter.element.type; |
+ expect(nodeG.returnType.type.element.displayName, 'String'); |
+ expect(parameterType.element.displayName, 'int'); |
+ } |
} |
- // Test inference interactions between local variables and fields |
- void test_perform_inference_local_variables_fields() { |
- AnalysisTarget source = newSource( |
+ test_perform_typedef_errors() { |
+ Source source = newSource( |
'/test.dart', |
''' |
- class A { |
- int x = 0; |
- |
- test1() { |
- var a = x; |
- a = "hi"; |
- a = 3; |
- var b = y; |
- b = "hi"; |
- b = 4; |
- var c = z; |
- c = "hi"; |
- c = 4; |
- } |
- |
- int y; // field def after use |
- final z = 42; // should infer `int` |
- } |
+typedef int F(NoSuchType p); |
'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
- CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- |
- InterfaceType intType = context.typeProvider.intType; |
- InterfaceType stringType = context.typeProvider.stringType; |
- |
- List<Statement> statements = getStatementsInMethod(unit, "A", "test1"); |
- |
- assertVariableDeclarationStatementTypes(statements[0], intType, intType); |
- assertAssignmentStatementTypes(statements[1], intType, stringType); |
- assertAssignmentStatementTypes(statements[2], intType, intType); |
- |
- assertVariableDeclarationStatementTypes(statements[3], intType, intType); |
- assertAssignmentStatementTypes(statements[4], intType, stringType); |
- assertAssignmentStatementTypes(statements[5], intType, intType); |
- |
- assertVariableDeclarationStatementTypes(statements[6], intType, intType); |
- assertAssignmentStatementTypes(statements[7], intType, stringType); |
- assertAssignmentStatementTypes(statements[8], intType, intType); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, RESOLVE_TYPE_NAMES_ERRORS, |
+ matcher: isResolveUnitTypeNamesTask); |
+ // validate |
+ _fillErrorListener(RESOLVE_TYPE_NAMES_ERRORS); |
+ errorListener |
+ .assertErrorsWithCodes(<ErrorCode>[StaticWarningCode.UNDEFINED_CLASS]); |
+ } |
+} |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit, "A", "x"), intType, intType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit, "A", "z"), intType, intType); |
+@reflectiveTest |
+class ResolveVariableReferencesTaskTest extends _AbstractDartTaskTest { |
+ /** |
+ * Verify that the mutated states of the given [variable] correspond to the |
+ * [mutatedInClosure] and [mutatedInScope] matchers. |
+ */ |
+ void expectMutated(VariableElement variable, Matcher mutatedInClosure, |
+ Matcher mutatedInScope) { |
+ expect(variable.isPotentiallyMutatedInClosure, mutatedInClosure); |
+ expect(variable.isPotentiallyMutatedInScope, mutatedInScope); |
} |
- // Test inference interactions between local variables and top level |
- // variables |
- void test_perform_inference_local_variables_topLevel() { |
- AnalysisTarget source = newSource( |
+ test_perform_buildClosureLibraryElements() { |
+ Source source = newSource( |
'/test.dart', |
''' |
- int x = 0; |
- |
- test1() { |
- var a = x; |
- a = /*severe:StaticTypeError*/"hi"; |
- a = 3; |
- var b = y; |
- b = /*severe:StaticTypeError*/"hi"; |
- b = 4; |
- var c = z; |
- c = /*severe:StaticTypeError*/"hi"; |
- c = 4; |
- } |
- |
- int y = 0; // field def after use |
- final z = 42; // should infer `int` |
+main() { |
+} |
'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
- CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- |
- InterfaceType intType = context.typeProvider.intType; |
- InterfaceType stringType = context.typeProvider.stringType; |
- |
- List<Statement> statements = getStatementsInTopLevelFunction(unit, "test1"); |
- |
- assertVariableDeclarationStatementTypes(statements[0], intType, intType); |
- assertAssignmentStatementTypes(statements[1], intType, stringType); |
- assertAssignmentStatementTypes(statements[2], intType, intType); |
- |
- assertVariableDeclarationStatementTypes(statements[3], intType, intType); |
- assertAssignmentStatementTypes(statements[4], intType, stringType); |
- assertAssignmentStatementTypes(statements[5], intType, intType); |
- |
- assertVariableDeclarationStatementTypes(statements[6], intType, intType); |
- assertAssignmentStatementTypes(statements[7], intType, stringType); |
- assertAssignmentStatementTypes(statements[8], intType, intType); |
- |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit, "x"), intType, intType); |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit, "y"), intType, intType); |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit, "z"), intType, intType); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, RESOLVED_UNIT4, |
+ matcher: isResolveVariableReferencesTask); |
} |
- // Test that inference does not propagate from null |
- void test_perform_inference_null() { |
- AnalysisTarget source = newSource( |
+ test_perform_local() { |
+ Source source = newSource( |
'/test.dart', |
''' |
- var x = null; |
- var y = 3; |
- class A { |
- static var x = null; |
- static var y = 3; |
- |
- var x2 = null; |
- var y2 = 3; |
- } |
- |
- test() { |
- x = "hi"; |
- y = /*severe:StaticTypeError*/"hi"; |
- A.x = "hi"; |
- A.y = /*severe:StaticTypeError*/"hi"; |
- new A().x2 = "hi"; |
- new A().y2 = /*severe:StaticTypeError*/"hi"; |
- } |
+main() { |
+ var v1 = 1; |
+ var v2 = 1; |
+ var v3 = 1; |
+ var v4 = 1; |
+ v2 = 2; |
+ v4 = 2; |
+ localFunction() { |
+ v3 = 3; |
+ v4 = 3; |
+ } |
+} |
'''); |
- computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
- CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- |
- InterfaceType intType = context.typeProvider.intType; |
- InterfaceType stringType = context.typeProvider.stringType; |
- DartType bottomType = context.typeProvider.bottomType; |
- DartType dynamicType = context.typeProvider.dynamicType; |
- |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit, "x"), dynamicType, bottomType); |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit, "y"), intType, intType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit, "A", "x"), dynamicType, bottomType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit, "A", "y"), intType, intType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit, "A", "x2"), dynamicType, bottomType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit, "A", "y2"), intType, intType); |
- |
- List<Statement> statements = getStatementsInTopLevelFunction(unit, "test"); |
- |
- assertAssignmentStatementTypes(statements[0], dynamicType, stringType); |
- assertAssignmentStatementTypes(statements[1], intType, stringType); |
- assertAssignmentStatementTypes(statements[2], dynamicType, stringType); |
- assertAssignmentStatementTypes(statements[3], intType, stringType); |
- assertAssignmentStatementTypes(statements[4], dynamicType, stringType); |
- assertAssignmentStatementTypes(statements[5], intType, stringType); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, RESOLVED_UNIT4, |
+ matcher: isResolveVariableReferencesTask); |
+ // validate |
+ CompilationUnit unit = outputs[RESOLVED_UNIT4]; |
+ FunctionElement main = unit.element.functions[0]; |
+ expectMutated(main.localVariables[0], isFalse, isFalse); |
+ expectMutated(main.localVariables[1], isFalse, isTrue); |
+ expectMutated(main.localVariables[2], isTrue, isTrue); |
+ expectMutated(main.localVariables[3], isTrue, isTrue); |
} |
- // Test inference across units (non-cyclic) |
- void test_perform_inference_cross_unit_non_cyclic() { |
- AnalysisTarget firstSource = newSource( |
- '/a.dart', |
- ''' |
- var x = 2; |
- class A { static var x = 2; } |
-'''); |
- AnalysisTarget secondSource = newSource( |
+ test_perform_parameter() { |
+ Source source = newSource( |
'/test.dart', |
''' |
- import 'a.dart'; |
- var y = x; |
- class B { static var y = A.x; } |
- |
- test1() { |
- x = /*severe:StaticTypeError*/"hi"; |
- y = /*severe:StaticTypeError*/"hi"; |
- A.x = /*severe:StaticTypeError*/"hi"; |
- B.y = /*severe:StaticTypeError*/"hi"; |
- } |
-'''); |
- computeResult( |
- new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8); |
- CompilationUnit unit1 = outputs[RESOLVED_UNIT8]; |
- computeResult( |
- new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8); |
- CompilationUnit unit2 = outputs[RESOLVED_UNIT8]; |
- |
- InterfaceType intType = context.typeProvider.intType; |
- InterfaceType stringType = context.typeProvider.stringType; |
- |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit1, "x"), intType, intType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit1, "A", "x"), intType, intType); |
- |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit2, "y"), intType, intType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit2, "B", "y"), intType, intType); |
- |
- List<Statement> statements = |
- getStatementsInTopLevelFunction(unit2, "test1"); |
+main(p1, p2, p3, p4) { |
+ p2 = 2; |
+ p4 = 2; |
+ localFunction() { |
+ p3 = 3; |
+ p4 = 3; |
+ } |
+} |
+'''); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, RESOLVED_UNIT4, |
+ matcher: isResolveVariableReferencesTask); |
+ // validate |
+ CompilationUnit unit = outputs[RESOLVED_UNIT4]; |
+ FunctionElement main = unit.element.functions[0]; |
+ expectMutated(main.parameters[0], isFalse, isFalse); |
+ expectMutated(main.parameters[1], isFalse, isTrue); |
+ expectMutated(main.parameters[2], isTrue, isTrue); |
+ expectMutated(main.parameters[3], isTrue, isTrue); |
+ } |
+} |
- assertAssignmentStatementTypes(statements[0], intType, stringType); |
- assertAssignmentStatementTypes(statements[1], intType, stringType); |
+@reflectiveTest |
+class ScanDartTaskTest extends _AbstractDartTaskTest { |
+ test_perform_errors() { |
+ _performScanTask('import "'); |
+ expect(outputs, hasLength(3)); |
+ expect(outputs[LINE_INFO], isNotNull); |
+ expect(outputs[SCAN_ERRORS], hasLength(1)); |
+ expect(outputs[TOKEN_STREAM], isNotNull); |
} |
- // Test inference across units (cyclic) |
- void test_perform_inference_cross_unit_cyclic() { |
- AnalysisTarget firstSource = newSource( |
- '/a.dart', |
- ''' |
- import 'test.dart'; |
- var x = 2; |
- class A { static var x = 2; } |
-'''); |
- AnalysisTarget secondSource = newSource( |
- '/test.dart', |
- ''' |
- import 'a.dart'; |
- var y = x; |
- class B { static var y = A.x; } |
+ test_perform_noErrors() { |
+ _performScanTask('class A {}'); |
+ expect(outputs, hasLength(3)); |
+ expect(outputs[LINE_INFO], isNotNull); |
+ expect(outputs[SCAN_ERRORS], hasLength(0)); |
+ expect(outputs[TOKEN_STREAM], isNotNull); |
+ } |
- test1() { |
- int t = 3; |
- t = x; |
- t = y; |
- t = A.x; |
- t = B.y; |
- } |
-'''); |
- computeResult( |
- new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8); |
- CompilationUnit unit1 = outputs[RESOLVED_UNIT8]; |
- computeResult( |
- new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8); |
- CompilationUnit unit2 = outputs[RESOLVED_UNIT8]; |
+ test_perform_script() { |
+ String scriptContent = ''' |
+ void buttonPressed() { |
+ '''; |
+ String htmlContent = ''' |
+<!DOCTYPE html> |
+<html> |
+ <head> |
+ <title>test page</title> |
+ <script type='application/dart'>$scriptContent</script> |
+ </head> |
+ <body>Test</body> |
+</html> |
+'''; |
+ Source source = newSource('/test.html', htmlContent); |
+ DartScript script = |
+ new DartScript(source, [new ScriptFragment(97, 5, 36, scriptContent)]); |
- InterfaceType intType = context.typeProvider.intType; |
+ computeResult(script, TOKEN_STREAM, matcher: isScanDartTask); |
+ expect(outputs[LINE_INFO], isNotNull); |
+ expect(outputs[SCAN_ERRORS], isEmpty); |
+ Token tokenStream = outputs[TOKEN_STREAM]; |
+ expect(tokenStream, isNotNull); |
+ expect(tokenStream.lexeme, 'void'); |
+ } |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit1, "x"), intType, intType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit1, "A", "x"), intType, intType); |
+ void _performScanTask(String content) { |
+ AnalysisTarget target = newSource('/test.dart', content); |
+ computeResult(target, TOKEN_STREAM, matcher: isScanDartTask); |
+ } |
+} |
- assertVariableDeclarationTypes( |
- getTopLevelVariable(unit2, "y"), intType, intType); |
- assertVariableDeclarationTypes( |
- getFieldInClass(unit2, "B", "y"), intType, intType); |
+@reflectiveTest |
+class StrongModeInferenceTest extends _AbstractDartTaskTest { |
+ void assertAssignmentStatementTypes( |
+ Statement stmt, DartType leftType, DartType rightType) { |
+ AssignmentExpression assgn = (stmt as ExpressionStatement).expression; |
+ expect(assgn.leftHandSide.staticType, leftType); |
+ expect(assgn.rightHandSide.staticType, rightType); |
+ } |
- List<Statement> statements = |
- getStatementsInTopLevelFunction(unit2, "test1"); |
+ // Check that even within a static variable cycle, inferred |
+ // types get propagated to the members of the cycle. |
+ void assertVariableDeclarationStatementTypes( |
+ Statement stmt, DartType varType, DartType initializerType) { |
+ VariableDeclaration decl = |
+ (stmt as VariableDeclarationStatement).variables.variables[0]; |
+ assertVariableDeclarationTypes(decl, varType, initializerType); |
+ } |
- assertAssignmentStatementTypes(statements[1], intType, intType); |
- assertAssignmentStatementTypes(statements[2], intType, intType); |
- assertAssignmentStatementTypes(statements[3], intType, intType); |
- assertAssignmentStatementTypes(statements[4], intType, intType); |
+ void assertVariableDeclarationTypes( |
+ VariableDeclaration decl, DartType varType, DartType initializerType) { |
+ expect(decl.element.type, varType); |
+ expect(decl.initializer.staticType, initializerType); |
} |
- // Test inference of instance fields across units |
- // TODO(leafp): Fix this |
- // https://github.com/dart-lang/dev_compiler/issues/354 |
void fail_perform_inference_cross_unit_instance() { |
List<Source> sources = newSources({ |
'/a7.dart': ''' |
@@ -3002,9 +2998,6 @@ var tau = piFirst ? pi * 2 : 6.28; |
assertAssignmentStatementTypes(statements[1], intType, intType); |
} |
- // Test inference between static and instance fields |
- // TODO(leafp): Fix this |
- // https://github.com/dart-lang/dev_compiler/issues/354 |
void fail_perform_inference_cross_unit_static_instance() { |
List<Source> sources = newSources({ |
'/a.dart': ''' |
@@ -3040,298 +3033,365 @@ var tau = piFirst ? pi * 2 : 6.28; |
InterfaceType intType = context.typeProvider.intType; |
assertVariableDeclarationTypes( |
- getFieldInClass(unit0, "A", "a1"), intType, intType); |
+ getFieldInClass(unit0, "A", "a1"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit0, "A", "a2"), intType, intType); |
+ |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit1, "B", "b1"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit1, "B", "b2"), intType, intType); |
+ |
+ List<Statement> statements = |
+ getStatementsInTopLevelFunction(unit2, "test1"); |
+ |
+ assertAssignmentStatementTypes(statements[1], intType, intType); |
+ assertAssignmentStatementTypes(statements[2], intType, intType); |
+ } |
+ |
+ @override |
+ void setUp() { |
+ super.setUp(); |
+ enableStrongMode(); |
+ } |
+ |
+ // Test that local variables in method bodies are inferred appropriately |
+ void test_perform_cycle() { |
+ AnalysisTarget source = newSource( |
+ '/test.dart', |
+ ''' |
+var piFirst = true; |
+var pi = piFirst ? 3.14 : tau / 2; |
+var tau = piFirst ? pi * 2 : 6.28; |
+'''); |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
+ VariableElement piFirst = |
+ getTopLevelVariable(unit, 'piFirst').name.staticElement; |
+ VariableElement pi = getTopLevelVariable(unit, 'pi').name.staticElement; |
+ VariableElement tau = getTopLevelVariable(unit, 'tau').name.staticElement; |
+ Expression piFirstUse = (getTopLevelVariable(unit, 'tau').initializer |
+ as ConditionalExpression).condition; |
+ |
+ expect(piFirstUse.staticType, context.typeProvider.boolType); |
+ expect(piFirst.type, context.typeProvider.boolType); |
+ expect(pi.type.isDynamic, isTrue); |
+ expect(tau.type.isDynamic, isTrue); |
+ } |
+ |
+ // Test inference interactions between local variables and fields |
+ void test_perform_inference_cross_unit_cyclic() { |
+ AnalysisTarget firstSource = newSource( |
+ '/a.dart', |
+ ''' |
+ import 'test.dart'; |
+ var x = 2; |
+ class A { static var x = 2; } |
+'''); |
+ AnalysisTarget secondSource = newSource( |
+ '/test.dart', |
+ ''' |
+ import 'a.dart'; |
+ var y = x; |
+ class B { static var y = A.x; } |
+ |
+ test1() { |
+ int t = 3; |
+ t = x; |
+ t = y; |
+ t = A.x; |
+ t = B.y; |
+ } |
+'''); |
+ computeResult( |
+ new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8); |
+ CompilationUnit unit1 = outputs[RESOLVED_UNIT8]; |
+ computeResult( |
+ new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8); |
+ CompilationUnit unit2 = outputs[RESOLVED_UNIT8]; |
+ |
+ InterfaceType intType = context.typeProvider.intType; |
+ |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit1, "x"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit1, "A", "x"), intType, intType); |
+ |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit2, "y"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit2, "B", "y"), intType, intType); |
+ |
+ List<Statement> statements = |
+ getStatementsInTopLevelFunction(unit2, "test1"); |
+ |
+ assertAssignmentStatementTypes(statements[1], intType, intType); |
+ assertAssignmentStatementTypes(statements[2], intType, intType); |
+ assertAssignmentStatementTypes(statements[3], intType, intType); |
+ assertAssignmentStatementTypes(statements[4], intType, intType); |
+ } |
+ |
+ // Test inference interactions between local variables and top level |
+ // variables |
+ void test_perform_inference_cross_unit_non_cyclic() { |
+ AnalysisTarget firstSource = newSource( |
+ '/a.dart', |
+ ''' |
+ var x = 2; |
+ class A { static var x = 2; } |
+'''); |
+ AnalysisTarget secondSource = newSource( |
+ '/test.dart', |
+ ''' |
+ import 'a.dart'; |
+ var y = x; |
+ class B { static var y = A.x; } |
+ |
+ test1() { |
+ x = /*severe:StaticTypeError*/"hi"; |
+ y = /*severe:StaticTypeError*/"hi"; |
+ A.x = /*severe:StaticTypeError*/"hi"; |
+ B.y = /*severe:StaticTypeError*/"hi"; |
+ } |
+'''); |
+ computeResult( |
+ new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8); |
+ CompilationUnit unit1 = outputs[RESOLVED_UNIT8]; |
+ computeResult( |
+ new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8); |
+ CompilationUnit unit2 = outputs[RESOLVED_UNIT8]; |
+ |
+ InterfaceType intType = context.typeProvider.intType; |
+ InterfaceType stringType = context.typeProvider.stringType; |
+ |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit1, "x"), intType, intType); |
assertVariableDeclarationTypes( |
- getFieldInClass(unit0, "A", "a2"), intType, intType); |
+ getFieldInClass(unit1, "A", "x"), intType, intType); |
assertVariableDeclarationTypes( |
- getFieldInClass(unit1, "B", "b1"), intType, intType); |
+ getTopLevelVariable(unit2, "y"), intType, intType); |
assertVariableDeclarationTypes( |
- getFieldInClass(unit1, "B", "b2"), intType, intType); |
+ getFieldInClass(unit2, "B", "y"), intType, intType); |
List<Statement> statements = |
getStatementsInTopLevelFunction(unit2, "test1"); |
- assertAssignmentStatementTypes(statements[1], intType, intType); |
- assertAssignmentStatementTypes(statements[2], intType, intType); |
+ assertAssignmentStatementTypes(statements[0], intType, stringType); |
+ assertAssignmentStatementTypes(statements[1], intType, stringType); |
} |
-} |
-@reflectiveTest |
-class ResolveLibraryTypeNamesTaskTest extends _AbstractDartTaskTest { |
- test_perform() { |
- Source sourceLib = newSource( |
- '/my_lib.dart', |
- ''' |
-library my_lib; |
-part 'my_part.dart'; |
-class A {} |
-class B extends A {} |
-'''); |
- newSource( |
- '/my_part.dart', |
+ // Test that inference does not propagate from null |
+ void test_perform_inference_local_variables() { |
+ AnalysisTarget source = newSource( |
+ '/test.dart', |
''' |
-part of my_lib; |
-class C extends A {} |
+ test() { |
+ int x = 3; |
+ x = "hi"; |
+ var y = 3; |
+ y = "hi"; |
+ } |
'''); |
- computeResult(sourceLib, LIBRARY_ELEMENT5, |
- matcher: isResolveLibraryTypeNamesTask); |
- // validate |
- LibraryElement library = outputs[LIBRARY_ELEMENT5]; |
- { |
- ClassElement classB = library.getType('B'); |
- expect(classB.supertype.displayName, 'A'); |
- } |
- { |
- ClassElement classC = library.getType('C'); |
- expect(classC.supertype.displayName, 'A'); |
- } |
- } |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- test_perform_external() { |
- Source sourceA = newSource( |
- '/a.dart', |
- ''' |
-library a; |
-import 'b.dart'; |
-class A extends B {} |
-'''); |
- newSource( |
- '/b.dart', |
- ''' |
-library b; |
-class B {} |
-'''); |
- // The reference A to B should be resolved, but there's no requirement that |
- // the full class hierarchy be resolved. |
- computeResult(sourceA, LIBRARY_ELEMENT5, |
- matcher: isResolveLibraryTypeNamesTask); |
- // validate |
- LibraryElement library = outputs[LIBRARY_ELEMENT5]; |
- { |
- ClassElement clazz = library.getType('A'); |
- expect(clazz.displayName, 'A'); |
- clazz = clazz.supertype.element; |
- expect(clazz.displayName, 'B'); |
- } |
- } |
-} |
+ InterfaceType intType = context.typeProvider.intType; |
+ InterfaceType stringType = context.typeProvider.stringType; |
-@reflectiveTest |
-class ResolveUnitTypeNamesTaskTest extends _AbstractDartTaskTest { |
- test_perform() { |
- Source source = newSource( |
- '/test.dart', |
- ''' |
-class A {} |
-class B extends A {} |
-int f(String p) => p.length; |
-'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, RESOLVED_UNIT3, matcher: isResolveUnitTypeNamesTask); |
- // validate |
- CompilationUnit unit = outputs[RESOLVED_UNIT3]; |
- { |
- ClassDeclaration nodeA = unit.declarations[0]; |
- ClassDeclaration nodeB = unit.declarations[1]; |
- DartType extendsType = nodeB.extendsClause.superclass.type; |
- expect(extendsType, nodeA.element.type); |
- } |
- { |
- FunctionDeclaration functionNode = unit.declarations[2]; |
- DartType returnType = functionNode.returnType.type; |
- List<FormalParameter> parameters = |
- functionNode.functionExpression.parameters.parameters; |
- expect(returnType.displayName, 'int'); |
- expect(parameters[0].element.type.displayName, 'String'); |
- } |
- } |
+ List<Statement> statements = getStatementsInTopLevelFunction(unit, "test"); |
- test_perform_errors() { |
- Source source = newSource( |
- '/test.dart', |
- ''' |
-NoSuchClass f() => null; |
-'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, RESOLVE_TYPE_NAMES_ERRORS, |
- matcher: isResolveUnitTypeNamesTask); |
- // validate |
- _fillErrorListener(RESOLVE_TYPE_NAMES_ERRORS); |
- errorListener |
- .assertErrorsWithCodes(<ErrorCode>[StaticWarningCode.UNDEFINED_CLASS]); |
+ assertVariableDeclarationStatementTypes(statements[0], intType, intType); |
+ assertAssignmentStatementTypes(statements[1], intType, stringType); |
+ assertVariableDeclarationStatementTypes(statements[2], intType, intType); |
+ assertAssignmentStatementTypes(statements[3], intType, stringType); |
} |
- test_perform_typedef() { |
- Source source = newSource( |
+ // Test inference across units (non-cyclic) |
+ void test_perform_inference_local_variables_fields() { |
+ AnalysisTarget source = newSource( |
'/test.dart', |
''' |
-typedef int F(G g); |
-typedef String G(int p); |
+ class A { |
+ int x = 0; |
+ |
+ test1() { |
+ var a = x; |
+ a = "hi"; |
+ a = 3; |
+ var b = y; |
+ b = "hi"; |
+ b = 4; |
+ var c = z; |
+ c = "hi"; |
+ c = 4; |
+ } |
+ |
+ int y; // field def after use |
+ final z = 42; // should infer `int` |
+ } |
'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, RESOLVED_UNIT3, matcher: isResolveUnitTypeNamesTask); |
- // validate |
- CompilationUnit unit = outputs[RESOLVED_UNIT3]; |
- FunctionTypeAlias nodeF = unit.declarations[0]; |
- FunctionTypeAlias nodeG = unit.declarations[1]; |
- { |
- FormalParameter parameter = nodeF.parameters.parameters[0]; |
- DartType parameterType = parameter.element.type; |
- Element returnTypeElement = nodeF.returnType.type.element; |
- expect(returnTypeElement.displayName, 'int'); |
- expect(parameterType.element, nodeG.element); |
- } |
- { |
- FormalParameter parameter = nodeG.parameters.parameters[0]; |
- DartType parameterType = parameter.element.type; |
- expect(nodeG.returnType.type.element.displayName, 'String'); |
- expect(parameterType.element.displayName, 'int'); |
- } |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
+ |
+ InterfaceType intType = context.typeProvider.intType; |
+ InterfaceType stringType = context.typeProvider.stringType; |
+ |
+ List<Statement> statements = getStatementsInMethod(unit, "A", "test1"); |
+ |
+ assertVariableDeclarationStatementTypes(statements[0], intType, intType); |
+ assertAssignmentStatementTypes(statements[1], intType, stringType); |
+ assertAssignmentStatementTypes(statements[2], intType, intType); |
+ |
+ assertVariableDeclarationStatementTypes(statements[3], intType, intType); |
+ assertAssignmentStatementTypes(statements[4], intType, stringType); |
+ assertAssignmentStatementTypes(statements[5], intType, intType); |
+ |
+ assertVariableDeclarationStatementTypes(statements[6], intType, intType); |
+ assertAssignmentStatementTypes(statements[7], intType, stringType); |
+ assertAssignmentStatementTypes(statements[8], intType, intType); |
+ |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit, "A", "x"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit, "A", "z"), intType, intType); |
} |
- test_perform_typedef_errors() { |
- Source source = newSource( |
+ // Test inference across units (cyclic) |
+ void test_perform_inference_local_variables_topLevel() { |
+ AnalysisTarget source = newSource( |
'/test.dart', |
''' |
-typedef int F(NoSuchType p); |
+ int x = 0; |
+ |
+ test1() { |
+ var a = x; |
+ a = /*severe:StaticTypeError*/"hi"; |
+ a = 3; |
+ var b = y; |
+ b = /*severe:StaticTypeError*/"hi"; |
+ b = 4; |
+ var c = z; |
+ c = /*severe:StaticTypeError*/"hi"; |
+ c = 4; |
+ } |
+ |
+ int y = 0; // field def after use |
+ final z = 42; // should infer `int` |
'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, RESOLVE_TYPE_NAMES_ERRORS, |
- matcher: isResolveUnitTypeNamesTask); |
- // validate |
- _fillErrorListener(RESOLVE_TYPE_NAMES_ERRORS); |
- errorListener |
- .assertErrorsWithCodes(<ErrorCode>[StaticWarningCode.UNDEFINED_CLASS]); |
- } |
-} |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
-@reflectiveTest |
-class ResolveVariableReferencesTaskTest extends _AbstractDartTaskTest { |
- /** |
- * Verify that the mutated states of the given [variable] correspond to the |
- * [mutatedInClosure] and [mutatedInScope] matchers. |
- */ |
- void expectMutated(VariableElement variable, Matcher mutatedInClosure, |
- Matcher mutatedInScope) { |
- expect(variable.isPotentiallyMutatedInClosure, mutatedInClosure); |
- expect(variable.isPotentiallyMutatedInScope, mutatedInScope); |
- } |
+ InterfaceType intType = context.typeProvider.intType; |
+ InterfaceType stringType = context.typeProvider.stringType; |
+ |
+ List<Statement> statements = getStatementsInTopLevelFunction(unit, "test1"); |
+ |
+ assertVariableDeclarationStatementTypes(statements[0], intType, intType); |
+ assertAssignmentStatementTypes(statements[1], intType, stringType); |
+ assertAssignmentStatementTypes(statements[2], intType, intType); |
+ |
+ assertVariableDeclarationStatementTypes(statements[3], intType, intType); |
+ assertAssignmentStatementTypes(statements[4], intType, stringType); |
+ assertAssignmentStatementTypes(statements[5], intType, intType); |
- test_perform_buildClosureLibraryElements() { |
- Source source = newSource( |
- '/test.dart', |
- ''' |
-main() { |
-} |
-'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, RESOLVED_UNIT4, |
- matcher: isResolveVariableReferencesTask); |
+ assertVariableDeclarationStatementTypes(statements[6], intType, intType); |
+ assertAssignmentStatementTypes(statements[7], intType, stringType); |
+ assertAssignmentStatementTypes(statements[8], intType, intType); |
+ |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit, "x"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit, "y"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit, "z"), intType, intType); |
} |
- test_perform_local() { |
- Source source = newSource( |
+ // Test inference of instance fields across units |
+ // TODO(leafp): Fix this |
+ // https://github.com/dart-lang/dev_compiler/issues/354 |
+ void test_perform_inference_null() { |
+ AnalysisTarget source = newSource( |
'/test.dart', |
''' |
-main() { |
- var v1 = 1; |
- var v2 = 1; |
- var v3 = 1; |
- var v4 = 1; |
- v2 = 2; |
- v4 = 2; |
- localFunction() { |
- v3 = 3; |
- v4 = 3; |
- } |
-} |
+ var x = null; |
+ var y = 3; |
+ class A { |
+ static var x = null; |
+ static var y = 3; |
+ |
+ var x2 = null; |
+ var y2 = 3; |
+ } |
+ |
+ test() { |
+ x = "hi"; |
+ y = /*severe:StaticTypeError*/"hi"; |
+ A.x = "hi"; |
+ A.y = /*severe:StaticTypeError*/"hi"; |
+ new A().x2 = "hi"; |
+ new A().y2 = /*severe:StaticTypeError*/"hi"; |
+ } |
'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, RESOLVED_UNIT4, |
- matcher: isResolveVariableReferencesTask); |
- // validate |
- CompilationUnit unit = outputs[RESOLVED_UNIT4]; |
- FunctionElement main = unit.element.functions[0]; |
- expectMutated(main.localVariables[0], isFalse, isFalse); |
- expectMutated(main.localVariables[1], isFalse, isTrue); |
- expectMutated(main.localVariables[2], isTrue, isTrue); |
- expectMutated(main.localVariables[3], isTrue, isTrue); |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
+ |
+ InterfaceType intType = context.typeProvider.intType; |
+ InterfaceType stringType = context.typeProvider.stringType; |
+ DartType bottomType = context.typeProvider.bottomType; |
+ DartType dynamicType = context.typeProvider.dynamicType; |
+ |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit, "x"), dynamicType, bottomType); |
+ assertVariableDeclarationTypes( |
+ getTopLevelVariable(unit, "y"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit, "A", "x"), dynamicType, bottomType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit, "A", "y"), intType, intType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit, "A", "x2"), dynamicType, bottomType); |
+ assertVariableDeclarationTypes( |
+ getFieldInClass(unit, "A", "y2"), intType, intType); |
+ |
+ List<Statement> statements = getStatementsInTopLevelFunction(unit, "test"); |
+ |
+ assertAssignmentStatementTypes(statements[0], dynamicType, stringType); |
+ assertAssignmentStatementTypes(statements[1], intType, stringType); |
+ assertAssignmentStatementTypes(statements[2], dynamicType, stringType); |
+ assertAssignmentStatementTypes(statements[3], intType, stringType); |
+ assertAssignmentStatementTypes(statements[4], dynamicType, stringType); |
+ assertAssignmentStatementTypes(statements[5], intType, stringType); |
} |
- test_perform_parameter() { |
- Source source = newSource( |
+ // Test inference between static and instance fields |
+ // TODO(leafp): Fix this |
+ // https://github.com/dart-lang/dev_compiler/issues/354 |
+ void test_perform_local_explicit_disabled() { |
+ AnalysisTarget source = newSource( |
'/test.dart', |
''' |
-main(p1, p2, p3, p4) { |
- p2 = 2; |
- p4 = 2; |
- localFunction() { |
- p3 = 3; |
- p4 = 3; |
- } |
-} |
+ test() { |
+ int x = 3; |
+ x = "hi"; |
+ } |
'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, RESOLVED_UNIT4, |
- matcher: isResolveVariableReferencesTask); |
- // validate |
- CompilationUnit unit = outputs[RESOLVED_UNIT4]; |
- FunctionElement main = unit.element.functions[0]; |
- expectMutated(main.parameters[0], isFalse, isFalse); |
- expectMutated(main.parameters[1], isFalse, isTrue); |
- expectMutated(main.parameters[2], isTrue, isTrue); |
- expectMutated(main.parameters[3], isTrue, isTrue); |
- } |
-} |
- |
-@reflectiveTest |
-class ScanDartTaskTest extends _AbstractDartTaskTest { |
- test_perform_errors() { |
- _performScanTask('import "'); |
- expect(outputs, hasLength(3)); |
- expect(outputs[LINE_INFO], isNotNull); |
- expect(outputs[SCAN_ERRORS], hasLength(1)); |
- expect(outputs[TOKEN_STREAM], isNotNull); |
- } |
- |
- test_perform_noErrors() { |
- _performScanTask('class A {}'); |
- expect(outputs, hasLength(3)); |
- expect(outputs[LINE_INFO], isNotNull); |
- expect(outputs[SCAN_ERRORS], hasLength(0)); |
- expect(outputs[TOKEN_STREAM], isNotNull); |
- } |
+ computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); |
+ CompilationUnit unit = outputs[RESOLVED_UNIT8]; |
- test_perform_script() { |
- String scriptContent = ''' |
- void buttonPressed() { |
- '''; |
- String htmlContent = ''' |
-<!DOCTYPE html> |
-<html> |
- <head> |
- <title>test page</title> |
- <script type='application/dart'>$scriptContent</script> |
- </head> |
- <body>Test</body> |
-</html> |
-'''; |
- Source source = newSource('/test.html', htmlContent); |
- DartScript script = |
- new DartScript(source, [new ScriptFragment(97, 5, 36, scriptContent)]); |
+ InterfaceType intType = context.typeProvider.intType; |
+ InterfaceType stringType = context.typeProvider.stringType; |
- computeResult(script, TOKEN_STREAM, matcher: isScanDartTask); |
- expect(outputs[LINE_INFO], isNotNull); |
- expect(outputs[SCAN_ERRORS], isEmpty); |
- Token tokenStream = outputs[TOKEN_STREAM]; |
- expect(tokenStream, isNotNull); |
- expect(tokenStream.lexeme, 'void'); |
- } |
+ List<Statement> statements = getStatementsInTopLevelFunction(unit, "test"); |
+ VariableDeclaration decl = |
+ (statements[0] as VariableDeclarationStatement).variables.variables[0]; |
+ expect(decl.element.type, intType); |
+ expect(decl.initializer.staticType, intType); |
- void _performScanTask(String content) { |
- AnalysisTarget target = newSource('/test.dart', content); |
- computeResult(target, TOKEN_STREAM, matcher: isScanDartTask); |
+ ExpressionStatement statement = statements[1]; |
+ AssignmentExpression assgn = statement.expression; |
+ expect(assgn.leftHandSide.staticType, intType); |
+ expect(assgn.rightHandSide.staticType, stringType); |
} |
} |
@@ -3368,39 +3428,39 @@ import 'no-such-file.dart'; |
<ErrorCode>[CompileTimeErrorCode.URI_DOES_NOT_EXIST]); |
} |
- test_perform_verifyError() { |
- Source source = newSource( |
+ void test_perform_reresolution() { |
+ enableStrongMode(); |
+ AnalysisTarget source = newSource( |
'/test.dart', |
''' |
-main() { |
- if (42) { |
- print('Not bool!'); |
- } |
+const topLevel = 3; |
+class C { |
+ String field = topLevel; |
} |
'''); |
- LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
- computeResult(target, VERIFY_ERRORS, matcher: isVerifyUnitTask); |
+ computeResult(new LibrarySpecificUnit(source, source), VERIFY_ERRORS); |
// validate |
_fillErrorListener(VERIFY_ERRORS); |
errorListener.assertErrorsWithCodes( |
- <ErrorCode>[StaticTypeWarningCode.NON_BOOL_CONDITION]); |
+ <ErrorCode>[StaticTypeWarningCode.INVALID_ASSIGNMENT]); |
} |
- void test_perform_reresolution() { |
- enableStrongMode(); |
- AnalysisTarget source = newSource( |
+ test_perform_verifyError() { |
+ Source source = newSource( |
'/test.dart', |
''' |
-const topLevel = 3; |
-class C { |
- String field = topLevel; |
+main() { |
+ if (42) { |
+ print('Not bool!'); |
+ } |
} |
'''); |
- computeResult(new LibrarySpecificUnit(source, source), VERIFY_ERRORS); |
+ LibrarySpecificUnit target = new LibrarySpecificUnit(source, source); |
+ computeResult(target, VERIFY_ERRORS, matcher: isVerifyUnitTask); |
// validate |
_fillErrorListener(VERIFY_ERRORS); |
errorListener.assertErrorsWithCodes( |
- <ErrorCode>[StaticTypeWarningCode.INVALID_ASSIGNMENT]); |
+ <ErrorCode>[StaticTypeWarningCode.NON_BOOL_CONDITION]); |
} |
} |
@@ -3538,6 +3598,23 @@ class _AbstractDartTaskTest extends AbstractContextTest { |
} |
/** |
+ * Return the declaration of the top-level function with the given |
+ * [functionName] in the given compilation [unit]. |
+ */ |
+ FunctionDeclaration getTopLevelFunction( |
+ CompilationUnit unit, String functionName) { |
+ NodeList<CompilationUnitMember> unitMembers = unit.declarations; |
+ for (CompilationUnitMember unitMember in unitMembers) { |
+ if (unitMember is FunctionDeclaration) { |
+ if (unitMember.name.name == functionName) { |
+ return unitMember; |
+ } |
+ } |
+ } |
+ return null; |
+ } |
+ |
+ /** |
* Return the declaration of the top-level variable with the given |
* [variableName] in the given compilation [unit]. |
*/ |
@@ -3558,23 +3635,6 @@ class _AbstractDartTaskTest extends AbstractContextTest { |
return null; |
} |
- /** |
- * Return the declaration of the top-level function with the given |
- * [functionName] in the given compilation [unit]. |
- */ |
- FunctionDeclaration getTopLevelFunction( |
- CompilationUnit unit, String functionName) { |
- NodeList<CompilationUnitMember> unitMembers = unit.declarations; |
- for (CompilationUnitMember unitMember in unitMembers) { |
- if (unitMember is FunctionDeclaration) { |
- if (unitMember.name.name == functionName) { |
- return unitMember; |
- } |
- } |
- } |
- return null; |
- } |
- |
void setUp() { |
super.setUp(); |
emptySource = newSource('/test.dart'); |