Chromium Code Reviews| 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..dcca81544125292cc709680b868038e34c3a175f 100644 | 
| --- a/pkg/analyzer/test/src/task/dart_test.dart | 
| +++ b/pkg/analyzer/test/src/task/dart_test.dart | 
| @@ -55,8 +55,9 @@ main() { | 
| runReflectiveTests(LibraryUnitErrorsTaskTest); | 
| runReflectiveTests(ParseDartTaskTest); | 
| runReflectiveTests(PartiallyResolveUnitReferencesTaskTest); | 
| - runReflectiveTests(ResolveFunctionBodiesInUnitTaskTest); | 
| runReflectiveTests(ResolveLibraryTypeNamesTaskTest); | 
| + runReflectiveTests(ResolveLibraryTypeNamesTaskTest); | 
| 
 
Brian Wilkerson
2015/10/06 19:04:47
Duplicated line. (Probably copied and pasted in pr
 
Leaf
2015/10/07 18:53:55
Done.
 
 | 
| + runReflectiveTests(ResolveUnitTaskTest); | 
| runReflectiveTests(ResolveUnitTypeNamesTaskTest); | 
| runReflectiveTests(ResolveVariableReferencesTaskTest); | 
| runReflectiveTests(ScanDartTaskTest); | 
| @@ -111,10 +112,9 @@ isInstanceOf isLibraryUnitErrorsTask = | 
| isInstanceOf isParseDartTask = new isInstanceOf<ParseDartTask>(); | 
| isInstanceOf isPartiallyResolveUnitReferencesTask = | 
| new isInstanceOf<PartiallyResolveUnitReferencesTask>(); | 
| -isInstanceOf isResolveFunctionBodiesInUnitTask = | 
| - new isInstanceOf<ResolveFunctionBodiesInUnitTask>(); | 
| isInstanceOf isResolveLibraryTypeNamesTask = | 
| new isInstanceOf<ResolveLibraryTypeNamesTask>(); | 
| +isInstanceOf isResolveUnitTask = new isInstanceOf<ResolveUnitTask>(); | 
| isInstanceOf isResolveUnitTypeNamesTask = | 
| new isInstanceOf<ResolveUnitTypeNamesTask>(); | 
| isInstanceOf isResolveVariableReferencesTask = | 
| @@ -1894,9 +1894,9 @@ class X {} | 
| class Y {} | 
| class Z {} | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7, | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8, | 
| matcher: isInferInstanceMembersInUnitTask); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT7]; | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| VariableDeclaration field = getFieldInClass(unit, 'B', 'f'); | 
| MethodDeclaration method = getMethodInClass(unit, 'B', 'm'); | 
| DartType typeX = getClass(unit, 'X').element.type; | 
| @@ -1928,12 +1928,12 @@ class M { | 
| } | 
| '''); | 
| computeResult( | 
| - new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT7, | 
| + new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8, | 
| matcher: isInferInstanceMembersInUnitTask); | 
| - CompilationUnit firstUnit = outputs[RESOLVED_UNIT7]; | 
| + CompilationUnit firstUnit = outputs[RESOLVED_UNIT8]; | 
| computeResult( | 
| - new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT7); | 
| - CompilationUnit secondUnit = outputs[RESOLVED_UNIT7]; | 
| + new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8); | 
| + CompilationUnit secondUnit = outputs[RESOLVED_UNIT8]; | 
| VariableDeclaration variableA = getTopLevelVariable(firstUnit, 'a'); | 
| VariableDeclaration variableB = getTopLevelVariable(secondUnit, 'b'); | 
| @@ -1957,8 +1957,8 @@ class C { | 
| String field = topLevel; | 
| } | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT7); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT7]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| VariableDeclaration topLevelDecl = getTopLevelVariable(unit, 'topLevel'); | 
| VariableDeclaration fieldDecl = getFieldInClass(unit, 'C', 'field'); | 
| VariableElement topLevel = topLevelDecl.name.staticElement; | 
| @@ -2125,32 +2125,6 @@ class C { | 
| expect(topLevel.type, stringType); | 
| expect(field.type, stringType); | 
| expect(fieldDecl.initializer.staticType, stringType); | 
| - expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); | 
| - } | 
| - | 
| - void test_perform_reresolution() { | 
| 
 
Brian Wilkerson
2015/10/06 19:04:47
Out of curiosity, why was this test removed?
 
Leaf
2015/10/06 20:30:55
The thing it's testing for (re-resolution of field
 
 | 
| - 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() { | 
| @@ -2174,7 +2148,6 @@ class C { | 
| InterfaceType stringType = context.typeProvider.stringType; | 
| expect(topLevel.type, stringType); | 
| expect(field.type, stringType); | 
| - expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); | 
| } | 
| void test_perform_cycle() { | 
| @@ -2197,7 +2170,6 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| expect(piFirst.type, context.typeProvider.boolType); | 
| expect(pi.type.isDynamic, isTrue); | 
| expect(tau.type.isDynamic, isTrue); | 
| - expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); | 
| } | 
| void test_perform_error() { | 
| @@ -2213,7 +2185,6 @@ var a = '' / null; | 
| computeResult(a, INFERRED_STATIC_VARIABLE, | 
| matcher: isInferStaticVariableTypeTask); | 
| expect(a.type.isDynamic, isTrue); | 
| - expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(1)); | 
| } | 
| void test_perform_null() { | 
| @@ -2229,7 +2200,6 @@ var a = null; | 
| computeResult(a, INFERRED_STATIC_VARIABLE, | 
| matcher: isInferStaticVariableTypeTask); | 
| expect(a.type.isDynamic, isTrue); | 
| - expect(outputs[INFER_STATIC_VARIABLE_ERRORS], hasLength(0)); | 
| } | 
| } | 
| @@ -2437,7 +2407,7 @@ class C { | 
| computeResult(target, RESOLVED_UNIT5, | 
| matcher: isPartiallyResolveUnitReferencesTask); | 
| // Test the outputs | 
| - expect(outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT], hasLength(5)); | 
| + expect(outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT], hasLength(4)); | 
| CompilationUnit unit = outputs[RESOLVED_UNIT5]; | 
| expect(unit, same(outputs[RESOLVED_UNIT5])); | 
| // Test the state of the AST | 
| @@ -2445,9 +2415,6 @@ class C { | 
| VariableDeclaration variableA = a.variables.variables[0]; | 
| SimpleIdentifier initializer = variableA.initializer; | 
| expect(initializer.staticElement, isNotNull); | 
| - // Test the error generation | 
| - _fillErrorListener(PARTIALLY_RESOLVE_REFERENCES_ERRORS); | 
| - errorListener.assertNoErrors(); | 
| } | 
| test_perform_importExport() { | 
| @@ -2558,7 +2525,7 @@ class C { | 
| } | 
| @reflectiveTest | 
| -class ResolveFunctionBodiesInUnitTaskTest extends _AbstractDartTaskTest { | 
| +class ResolveUnitTaskTest extends _AbstractDartTaskTest { | 
| void test_perform() { | 
| AnalysisTarget source = newSource( | 
| '/test.dart', | 
| @@ -2573,9 +2540,9 @@ class C { | 
| } | 
| } | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8, | 
| - matcher: isResolveFunctionBodiesInUnitTask); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9, | 
| + matcher: isResolveUnitTask); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT9]; | 
| FunctionDeclaration f = unit.declarations[0]; | 
| _assertResolved(f.functionExpression.body); | 
| @@ -2583,7 +2550,7 @@ class C { | 
| MethodDeclaration m = (unit.declarations[1] as ClassDeclaration).members[0]; | 
| _assertResolved(m.body); | 
| - expect(outputs[RESOLVE_FUNCTION_BODIES_ERRORS], hasLength(0)); | 
| + expect(outputs[RESOLVE_UNIT_ERRORS], hasLength(0)); | 
| } | 
| void _assertResolved(FunctionBody body) { | 
| @@ -2595,13 +2562,176 @@ class C { | 
| @reflectiveTest | 
| class StrongModeInferenceTest extends _AbstractDartTaskTest { | 
| - | 
| @override | 
| void setUp() { | 
| super.setUp(); | 
| enableStrongMode(); | 
| } | 
| + void test_library_cycle_singleton() { | 
| 
 
Brian Wilkerson
2015/10/06 19:04:47
These tests look like they're testing the results
 
Leaf
2015/10/07 18:53:55
Done.
 
 | 
| + Source source = newSource( | 
| + '/test.dart', | 
| + ''' | 
| +import 'dart:core'; | 
| +'''); | 
| + computeResult(new LibrarySpecificUnit(source, source), LIBRARY_CYCLE); | 
| + List<LibraryElement> component = outputs[LIBRARY_CYCLE]; | 
| + List<CompilationUnitElement> units = outputs[LIBRARY_CYCLE_UNITS]; | 
| + expect(component, hasLength(1)); | 
| + expect(units, hasLength(1)); | 
| + | 
| + computeResult( | 
| + new LibrarySpecificUnit(source, source), LIBRARY_CYCLE_DEPENDENCIES); | 
| + List<CompilationUnitElement> deps = outputs[LIBRARY_CYCLE_DEPENDENCIES]; | 
| + expect(deps, hasLength(1)); | 
| + } | 
| + | 
| + void test_library_cycle_linear() { | 
| + List<Source> sources = newSources({ | 
| + '/a.dart': ''' | 
| +''', | 
| + '/b.dart': ''' | 
| +import 'a.dart'; | 
| + ''' | 
| + }); | 
| + List<List<LibraryElement>> components = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE).toList(); | 
| + List<LibraryElement> component0 = components[0]; | 
| + List<LibraryElement> component1 = components[1]; | 
| + expect(component0, hasLength(1)); | 
| + expect(component1, hasLength(1)); | 
| + | 
| + List<List<CompilationUnitElement>> deps = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE_DEPENDENCIES).toList(); | 
| + List<CompilationUnitElement> dep0 = deps[0]; | 
| + List<CompilationUnitElement> dep1 = deps[1]; | 
| + expect(dep0, hasLength(1)); // dart:core | 
| + expect(dep1, hasLength(2)); // dart:core, a.dart | 
| + } | 
| + | 
| + void test_library_cycle_tree() { | 
| + List<Source> sources = newSources({ | 
| + '/a.dart': ''' | 
| +''', | 
| + '/b.dart': ''' | 
| + ''', | 
| + '/c.dart': ''' | 
| + import 'a.dart'; | 
| + import 'b.dart'; | 
| + ''' | 
| + }); | 
| + List<List<LibraryElement>> components = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE).toList(); | 
| + List<LibraryElement> component0 = components[0]; | 
| + List<LibraryElement> component1 = components[1]; | 
| + List<LibraryElement> component2 = components[2]; | 
| + expect(component0, hasLength(1)); | 
| + expect(component1, hasLength(1)); | 
| + expect(component2, hasLength(1)); | 
| + | 
| + List<List<CompilationUnitElement>> deps = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE_DEPENDENCIES).toList(); | 
| + List<CompilationUnitElement> dep0 = deps[0]; | 
| + List<CompilationUnitElement> dep1 = deps[1]; | 
| + List<CompilationUnitElement> dep2 = deps[2]; | 
| + expect(dep0, hasLength(1)); // dart:core | 
| + expect(dep1, hasLength(1)); // dart:core, | 
| + expect(dep2, hasLength(3)); // dart:core, a.dart, b.dart | 
| + } | 
| + | 
| + void test_library_cycle_loop() { | 
| + List<Source> sources = newSources({ | 
| + '/a.dart': ''' | 
| + import 'c.dart'; | 
| +''', | 
| + '/b.dart': ''' | 
| + import 'a.dart'; | 
| + ''', | 
| + '/c.dart': ''' | 
| + import 'b.dart'; | 
| + ''' | 
| + }); | 
| + List<List<LibraryElement>> components = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE).toList(); | 
| + List<LibraryElement> component0 = components[0]; | 
| + List<LibraryElement> component1 = components[1]; | 
| + List<LibraryElement> component2 = components[2]; | 
| + | 
| + expect(component0, hasLength(3)); | 
| + expect(component1, hasLength(3)); | 
| + expect(component2, hasLength(3)); | 
| + | 
| + List<List<CompilationUnitElement>> deps = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE_DEPENDENCIES).toList(); | 
| + List<CompilationUnitElement> dep0 = deps[0]; | 
| + List<CompilationUnitElement> dep1 = deps[1]; | 
| + List<CompilationUnitElement> dep2 = deps[2]; | 
| + expect(dep0, hasLength(1)); // dart:core | 
| + expect(dep1, hasLength(1)); // dart:core | 
| + expect(dep2, hasLength(1)); // dart:core | 
| + } | 
| + | 
| + void test_library_cycle_self_loop() { | 
| + List<Source> sources = newSources({ | 
| + '/a.dart': ''' | 
| + import 'a.dart'; | 
| +''' | 
| + }); | 
| + List<List<LibraryElement>> components = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE).toList(); | 
| + List<LibraryElement> component0 = components[0]; | 
| + | 
| + expect(component0, hasLength(1)); | 
| + | 
| + List<List<CompilationUnitElement>> deps = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE_DEPENDENCIES).toList(); | 
| + List<CompilationUnitElement> dep0 = deps[0]; | 
| + expect(dep0, hasLength(1)); // dart:core | 
| + } | 
| + | 
| + void test_library_double_loop() { | 
| + List<Source> sources = newSources({ | 
| + '/a.dart': ''' | 
| + import 'b.dart'; | 
| +''', | 
| + '/b.dart': ''' | 
| + import 'a.dart'; | 
| + ''', | 
| + '/c.dart': ''' | 
| + import 'd.dart' as foo; | 
| + import 'a.dart' as bar; | 
| + export 'b.dart'; | 
| + ''', | 
| + '/d.dart': ''' | 
| + import 'c.dart' as foo; | 
| + import 'b.dart' as bar; | 
| + export 'a.dart'; | 
| + ''' | 
| + }); | 
| + List<List<LibraryElement>> components = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE).toList(); | 
| + List<LibraryElement> component0 = components[0]; | 
| + List<LibraryElement> component1 = components[1]; | 
| + List<LibraryElement> component2 = components[2]; | 
| + List<LibraryElement> component3 = components[3]; | 
| + | 
| + expect(component0, hasLength(2)); | 
| + expect(component1, hasLength(2)); | 
| + expect(component2, hasLength(2)); | 
| + expect(component3, hasLength(2)); | 
| + | 
| + List<List<CompilationUnitElement>> deps = | 
| + computeLibraryResults(sources, LIBRARY_CYCLE_DEPENDENCIES).toList(); | 
| + List<CompilationUnitElement> dep0 = deps[0]; | 
| + List<CompilationUnitElement> dep1 = deps[1]; | 
| + List<CompilationUnitElement> dep2 = deps[2]; | 
| + List<CompilationUnitElement> dep3 = deps[3]; | 
| + expect(dep0, hasLength(1)); // dart:core | 
| + expect(dep1, hasLength(1)); // dart:core | 
| + expect(dep3, hasLength(3)); // dart:core, a.dart, b.dart | 
| + expect(dep3, hasLength(3)); // dart:core, a.dart, b.dart | 
| + } | 
| + | 
| // Check that even within a static variable cycle, inferred | 
| // types get propagated to the members of the cycle. | 
| void test_perform_cycle() { | 
| @@ -2612,8 +2742,8 @@ 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]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT9]; | 
| VariableElement piFirst = | 
| getTopLevelVariable(unit, 'piFirst').name.staticElement; | 
| VariableElement pi = getTopLevelVariable(unit, 'pi').name.staticElement; | 
| @@ -2636,8 +2766,8 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| x = "hi"; | 
| } | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT9]; | 
| InterfaceType intType = context.typeProvider.intType; | 
| InterfaceType stringType = context.typeProvider.stringType; | 
| @@ -2686,8 +2816,8 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| y = "hi"; | 
| } | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT9]; | 
| InterfaceType intType = context.typeProvider.intType; | 
| InterfaceType stringType = context.typeProvider.stringType; | 
| @@ -2724,8 +2854,8 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| final z = 42; // should infer `int` | 
| } | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT9]; | 
| InterfaceType intType = context.typeProvider.intType; | 
| InterfaceType stringType = context.typeProvider.stringType; | 
| @@ -2773,8 +2903,8 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| int y = 0; // field def after use | 
| final z = 42; // should infer `int` | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT9]; | 
| InterfaceType intType = context.typeProvider.intType; | 
| InterfaceType stringType = context.typeProvider.stringType; | 
| @@ -2825,8 +2955,8 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| new A().y2 = /*severe:StaticTypeError*/"hi"; | 
| } | 
| '''); | 
| - computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8); | 
| - CompilationUnit unit = outputs[RESOLVED_UNIT8]; | 
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9); | 
| + CompilationUnit unit = outputs[RESOLVED_UNIT9]; | 
| InterfaceType intType = context.typeProvider.intType; | 
| InterfaceType stringType = context.typeProvider.stringType; | 
| @@ -2879,11 +3009,11 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| } | 
| '''); | 
| computeResult( | 
| - new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8); | 
| - CompilationUnit unit1 = outputs[RESOLVED_UNIT8]; | 
| + new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT9); | 
| + CompilationUnit unit1 = outputs[RESOLVED_UNIT9]; | 
| computeResult( | 
| - new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8); | 
| - CompilationUnit unit2 = outputs[RESOLVED_UNIT8]; | 
| + new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT9); | 
| + CompilationUnit unit2 = outputs[RESOLVED_UNIT9]; | 
| InterfaceType intType = context.typeProvider.intType; | 
| InterfaceType stringType = context.typeProvider.stringType; | 
| @@ -2930,11 +3060,11 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| } | 
| '''); | 
| computeResult( | 
| - new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8); | 
| - CompilationUnit unit1 = outputs[RESOLVED_UNIT8]; | 
| + new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT9); | 
| + CompilationUnit unit1 = outputs[RESOLVED_UNIT9]; | 
| computeResult( | 
| - new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8); | 
| - CompilationUnit unit2 = outputs[RESOLVED_UNIT8]; | 
| + new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT9); | 
| + CompilationUnit unit2 = outputs[RESOLVED_UNIT9]; | 
| InterfaceType intType = context.typeProvider.intType; | 
| @@ -2958,9 +3088,7 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| } | 
| // 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() { | 
| + void test_perform_inference_cross_unit_instance() { | 
| List<Source> sources = newSources({ | 
| '/a7.dart': ''' | 
| import 'b7.dart'; | 
| @@ -2983,7 +3111,7 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| ''' | 
| }); | 
| List<dynamic> units = | 
| - computeLibraryResults(sources, RESOLVED_UNIT8).toList(); | 
| + computeLibraryResults(sources, RESOLVED_UNIT9).toList(); | 
| CompilationUnit unit0 = units[0]; | 
| CompilationUnit unit1 = units[1]; | 
| CompilationUnit unit2 = units[2]; | 
| @@ -3003,9 +3131,7 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| } | 
| // 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() { | 
| + void test_perform_inference_cross_unit_static_instance() { | 
| List<Source> sources = newSources({ | 
| '/a.dart': ''' | 
| import 'b.dart'; | 
| @@ -3032,7 +3158,7 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| ''' | 
| }); | 
| List<dynamic> units = | 
| - computeLibraryResults(sources, RESOLVED_UNIT8).toList(); | 
| + computeLibraryResults(sources, RESOLVED_UNIT9).toList(); | 
| CompilationUnit unit0 = units[0]; | 
| CompilationUnit unit1 = units[1]; | 
| CompilationUnit unit2 = units[2]; | 
| @@ -3055,6 +3181,48 @@ var tau = piFirst ? pi * 2 : 6.28; | 
| assertAssignmentStatementTypes(statements[1], intType, intType); | 
| assertAssignmentStatementTypes(statements[2], intType, intType); | 
| } | 
| + | 
| + // Test inference between fields and method bodies | 
| + void test_perform_inference_cross_unit_instance_member() { | 
| + List<Source> sources = newSources({ | 
| + '/a.dart': ''' | 
| + import 'b.dart'; | 
| + var bar = new B(); | 
| + void foo() { | 
| + String x = bar.f.z; | 
| + } | 
| + ''', | 
| + '/b.dart': ''' | 
| + class C { | 
| + var z = 3; | 
| + } | 
| + | 
| + class B { | 
| + var f = new C(); | 
| + } | 
| + ''', | 
| + '/c.dart': ''' | 
| + import 'b.dart'; | 
| + var bar = new B(); | 
| + void foo() { | 
| + String x = bar.f.z; | 
| + } | 
| + ''' | 
| + }); | 
| + List<dynamic> units = | 
| + computeLibraryResults(sources, RESOLVED_UNIT9).toList(); | 
| + CompilationUnit unit0 = units[0]; | 
| + CompilationUnit unit1 = units[1]; | 
| + CompilationUnit unit2 = units[2]; | 
| + | 
| + InterfaceType intType = context.typeProvider.intType; | 
| + InterfaceType stringType = context.typeProvider.stringType; | 
| + | 
| + assertVariableDeclarationStatementTypes( | 
| + getStatementsInTopLevelFunction(unit0, "foo")[0], stringType, intType); | 
| + assertVariableDeclarationStatementTypes( | 
| + getStatementsInTopLevelFunction(unit2, "foo")[0], stringType, intType); | 
| + } | 
| } | 
| @reflectiveTest |