| Index: packages/analyzer/test/src/task/dart_test.dart
|
| diff --git a/packages/analyzer/test/src/task/dart_test.dart b/packages/analyzer/test/src/task/dart_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0f39004e1c77208f0eb03914aef6097e2dd86f1d
|
| --- /dev/null
|
| +++ b/packages/analyzer/test/src/task/dart_test.dart
|
| @@ -0,0 +1,4259 @@
|
| +// Copyright (c) 2015, 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.
|
| +
|
| +library test.src.task.dart_test;
|
| +
|
| +import 'package:analyzer/src/context/cache.dart';
|
| +import 'package:analyzer/src/generated/ast.dart';
|
| +import 'package:analyzer/src/generated/constant.dart';
|
| +import 'package:analyzer/src/generated/element.dart';
|
| +import 'package:analyzer/src/generated/engine.dart'
|
| + show AnalysisOptionsImpl, CacheState;
|
| +import 'package:analyzer/src/generated/error.dart';
|
| +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';
|
| +import 'package:analyzer/task/general.dart';
|
| +import 'package:analyzer/task/model.dart';
|
| +import 'package:unittest/unittest.dart';
|
| +
|
| +import '../../generated/resolver_test.dart';
|
| +import '../../generated/test_support.dart';
|
| +import '../../reflective_tests.dart';
|
| +import '../../utils.dart';
|
| +import '../context/abstract_context.dart';
|
| +
|
| +main() {
|
| + initializeTestEnvironment();
|
| + runReflectiveTests(BuildCompilationUnitElementTaskTest);
|
| + runReflectiveTests(BuildDirectiveElementsTaskTest);
|
| + runReflectiveTests(BuildEnumMemberElementsTaskTest);
|
| + runReflectiveTests(BuildExportNamespaceTaskTest);
|
| + runReflectiveTests(BuildLibraryElementTaskTest);
|
| + runReflectiveTests(BuildPublicNamespaceTaskTest);
|
| + runReflectiveTests(BuildSourceExportClosureTaskTest);
|
| + runReflectiveTests(BuildSourceImportExportClosureTaskTest);
|
| + runReflectiveTests(BuildTypeProviderTaskTest);
|
| + runReflectiveTests(ComputeConstantDependenciesTaskTest);
|
| + runReflectiveTests(ComputeConstantValueTaskTest);
|
| + runReflectiveTests(ComputeInferableStaticVariableDependenciesTaskTest);
|
| + runReflectiveTests(ComputeLibraryCycleTaskTest);
|
| + runReflectiveTests(ContainingLibrariesTaskTest);
|
| + runReflectiveTests(DartErrorsTaskTest);
|
| + runReflectiveTests(EvaluateUnitConstantsTaskTest);
|
| + runReflectiveTests(GatherUsedImportedElementsTaskTest);
|
| + runReflectiveTests(GatherUsedLocalElementsTaskTest);
|
| + runReflectiveTests(GenerateHintsTaskTest);
|
| + runReflectiveTests(GenerateLintsTaskTest);
|
| + runReflectiveTests(InferInstanceMembersInUnitTaskTest);
|
| + runReflectiveTests(InferStaticVariableTypesInUnitTaskTest);
|
| + runReflectiveTests(InferStaticVariableTypeTaskTest);
|
| + runReflectiveTests(LibraryErrorsReadyTaskTest);
|
| + runReflectiveTests(LibraryUnitErrorsTaskTest);
|
| + runReflectiveTests(ParseDartTaskTest);
|
| + runReflectiveTests(PartiallyResolveUnitReferencesTaskTest);
|
| + runReflectiveTests(ResolveInstanceFieldsInUnitTaskTest);
|
| + runReflectiveTests(ResolveLibraryTypeNamesTaskTest);
|
| + runReflectiveTests(ResolveUnitTaskTest);
|
| + runReflectiveTests(ResolveUnitTypeNamesTaskTest);
|
| + runReflectiveTests(ResolveVariableReferencesTaskTest);
|
| + runReflectiveTests(ScanDartTaskTest);
|
| + runReflectiveTests(StrongModeInferenceTest);
|
| + runReflectiveTests(VerifyUnitTaskTest);
|
| +}
|
| +
|
| +isInstanceOf isBuildCompilationUnitElementTask =
|
| + new isInstanceOf<BuildCompilationUnitElementTask>();
|
| +isInstanceOf isBuildDirectiveElementsTask =
|
| + new isInstanceOf<BuildDirectiveElementsTask>();
|
| +isInstanceOf isBuildEnumMemberElementsTask =
|
| + new isInstanceOf<BuildEnumMemberElementsTask>();
|
| +isInstanceOf isBuildExportNamespaceTask =
|
| + new isInstanceOf<BuildExportNamespaceTask>();
|
| +isInstanceOf isBuildLibraryElementTask =
|
| + new isInstanceOf<BuildLibraryElementTask>();
|
| +isInstanceOf isBuildPublicNamespaceTask =
|
| + new isInstanceOf<BuildPublicNamespaceTask>();
|
| +isInstanceOf isBuildSourceExportClosureTask =
|
| + new isInstanceOf<BuildSourceExportClosureTask>();
|
| +isInstanceOf isBuildSourceImportExportClosureTask =
|
| + new isInstanceOf<BuildSourceImportExportClosureTask>();
|
| +isInstanceOf isBuildTypeProviderTask =
|
| + new isInstanceOf<BuildTypeProviderTask>();
|
| +isInstanceOf isComputeConstantDependenciesTask =
|
| + new isInstanceOf<ComputeConstantDependenciesTask>();
|
| +isInstanceOf isComputeConstantValueTask =
|
| + new isInstanceOf<ComputeConstantValueTask>();
|
| +isInstanceOf isComputeInferableStaticVariableDependenciesTask =
|
| + new isInstanceOf<ComputeInferableStaticVariableDependenciesTask>();
|
| +isInstanceOf isContainingLibrariesTask =
|
| + new isInstanceOf<ContainingLibrariesTask>();
|
| +isInstanceOf isDartErrorsTask = new isInstanceOf<DartErrorsTask>();
|
| +isInstanceOf isEvaluateUnitConstantsTask =
|
| + new isInstanceOf<EvaluateUnitConstantsTask>();
|
| +isInstanceOf isGatherUsedImportedElementsTask =
|
| + new isInstanceOf<GatherUsedImportedElementsTask>();
|
| +isInstanceOf isGatherUsedLocalElementsTask =
|
| + new isInstanceOf<GatherUsedLocalElementsTask>();
|
| +isInstanceOf isGenerateHintsTask = new isInstanceOf<GenerateHintsTask>();
|
| +isInstanceOf isGenerateLintsTask = new isInstanceOf<GenerateLintsTask>();
|
| +isInstanceOf isInferInstanceMembersInUnitTask =
|
| + new isInstanceOf<InferInstanceMembersInUnitTask>();
|
| +isInstanceOf isInferStaticVariableTypesInUnitTask =
|
| + new isInstanceOf<InferStaticVariableTypesInUnitTask>();
|
| +isInstanceOf isInferStaticVariableTypeTask =
|
| + new isInstanceOf<InferStaticVariableTypeTask>();
|
| +isInstanceOf isLibraryErrorsReadyTask =
|
| + new isInstanceOf<LibraryErrorsReadyTask>();
|
| +isInstanceOf isLibraryUnitErrorsTask =
|
| + new isInstanceOf<LibraryUnitErrorsTask>();
|
| +isInstanceOf isParseDartTask = new isInstanceOf<ParseDartTask>();
|
| +isInstanceOf isPartiallyResolveUnitReferencesTask =
|
| + new isInstanceOf<PartiallyResolveUnitReferencesTask>();
|
| +isInstanceOf isResolveLibraryTypeNamesTask =
|
| + new isInstanceOf<ResolveLibraryTypeNamesTask>();
|
| +isInstanceOf isResolveUnitTask = new isInstanceOf<ResolveUnitTask>();
|
| +isInstanceOf isResolveUnitTypeNamesTask =
|
| + new isInstanceOf<ResolveUnitTypeNamesTask>();
|
| +isInstanceOf isResolveVariableReferencesTask =
|
| + new isInstanceOf<ResolveVariableReferencesTask>();
|
| +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;
|
| + LibrarySpecificUnit target;
|
| +
|
| + test_perform_find_constants() {
|
| + _performBuildTask('''
|
| +const x = 1;
|
| +class C {
|
| + static const y = 1;
|
| + const C([p = 1]);
|
| +}
|
| +@x
|
| +f() {
|
| + const z = 1;
|
| +}
|
| +''');
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT1];
|
| + CompilationUnitElement unitElement = outputs[COMPILATION_UNIT_ELEMENT];
|
| + Annotation annotation = unit.declarations
|
| + .firstWhere((m) => m is FunctionDeclaration)
|
| + .metadata[0];
|
| + List<ConstantEvaluationTarget> expectedConstants = [
|
| + unitElement.accessors.firstWhere((e) => e.isGetter).variable,
|
| + unitElement.types[0].fields[0],
|
| + unitElement.functions[0].localVariables[0],
|
| + unitElement.types[0].constructors[0],
|
| + new ConstantEvaluationTarget_Annotation(
|
| + context, source, source, annotation),
|
| + unitElement.types[0].constructors[0].parameters[0]
|
| + ];
|
| + expect(
|
| + outputs[COMPILATION_UNIT_CONSTANTS].toSet(), expectedConstants.toSet());
|
| + }
|
| +
|
| + test_perform_library() {
|
| + _performBuildTask(r'''
|
| +library lib;
|
| +import 'lib2.dart';
|
| +export 'lib3.dart';
|
| +part 'part.dart';
|
| +final x = '';
|
| +class A {
|
| + static final y = 0;
|
| +}
|
| +class B = Object with A;
|
| +''');
|
| + expect(outputs, hasLength(3));
|
| + expect(outputs[COMPILATION_UNIT_CONSTANTS], isNotNull);
|
| + expect(outputs[COMPILATION_UNIT_ELEMENT], isNotNull);
|
| + expect(outputs[RESOLVED_UNIT1], isNotNull);
|
| + }
|
| +
|
| + test_perform_reuseElement() {
|
| + _performBuildTask(r'''
|
| +library lib;
|
| +class A {}
|
| +class B = Object with A;
|
| +''');
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT1];
|
| + CompilationUnitElement unitElement = outputs[COMPILATION_UNIT_ELEMENT];
|
| + expect(unit, isNotNull);
|
| + expect(unitElement, isNotNull);
|
| + // invalidate RESOLVED_UNIT1
|
| + CacheEntry cacheEntry = analysisCache.get(target);
|
| + cacheEntry.setState(RESOLVED_UNIT1, CacheState.INVALID);
|
| + // compute again
|
| + computeResult(target, RESOLVED_UNIT1,
|
| + matcher: isBuildCompilationUnitElementTask);
|
| + expect(outputs[COMPILATION_UNIT_ELEMENT], same(unitElement));
|
| + expect(outputs[RESOLVED_UNIT1], isNot(same(unit)));
|
| + }
|
| +
|
| + void _performBuildTask(String content) {
|
| + source = newSource('/test.dart', content);
|
| + target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, RESOLVED_UNIT1,
|
| + matcher: isBuildCompilationUnitElementTask);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildDirectiveElementsTaskTest extends _AbstractDartTaskTest {
|
| + test_perform() {
|
| + List<Source> sources = newSources({
|
| + '/libA.dart': '''
|
| +library libA;
|
| +import 'libB.dart';
|
| +export 'libC.dart';
|
| +''',
|
| + '/libB.dart': '''
|
| +library libB;
|
| +''',
|
| + '/libC.dart': '''
|
| +library libC;
|
| +'''
|
| + });
|
| + Source sourceA = sources[0];
|
| + Source sourceB = sources[1];
|
| + Source sourceC = sources[2];
|
| + // perform task
|
| + computeResult(sourceA, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // prepare outputs
|
| + LibraryElement libraryElementA = outputs[LIBRARY_ELEMENT2];
|
| + LibraryElement libraryElementB = _getImportLibraryInput(sourceB);
|
| + LibraryElement libraryElementC = _getExportLibraryInput(sourceC);
|
| + // no errors
|
| + _assertErrorsWithCodes([]);
|
| + // validate directives
|
| + CompilationUnit libraryUnitA = context
|
| + .getCacheEntry(new LibrarySpecificUnit(sourceA, sourceA))
|
| + .getValue(RESOLVED_UNIT1);
|
| + {
|
| + ImportDirective importNode = libraryUnitA.directives[1];
|
| + ImportElement importElement = importNode.element;
|
| + expect(importElement, isNotNull);
|
| + expect(importElement.importedLibrary, libraryElementB);
|
| + expect(importElement.prefix, isNull);
|
| + expect(importElement.nameOffset, 14);
|
| + expect(importElement.uriOffset, 21);
|
| + expect(importElement.uriEnd, 32);
|
| + }
|
| + {
|
| + ExportDirective exportNode = libraryUnitA.directives[2];
|
| + ExportElement exportElement = exportNode.element;
|
| + expect(exportElement, isNotNull);
|
| + expect(exportElement.exportedLibrary, libraryElementC);
|
| + expect(exportElement.nameOffset, 34);
|
| + expect(exportElement.uriOffset, 41);
|
| + expect(exportElement.uriEnd, 52);
|
| + }
|
| + // validate LibraryElement
|
| + expect(libraryElementA.hasExtUri, isFalse);
|
| + // has an artificial "dart:core" import
|
| + {
|
| + List<ImportElement> imports = libraryElementA.imports;
|
| + expect(imports, hasLength(2));
|
| + expect(imports[1].importedLibrary.isDartCore, isTrue);
|
| + expect(imports[1].isSynthetic, isTrue);
|
| + }
|
| + }
|
| +
|
| + test_perform_combinators() {
|
| + List<Source> sources = newSources({
|
| + '/libA.dart': '''
|
| +library libA;
|
| +import 'libB.dart' show A, B hide C, D;
|
| +''',
|
| + '/libB.dart': '''
|
| +library libB;
|
| +'''
|
| + });
|
| + Source sourceA = sources[0];
|
| + // perform task
|
| + computeResult(sourceA, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // prepare outputs
|
| + CompilationUnit libraryUnitA = context
|
| + .getCacheEntry(new LibrarySpecificUnit(sourceA, sourceA))
|
| + .getValue(RESOLVED_UNIT1);
|
| + // no errors
|
| + _assertErrorsWithCodes([]);
|
| + // validate directives
|
| + ImportDirective importNode = libraryUnitA.directives[1];
|
| + ImportElement importElement = importNode.element;
|
| + List<NamespaceCombinator> combinators = importElement.combinators;
|
| + expect(combinators, hasLength(2));
|
| + {
|
| + ShowElementCombinator combinator = combinators[0];
|
| + expect(combinator.offset, 33);
|
| + expect(combinator.end, 42);
|
| + expect(combinator.shownNames, ['A', 'B']);
|
| + }
|
| + {
|
| + HideElementCombinator combinator = combinators[1];
|
| + expect(combinator.hiddenNames, ['C', 'D']);
|
| + }
|
| + }
|
| +
|
| + test_perform_dartCoreContext() {
|
| + List<Source> sources = newSources({'/libA.dart': ''});
|
| + Source source = sources[0];
|
| + // perform task
|
| + computeResult(source, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // prepare outputs
|
| + LibraryElement libraryElement = outputs[LIBRARY_ELEMENT2];
|
| + // verify that dart:core has SDK context
|
| + {
|
| + LibraryElement coreLibrary = libraryElement.importedLibraries[0];
|
| + DartSdk dartSdk = context.sourceFactory.dartSdk;
|
| + expect(coreLibrary.context, same(dartSdk.context));
|
| + }
|
| + }
|
| +
|
| + test_perform_error_exportOfNonLibrary() {
|
| + List<Source> sources = newSources({
|
| + '/libA.dart': '''
|
| +library libA;
|
| +export 'part.dart';
|
| +''',
|
| + '/part.dart': '''
|
| +part of notLib;
|
| +'''
|
| + });
|
| + Source sourceA = sources[0];
|
| + // perform task
|
| + computeResult(sourceA, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // validate errors
|
| + _assertErrorsWithCodes([CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY]);
|
| + }
|
| +
|
| + test_perform_error_importOfNonLibrary() {
|
| + List<Source> sources = newSources({
|
| + '/libA.dart': '''
|
| +library libA;
|
| +import 'part.dart';
|
| +''',
|
| + '/part.dart': '''
|
| +part of notLib;
|
| +'''
|
| + });
|
| + Source sourceA = sources[0];
|
| + // perform task
|
| + computeResult(sourceA, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // validate errors
|
| + _assertErrorsWithCodes([CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY]);
|
| + }
|
| +
|
| + test_perform_explicitDartCoreImport() {
|
| + List<Source> sources = newSources({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +import 'dart:core' show List;
|
| +'''
|
| + });
|
| + Source source = sources[0];
|
| + // perform task
|
| + computeResult(source, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // prepare outputs
|
| + LibraryElement libraryElement = outputs[LIBRARY_ELEMENT2];
|
| + // has an explicit "dart:core" import
|
| + {
|
| + List<ImportElement> imports = libraryElement.imports;
|
| + expect(imports, hasLength(1));
|
| + expect(imports[0].importedLibrary.isDartCore, isTrue);
|
| + expect(imports[0].isSynthetic, isFalse);
|
| + }
|
| + }
|
| +
|
| + test_perform_hasExtUri() {
|
| + List<Source> sources = newSources({
|
| + '/lib.dart': '''
|
| +import 'dart-ext:doesNotExist.dart';
|
| +'''
|
| + });
|
| + Source source = sources[0];
|
| + // perform task
|
| + computeResult(source, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // prepare outputs
|
| + LibraryElement libraryElement = outputs[LIBRARY_ELEMENT2];
|
| + expect(libraryElement.hasExtUri, isTrue);
|
| + }
|
| +
|
| + test_perform_importPrefix() {
|
| + List<Source> sources = newSources({
|
| + '/libA.dart': '''
|
| +library libA;
|
| +import 'libB.dart' as pref;
|
| +import 'libC.dart' as pref;
|
| +''',
|
| + '/libB.dart': '''
|
| +library libB;
|
| +''',
|
| + '/libC.dart': '''
|
| +library libC;
|
| +'''
|
| + });
|
| + Source sourceA = sources[0];
|
| + Source sourceB = sources[1];
|
| + // perform task
|
| + computeResult(sourceA, LIBRARY_ELEMENT2,
|
| + matcher: isBuildDirectiveElementsTask);
|
| + // prepare outputs
|
| + CompilationUnit libraryUnitA = context
|
| + .getCacheEntry(new LibrarySpecificUnit(sourceA, sourceA))
|
| + .getValue(RESOLVED_UNIT1);
|
| + // validate directives
|
| + ImportDirective importNodeB = libraryUnitA.directives[1];
|
| + SimpleIdentifier prefixNodeB = importNodeB.prefix;
|
| + ImportElement importElementB = importNodeB.element;
|
| + PrefixElement prefixElement = importElementB.prefix;
|
| + expect(importElementB, isNotNull);
|
| + expect(importElementB.importedLibrary, _getImportLibraryInput(sourceB));
|
| + expect(prefixElement, isNotNull);
|
| + expect(importElementB.prefixOffset, prefixElement.nameOffset);
|
| + expect(prefixNodeB.staticElement, prefixElement);
|
| + // PrefixElement "pref" is shared
|
| + ImportDirective importNodeC = libraryUnitA.directives[2];
|
| + SimpleIdentifier prefixNodeC = importNodeC.prefix;
|
| + ImportElement importElementC = importNodeC.element;
|
| + expect(prefixNodeC.staticElement, prefixElement);
|
| + expect(importElementC.prefix, prefixElement);
|
| + }
|
| +
|
| + void _assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
|
| + _fillErrorListener(BUILD_DIRECTIVES_ERRORS);
|
| + errorListener.assertErrorsWithCodes(expectedErrorCodes);
|
| + }
|
| +
|
| + _getExportLibraryInput(Source source) {
|
| + var key = BuildDirectiveElementsTask.EXPORTS_LIBRARY_ELEMENT_INPUT_NAME;
|
| + return task.inputs[key][source];
|
| + }
|
| +
|
| + _getImportLibraryInput(Source source) {
|
| + var key = BuildDirectiveElementsTask.IMPORTS_LIBRARY_ELEMENT_INPUT_NAME;
|
| + return task.inputs[key][source];
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildEnumMemberElementsTaskTest extends _AbstractDartTaskTest {
|
| + test_perform() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +enum MyEnum {
|
| + A, B
|
| +}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT2,
|
| + matcher: isBuildEnumMemberElementsTask);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT2];
|
| + // validate Element
|
| + ClassElement enumElement = unit.element.getEnum('MyEnum');
|
| + List<FieldElement> fields = enumElement.fields;
|
| + expect(fields, hasLength(4));
|
| + {
|
| + FieldElementImpl index = fields[0];
|
| + expect(index, isNotNull);
|
| + expect(index.name, 'index');
|
| + expect(index.isStatic, isFalse);
|
| + expect(index.evaluationResult, isNull);
|
| + _assertGetter(index);
|
| + }
|
| + {
|
| + ConstFieldElementImpl values = fields[1];
|
| + expect(values, isNotNull);
|
| + expect(values.name, 'values');
|
| + expect(values.isStatic, isTrue);
|
| + expect(values.evaluationResult, isNotNull);
|
| + _assertGetter(values);
|
| + }
|
| + {
|
| + ConstFieldElementImpl constant = fields[2];
|
| + expect(constant, isNotNull);
|
| + expect(constant.name, 'A');
|
| + expect(constant.isStatic, isTrue);
|
| + expect(constant.evaluationResult, isNotNull);
|
| + _assertGetter(constant);
|
| + }
|
| + {
|
| + ConstFieldElementImpl constant = fields[3];
|
| + expect(constant, isNotNull);
|
| + expect(constant.name, 'B');
|
| + expect(constant.isStatic, isTrue);
|
| + expect(constant.evaluationResult, isNotNull);
|
| + _assertGetter(constant);
|
| + }
|
| + // validate nodes
|
| + EnumDeclaration enumNode = unit.declarations[0];
|
| + expect(enumNode.name.staticElement, same(enumElement));
|
| + expect(enumNode.constants[0].element, same(enumElement.getField('A')));
|
| + expect(enumNode.constants[1].element, same(enumElement.getField('B')));
|
| + }
|
| +
|
| + static void _assertGetter(FieldElement field) {
|
| + PropertyAccessorElement getter = field.getter;
|
| + expect(getter, isNotNull);
|
| + expect(getter.variable, same(field));
|
| + expect(getter.type, isNotNull);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildExportNamespaceTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_entryPoint() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +export 'b.dart';
|
| +''');
|
| + Source sourceB = newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +main() {}
|
| +''');
|
| + computeResult(sourceA, LIBRARY_ELEMENT4,
|
| + matcher: isBuildExportNamespaceTask);
|
| + // validate
|
| + LibraryElement library = outputs[LIBRARY_ELEMENT4];
|
| + FunctionElement entryPoint = library.entryPoint;
|
| + expect(entryPoint, isNotNull);
|
| + expect(entryPoint.source, sourceB);
|
| + }
|
| +
|
| + test_perform_hideCombinator() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +export 'b.dart' hide B1;
|
| +class A1 {}
|
| +class A2 {}
|
| +class _A3 {}
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +class B1 {}
|
| +class B2 {}
|
| +class B3 {}
|
| +class _B4 {}
|
| +''');
|
| + newSource(
|
| + '/c.dart',
|
| + '''
|
| +library lib_c;
|
| +class C1 {}
|
| +class C2 {}
|
| +class C3 {}
|
| +''');
|
| + computeResult(sourceA, LIBRARY_ELEMENT4,
|
| + matcher: isBuildExportNamespaceTask);
|
| + // validate
|
| + LibraryElement library = outputs[LIBRARY_ELEMENT4];
|
| + Namespace namespace = library.exportNamespace;
|
| + Iterable<String> definedKeys = namespace.definedNames.keys;
|
| + expect(definedKeys, unorderedEquals(['A1', 'A2', 'B2', 'B3']));
|
| + }
|
| +
|
| + test_perform_showCombinator() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +export 'b.dart' show B1;
|
| +class A1 {}
|
| +class A2 {}
|
| +class _A3 {}
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +class B1 {}
|
| +class B2 {}
|
| +class _B3 {}
|
| +''');
|
| + computeResult(sourceA, LIBRARY_ELEMENT4,
|
| + matcher: isBuildExportNamespaceTask);
|
| + // validate
|
| + LibraryElement library = outputs[LIBRARY_ELEMENT4];
|
| + Namespace namespace = library.exportNamespace;
|
| + Iterable<String> definedKeys = namespace.definedNames.keys;
|
| + expect(definedKeys, unorderedEquals(['A1', 'A2', 'B1']));
|
| + }
|
| +
|
| + test_perform_showCombinator_setter() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +export 'b.dart' show topLevelB;
|
| +class A {}
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +int topLevelB;
|
| +''');
|
| + computeResult(sourceA, LIBRARY_ELEMENT4,
|
| + matcher: isBuildExportNamespaceTask);
|
| + // validate
|
| + LibraryElement library = outputs[LIBRARY_ELEMENT4];
|
| + Namespace namespace = library.exportNamespace;
|
| + Iterable<String> definedKeys = namespace.definedNames.keys;
|
| + expect(definedKeys, unorderedEquals(['A', 'topLevelB', 'topLevelB=']));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildLibraryElementTaskTest extends _AbstractDartTaskTest {
|
| + Source librarySource;
|
| + CompilationUnit libraryUnit;
|
| + CompilationUnitElement libraryUnitElement;
|
| + List<CompilationUnit> partUnits;
|
| +
|
| + LibraryElement libraryElement;
|
| +
|
| + test_perform() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'part1.dart';
|
| +part 'part2.dart';
|
| +''',
|
| + '/part1.dart': '''
|
| +part of lib;
|
| +''',
|
| + '/part2.dart': '''
|
| +part of lib;
|
| +'''
|
| + });
|
| + expect(outputs, hasLength(3));
|
| + // simple outputs
|
| + expect(outputs[BUILD_LIBRARY_ERRORS], isEmpty);
|
| + expect(outputs[IS_LAUNCHABLE], isFalse);
|
| + // LibraryElement output
|
| + expect(libraryElement, isNotNull);
|
| + expect(libraryElement.entryPoint, isNull);
|
| + expect(libraryElement.source, same(librarySource));
|
| + expect(libraryElement.definingCompilationUnit, libraryUnitElement);
|
| + expect(libraryElement.parts,
|
| + unorderedEquals([partUnits[0].element, partUnits[1].element]));
|
| + // LibraryElement references
|
| + expect((libraryUnit.directives[0] as LibraryDirective).element,
|
| + same(libraryElement));
|
| + expect((partUnits[0].directives[0] as PartOfDirective).element,
|
| + same(libraryElement));
|
| + expect((partUnits[1].directives[0] as PartOfDirective).element,
|
| + same(libraryElement));
|
| + // CompilationUnitElement(s)
|
| + CompilationUnitElement firstPart;
|
| + CompilationUnitElement secondPart;
|
| + if (partUnits[0].element.uri == 'part1.dart') {
|
| + firstPart = partUnits[0].element;
|
| + secondPart = partUnits[1].element;
|
| + } else {
|
| + firstPart = partUnits[1].element;
|
| + secondPart = partUnits[0].element;
|
| + }
|
| + expect(firstPart.uri, 'part1.dart');
|
| + expect(firstPart.uriOffset, 18);
|
| + expect(firstPart.uriEnd, 30);
|
| + expect(
|
| + (libraryUnit.directives[1] as PartDirective).element, same(firstPart));
|
| +
|
| + expect(secondPart.uri, 'part2.dart');
|
| + expect(secondPart.uriOffset, 37);
|
| + expect(secondPart.uriEnd, 49);
|
| + expect(
|
| + (libraryUnit.directives[2] as PartDirective).element, same(secondPart));
|
| + }
|
| +
|
| + test_perform_error_missingLibraryDirectiveWithPart_hasCommon() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +part 'partA.dart';
|
| +part 'partB.dart';
|
| +''',
|
| + '/partA.dart': '''
|
| +part of my_lib;
|
| + ''',
|
| + '/partB.dart': '''
|
| +part of my_lib;
|
| +'''
|
| + });
|
| + _assertErrorsWithCodes(
|
| + [ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART]);
|
| + AnalysisError error = errorListener.errors[0];
|
| + expect(error.getProperty(ErrorProperty.PARTS_LIBRARY_NAME), 'my_lib');
|
| + }
|
| +
|
| + test_perform_error_missingLibraryDirectiveWithPart_noCommon() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +part 'partA.dart';
|
| +part 'partB.dart';
|
| +''',
|
| + '/partA.dart': '''
|
| +part of libA;
|
| + ''',
|
| + '/partB.dart': '''
|
| +part of libB;
|
| +'''
|
| + });
|
| + _assertErrorsWithCodes(
|
| + [ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART]);
|
| + AnalysisError error = errorListener.errors[0];
|
| + expect(error.getProperty(ErrorProperty.PARTS_LIBRARY_NAME), isNull);
|
| + }
|
| +
|
| + test_perform_error_partDoesNotExist() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'part.dart';
|
| +'''
|
| + });
|
| + // we already report URI_DOES_NOT_EXIST, no need to report other errors
|
| + _assertErrorsWithCodes([]);
|
| + }
|
| +
|
| + test_perform_error_partOfDifferentLibrary() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'part.dart';
|
| +''',
|
| + '/part.dart': '''
|
| +part of someOtherLib;
|
| +'''
|
| + });
|
| + _assertErrorsWithCodes([StaticWarningCode.PART_OF_DIFFERENT_LIBRARY]);
|
| + }
|
| +
|
| + test_perform_error_partOfNonPart() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'part.dart';
|
| +''',
|
| + '/part.dart': '''
|
| +// no part of
|
| +'''
|
| + });
|
| + _assertErrorsWithCodes([CompileTimeErrorCode.PART_OF_NON_PART]);
|
| + }
|
| +
|
| + test_perform_invalidUri_part() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part '//////////';
|
| +'''
|
| + });
|
| + expect(libraryElement.parts, isEmpty);
|
| + }
|
| +
|
| + test_perform_isLaunchable_inDefiningUnit() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +main() {
|
| +}
|
| +'''
|
| + });
|
| + expect(outputs[IS_LAUNCHABLE], isTrue);
|
| + expect(libraryElement.entryPoint, isNotNull);
|
| + }
|
| +
|
| + test_perform_isLaunchable_inPartUnit() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'part.dart';
|
| +''',
|
| + '/part.dart': '''
|
| +part of lib;
|
| +main() {
|
| +}
|
| +'''
|
| + });
|
| + expect(outputs[IS_LAUNCHABLE], isTrue);
|
| + expect(libraryElement.entryPoint, isNotNull);
|
| + }
|
| +
|
| + test_perform_noSuchFilePart() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'no-such-file.dart';
|
| +'''
|
| + });
|
| + expect(libraryElement.parts, hasLength(1));
|
| + CompilationUnitElement part = libraryElement.parts[0];
|
| + expect(part, isNotNull);
|
| + expect(part.source, isNotNull);
|
| + expect(part.library, same(libraryElement));
|
| + expect(context.exists(part.source), isFalse);
|
| + }
|
| +
|
| + test_perform_patchTopLevelAccessors() {
|
| + _performBuildTask({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'part1.dart';
|
| +part 'part2.dart';
|
| +''',
|
| + '/part1.dart': '''
|
| +part of lib;
|
| +int get test => 0;
|
| +''',
|
| + '/part2.dart': '''
|
| +part of lib;
|
| +void set test(_) {}
|
| +'''
|
| + });
|
| + CompilationUnitElement unitElement1 = partUnits[0].element;
|
| + CompilationUnitElement unitElement2 = partUnits[1].element;
|
| + PropertyAccessorElement getter = unitElement1.accessors[0];
|
| + PropertyAccessorElement setter = unitElement2.accessors[0];
|
| + PropertyInducingElement variable = getter.variable;
|
| + expect(getter.isGetter, isTrue);
|
| + expect(setter.isSetter, isTrue);
|
| + expect(variable, isNotNull);
|
| + expect(setter.variable, same(variable));
|
| + expect(unitElement1.topLevelVariables, [variable]);
|
| + expect(unitElement2.topLevelVariables, [variable]);
|
| + }
|
| +
|
| + void _assertErrorsWithCodes(List<ErrorCode> expectedErrorCodes) {
|
| + _fillErrorListener(BUILD_LIBRARY_ERRORS);
|
| + errorListener.assertErrorsWithCodes(expectedErrorCodes);
|
| + }
|
| +
|
| + void _performBuildTask(Map<String, String> sourceMap) {
|
| + List<Source> sources = newSources(sourceMap);
|
| + Source libSource = sources.first;
|
| + computeResult(libSource, LIBRARY_ELEMENT1,
|
| + matcher: isBuildLibraryElementTask);
|
| + libraryUnit = context
|
| + .getCacheEntry(new LibrarySpecificUnit(libSource, libSource))
|
| + .getValue(RESOLVED_UNIT1);
|
| + libraryUnitElement = libraryUnit.element;
|
| + librarySource = libraryUnitElement.source;
|
| + libraryElement = outputs[LIBRARY_ELEMENT1];
|
| + partUnits = task.inputs[BuildLibraryElementTask.PARTS_UNIT_INPUT];
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildPublicNamespaceTaskTest extends _AbstractDartTaskTest {
|
| + test_perform() {
|
| + List<Source> sources = newSources({
|
| + '/lib.dart': '''
|
| +library lib;
|
| +part 'part.dart';
|
| +a() {}
|
| +_b() {}
|
| +''',
|
| + '/part.dart': '''
|
| +part of lib;
|
| +_c() {}
|
| +d() {}
|
| +'''
|
| + });
|
| + computeResult(sources.first, LIBRARY_ELEMENT3,
|
| + matcher: isBuildPublicNamespaceTask);
|
| + // validate
|
| + LibraryElement library = outputs[LIBRARY_ELEMENT3];
|
| + Namespace namespace = library.publicNamespace;
|
| + expect(namespace.definedNames.keys, unorderedEquals(['a', 'd']));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildSourceExportClosureTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_exportClosure() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +export 'b.dart';
|
| +''');
|
| + Source sourceB = newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +export 'c.dart';
|
| +''');
|
| + Source sourceC = newSource(
|
| + '/c.dart',
|
| + '''
|
| +library lib_c;
|
| +export 'a.dart';
|
| +''');
|
| + Source sourceD = newSource(
|
| + '/d.dart',
|
| + '''
|
| +library lib_d;
|
| +''');
|
| + // a.dart
|
| + {
|
| + computeResult(sourceA, EXPORT_SOURCE_CLOSURE,
|
| + matcher: isBuildSourceExportClosureTask);
|
| + List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
|
| + expect(closure, unorderedEquals([sourceA, sourceB, sourceC]));
|
| + }
|
| + // c.dart
|
| + {
|
| + computeResult(sourceC, EXPORT_SOURCE_CLOSURE,
|
| + matcher: isBuildSourceExportClosureTask);
|
| + List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
|
| + expect(closure, unorderedEquals([sourceA, sourceB, sourceC]));
|
| + }
|
| + // d.dart
|
| + {
|
| + computeResult(sourceD, EXPORT_SOURCE_CLOSURE,
|
| + matcher: isBuildSourceExportClosureTask);
|
| + List<Source> closure = outputs[EXPORT_SOURCE_CLOSURE];
|
| + expect(closure, unorderedEquals([sourceD]));
|
| + }
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildSourceImportExportClosureTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_importExportClosure() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +''');
|
| + Source sourceB = newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +export 'a.dart';
|
| +''');
|
| + Source sourceC = newSource(
|
| + '/c.dart',
|
| + '''
|
| +library lib_c;
|
| +import 'b.dart';
|
| +''');
|
| + Source coreSource = context.sourceFactory.resolveUri(null, 'dart:core');
|
| + // c.dart
|
| + {
|
| + computeResult(sourceC, IMPORT_EXPORT_SOURCE_CLOSURE,
|
| + matcher: isBuildSourceImportExportClosureTask);
|
| + List<Source> closure = outputs[IMPORT_EXPORT_SOURCE_CLOSURE];
|
| + expect(closure, contains(sourceA));
|
| + expect(closure, contains(sourceB));
|
| + expect(closure, contains(sourceC));
|
| + expect(closure, contains(coreSource));
|
| + }
|
| + // b.dart
|
| + {
|
| + computeResult(sourceB, IMPORT_EXPORT_SOURCE_CLOSURE,
|
| + matcher: isBuildSourceImportExportClosureTask);
|
| + List<Source> closure = outputs[IMPORT_EXPORT_SOURCE_CLOSURE];
|
| + expect(closure, contains(sourceA));
|
| + expect(closure, contains(sourceB));
|
| + expect(closure, contains(coreSource));
|
| + }
|
| + }
|
| +
|
| + test_perform_isClient_false() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +import 'b.dart';
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +''');
|
| + computeResult(sourceA, IS_CLIENT,
|
| + matcher: isBuildSourceImportExportClosureTask);
|
| + expect(outputs[IS_CLIENT], isFalse);
|
| + }
|
| +
|
| + test_perform_isClient_true_export_indirect() {
|
| + newSource(
|
| + '/exports_html.dart',
|
| + '''
|
| +library lib_exports_html;
|
| +export 'dart:html';
|
| +''');
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +import 'exports_html.dart';
|
| +''');
|
| + computeResult(source, IS_CLIENT,
|
| + matcher: isBuildSourceImportExportClosureTask);
|
| + expect(outputs[IS_CLIENT], isTrue);
|
| + }
|
| +
|
| + test_perform_isClient_true_import_direct() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +import 'dart:html';
|
| +''');
|
| + computeResult(sourceA, IS_CLIENT,
|
| + matcher: isBuildSourceImportExportClosureTask);
|
| + expect(outputs[IS_CLIENT], isTrue);
|
| + }
|
| +
|
| + test_perform_isClient_true_import_indirect() {
|
| + Source sourceA = newSource(
|
| + '/a.dart',
|
| + '''
|
| +library lib_a;
|
| +import 'b.dart';
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + '''
|
| +library lib_b;
|
| +import 'dart:html';
|
| +''');
|
| + computeResult(sourceA, IS_CLIENT,
|
| + matcher: isBuildSourceImportExportClosureTask);
|
| + expect(outputs[IS_CLIENT], isTrue);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class BuildTypeProviderTaskTest extends _AbstractDartTaskTest {
|
| + test_perform() {
|
| + computeResult(AnalysisContextTarget.request, TYPE_PROVIDER,
|
| + matcher: isBuildTypeProviderTask);
|
| + // validate
|
| + TypeProvider typeProvider = outputs[TYPE_PROVIDER];
|
| + expect(typeProvider, isNotNull);
|
| + expect(typeProvider.boolType, isNotNull);
|
| + expect(typeProvider.intType, isNotNull);
|
| + expect(typeProvider.futureType, isNotNull);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ComputeConstantDependenciesTaskTest extends _AbstractDartTaskTest {
|
| + Annotation findClassAnnotation(CompilationUnit unit, String className) {
|
| + for (CompilationUnitMember member in unit.declarations) {
|
| + if (member is ClassDeclaration && member.name.name == className) {
|
| + expect(member.metadata, hasLength(1));
|
| + return member.metadata[0];
|
| + }
|
| + }
|
| + fail('Annotation not found');
|
| + return null;
|
| + }
|
| +
|
| + test_annotation_with_args() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const x = 1;
|
| +@D(x) class C {}
|
| +class D { const D(value); }
|
| +''');
|
| + // First compute the resolved unit for the source.
|
| + LibrarySpecificUnit librarySpecificUnit =
|
| + new LibrarySpecificUnit(source, source);
|
| + computeResult(librarySpecificUnit, RESOLVED_UNIT1);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT1];
|
| + // Find the elements for x and D's constructor, and the annotation on C.
|
| + List<PropertyAccessorElement> accessors = unit.element.accessors;
|
| + Element x = accessors
|
| + .firstWhere((PropertyAccessorElement accessor) =>
|
| + accessor.isGetter && accessor.name == 'x')
|
| + .variable;
|
| + List<ClassElement> types = unit.element.types;
|
| + Element constructorForD =
|
| + types.firstWhere((ClassElement cls) => cls.name == 'D').constructors[0];
|
| + Annotation annotation = findClassAnnotation(unit, 'C');
|
| + // Now compute the dependencies for the annotation, and check that it is
|
| + // the set [x, constructorForD].
|
| + // TODO(paulberry): test librarySource != source
|
| + computeResult(
|
| + new ConstantEvaluationTarget_Annotation(
|
| + context, source, source, annotation),
|
| + CONSTANT_DEPENDENCIES,
|
| + matcher: isComputeConstantDependenciesTask);
|
| + expect(
|
| + outputs[CONSTANT_DEPENDENCIES].toSet(), [x, constructorForD].toSet());
|
| + }
|
| +
|
| + test_annotation_without_args() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const x = 1;
|
| +@x class C {}
|
| +''');
|
| + // First compute the resolved unit for the source.
|
| + LibrarySpecificUnit librarySpecificUnit =
|
| + new LibrarySpecificUnit(source, source);
|
| + computeResult(librarySpecificUnit, RESOLVED_UNIT1);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT1];
|
| + // Find the element for x and the annotation on C.
|
| + List<PropertyAccessorElement> accessors = unit.element.accessors;
|
| + Element x = accessors
|
| + .firstWhere((PropertyAccessorElement accessor) =>
|
| + accessor.isGetter && accessor.name == 'x')
|
| + .variable;
|
| + Annotation annotation = findClassAnnotation(unit, 'C');
|
| + // Now compute the dependencies for the annotation, and check that it is
|
| + // the list [x].
|
| + computeResult(
|
| + new ConstantEvaluationTarget_Annotation(
|
| + context, source, source, annotation),
|
| + CONSTANT_DEPENDENCIES,
|
| + matcher: isComputeConstantDependenciesTask);
|
| + expect(outputs[CONSTANT_DEPENDENCIES], [x]);
|
| + }
|
| +
|
| + test_enumConstant() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +enum E {A, B, C}
|
| +''');
|
| + // First compute the resolved unit for the source.
|
| + LibrarySpecificUnit librarySpecificUnit =
|
| + new LibrarySpecificUnit(source, source);
|
| + computeResult(librarySpecificUnit, RESOLVED_UNIT2);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT2];
|
| + // Find the element for 'A'
|
| + EnumDeclaration enumDeclaration = unit.declarations[0];
|
| + EnumConstantDeclaration constantDeclaration = enumDeclaration.constants[0];
|
| + FieldElement constantElement = constantDeclaration.element;
|
| + // Now compute the dependencies for the constant and check that there are
|
| + // none.
|
| + computeResult(constantElement, CONSTANT_DEPENDENCIES,
|
| + matcher: isComputeConstantDependenciesTask);
|
| + expect(outputs[CONSTANT_DEPENDENCIES], isEmpty);
|
| + }
|
| +
|
| + test_perform() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const x = y;
|
| +const y = 1;
|
| +''');
|
| + // First compute the resolved unit for the source.
|
| + LibrarySpecificUnit librarySpecificUnit =
|
| + new LibrarySpecificUnit(source, source);
|
| + computeResult(librarySpecificUnit, RESOLVED_UNIT1);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT1];
|
| + // Find the elements for the constants x and y.
|
| + List<PropertyAccessorElement> accessors = unit.element.accessors;
|
| + Element x = accessors
|
| + .firstWhere((PropertyAccessorElement accessor) =>
|
| + accessor.isGetter && accessor.name == 'x')
|
| + .variable;
|
| + Element y = accessors
|
| + .firstWhere((PropertyAccessorElement accessor) =>
|
| + accessor.isGetter && accessor.name == 'y')
|
| + .variable;
|
| + // Now compute the dependencies for x, and check that it is the list [y].
|
| + computeResult(x, CONSTANT_DEPENDENCIES,
|
| + matcher: isComputeConstantDependenciesTask);
|
| + expect(outputs[CONSTANT_DEPENDENCIES], [y]);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ComputeConstantValueTaskTest extends _AbstractDartTaskTest {
|
| + EvaluationResultImpl computeClassAnnotation(
|
| + Source source, CompilationUnit unit, String className) {
|
| + for (CompilationUnitMember member in unit.declarations) {
|
| + if (member is ClassDeclaration && member.name.name == className) {
|
| + expect(member.metadata, hasLength(1));
|
| + Annotation annotation = member.metadata[0];
|
| + ConstantEvaluationTarget_Annotation target =
|
| + new ConstantEvaluationTarget_Annotation(
|
| + context, source, source, annotation);
|
| + computeResult(target, CONSTANT_VALUE,
|
| + matcher: isComputeConstantValueTask);
|
| + expect(outputs[CONSTANT_VALUE], same(target));
|
| + EvaluationResultImpl evaluationResult = (annotation.elementAnnotation
|
| + as ElementAnnotationImpl).evaluationResult;
|
| + return evaluationResult;
|
| + }
|
| + }
|
| + fail('Annotation not found');
|
| + return null;
|
| + }
|
| +
|
| + test_annotation_non_const_constructor() {
|
| + // Calling a non-const constructor from an annotation that is illegal, but
|
| + // shouldn't crash analysis.
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +class A {
|
| + final int i;
|
| + A(this.i);
|
| +}
|
| +
|
| +@A(5)
|
| +class C {}
|
| +''');
|
| + // First compute the resolved unit for the source.
|
| + CompilationUnit unit = _resolveSource(source);
|
| + // Compute the constant value of the annotation on C.
|
| + EvaluationResultImpl evaluationResult =
|
| + computeClassAnnotation(source, unit, 'C');
|
| + // And check that it has no value stored in it.
|
| + expect(evaluationResult, isNotNull);
|
| + expect(evaluationResult.value, isNull);
|
| + }
|
| +
|
| + test_annotation_with_args() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const x = 1;
|
| +@D(x) class C {}
|
| +class D {
|
| + const D(this.value);
|
| + final value;
|
| +}
|
| +''');
|
| + // First compute the resolved unit for the source.
|
| + CompilationUnit unit = _resolveSource(source);
|
| + // Compute the constant value of the annotation on C.
|
| + EvaluationResultImpl evaluationResult =
|
| + computeClassAnnotation(source, unit, 'C');
|
| + // And check that it has the expected value.
|
| + expect(evaluationResult, isNotNull);
|
| + expect(evaluationResult.value, isNotNull);
|
| + expect(evaluationResult.value.type, isNotNull);
|
| + expect(evaluationResult.value.type.name, 'D');
|
| + expect(evaluationResult.value.fields, contains('value'));
|
| + expect(evaluationResult.value.fields['value'].intValue, 1);
|
| + }
|
| +
|
| + test_annotation_without_args() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const x = 1;
|
| +@x class C {}
|
| +''');
|
| + // First compute the resolved unit for the source.
|
| + CompilationUnit unit = _resolveSource(source);
|
| + // Compute the constant value of the annotation on C.
|
| + EvaluationResultImpl evaluationResult =
|
| + computeClassAnnotation(source, unit, 'C');
|
| + // And check that it has the expected value.
|
| + expect(evaluationResult, isNotNull);
|
| + expect(evaluationResult.value, isNotNull);
|
| + expect(evaluationResult.value.intValue, 1);
|
| + }
|
| +
|
| + test_circular_reference() {
|
| + _checkCircularities(
|
| + 'x',
|
| + ['y'],
|
| + '''
|
| +const x = y + 1;
|
| +const y = x + 1;
|
| +''');
|
| + }
|
| +
|
| + test_circular_reference_one_element() {
|
| + // See dartbug.com/23490.
|
| + _checkCircularities('x', [], 'const x = x;');
|
| + }
|
| +
|
| + test_circular_reference_strongly_connected_component() {
|
| + // When there is a circularity, all elements in the strongly connected
|
| + // component should be marked as having an error.
|
| + _checkCircularities(
|
| + 'a',
|
| + ['b', 'c', 'd'],
|
| + '''
|
| +const a = b;
|
| +const b = c + d;
|
| +const c = a;
|
| +const d = a;
|
| +''');
|
| + }
|
| +
|
| + test_const_constructor_calls_implicit_super_constructor_implicitly() {
|
| + // Note: the situation below is a compile-time error (since the synthetic
|
| + // constructor for Base is non-const), but we need to handle it without
|
| + // throwing an exception.
|
| + EvaluationResultImpl evaluationResult = _computeTopLevelVariableConstValue(
|
| + 'x',
|
| + '''
|
| +class Base {}
|
| +class Derived extends Base {
|
| + const Derived();
|
| +}
|
| +const x = const Derived();
|
| +''');
|
| + expect(evaluationResult, isNotNull);
|
| + }
|
| +
|
| + test_dependency() {
|
| + EvaluationResultImpl evaluationResult = _computeTopLevelVariableConstValue(
|
| + 'x',
|
| + '''
|
| +const x = y + 1;
|
| +const y = 1;
|
| +''');
|
| + expect(evaluationResult, isNotNull);
|
| + expect(evaluationResult.value, isNotNull);
|
| + expect(evaluationResult.value.intValue, 2);
|
| + }
|
| +
|
| + test_external_const_factory() {
|
| + EvaluationResultImpl evaluationResult = _computeTopLevelVariableConstValue(
|
| + 'x',
|
| + '''
|
| +const x = const C.foo();
|
| +
|
| +class C extends B {
|
| + external const factory C.foo();
|
| +}
|
| +
|
| +class B {}
|
| +''');
|
| + expect(evaluationResult, isNotNull);
|
| + }
|
| +
|
| + test_simple_constant() {
|
| + EvaluationResultImpl evaluationResult = _computeTopLevelVariableConstValue(
|
| + 'x',
|
| + '''
|
| +const x = 1;
|
| +''');
|
| + expect(evaluationResult, isNotNull);
|
| + expect(evaluationResult.value, isNotNull);
|
| + expect(evaluationResult.value.intValue, 1);
|
| + }
|
| +
|
| + void _checkCircularities(
|
| + String variableName, List<String> otherVariables, String content) {
|
| + // Evaluating the first constant should produce an error.
|
| + CompilationUnit unit = _resolveUnit(content);
|
| + _expectCircularityError(_evaluateConstant(unit, variableName));
|
| + // And all the other constants involved in the strongly connected component
|
| + // should be set to the same error state.
|
| + for (String otherVariableName in otherVariables) {
|
| + PropertyInducingElement otherVariableElement =
|
| + _findVariable(unit, otherVariableName);
|
| + _expectCircularityError((otherVariableElement
|
| + as TopLevelVariableElementImpl).evaluationResult);
|
| + }
|
| + }
|
| +
|
| + EvaluationResultImpl _computeTopLevelVariableConstValue(
|
| + String variableName, String content) {
|
| + return _evaluateConstant(_resolveUnit(content), variableName);
|
| + }
|
| +
|
| + EvaluationResultImpl _evaluateConstant(
|
| + CompilationUnit unit, String variableName) {
|
| + // Find the element for the given constant.
|
| + PropertyInducingElement variableElement = _findVariable(unit, variableName);
|
| + // Now compute the value of the constant.
|
| + computeResult(variableElement, CONSTANT_VALUE,
|
| + matcher: isComputeConstantValueTask);
|
| + expect(outputs[CONSTANT_VALUE], same(variableElement));
|
| + EvaluationResultImpl evaluationResult =
|
| + (variableElement as TopLevelVariableElementImpl).evaluationResult;
|
| + return evaluationResult;
|
| + }
|
| +
|
| + void _expectCircularityError(EvaluationResultImpl evaluationResult) {
|
| + expect(evaluationResult, isNotNull);
|
| + expect(evaluationResult.value, isNull);
|
| + expect(evaluationResult.errors, hasLength(1));
|
| + expect(evaluationResult.errors[0].errorCode,
|
| + CompileTimeErrorCode.RECURSIVE_COMPILE_TIME_CONSTANT);
|
| + }
|
| +
|
| + PropertyInducingElement _findVariable(
|
| + CompilationUnit unit, String variableName) {
|
| + // Find the element for the given constant.
|
| + return unit.element.topLevelVariables.firstWhere(
|
| + (TopLevelVariableElement variable) => variable.name == variableName);
|
| + }
|
| +
|
| + CompilationUnit _resolveSource(Source source) {
|
| + LibrarySpecificUnit librarySpecificUnit =
|
| + new LibrarySpecificUnit(source, source);
|
| + computeResult(librarySpecificUnit, RESOLVED_UNIT1);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT1];
|
| + return unit;
|
| + }
|
| +
|
| + CompilationUnit _resolveUnit(String content) =>
|
| + _resolveSource(newSource('/test.dart', content));
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ComputeInferableStaticVariableDependenciesTaskTest
|
| + extends _AbstractDartTaskTest {
|
| + @override
|
| + void setUp() {
|
| + super.setUp();
|
| + // Variable dependencies are only available in strong mode.
|
| + enableStrongMode();
|
| + }
|
| +
|
| + test_perform() {
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const a = b;
|
| +const b = 0;
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, RESOLVED_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + TopLevelVariableElement elementA = unit.element.topLevelVariables[0];
|
| + TopLevelVariableElement elementB = unit.element.topLevelVariables[1];
|
| +
|
| + computeResult(elementA, INFERABLE_STATIC_VARIABLE_DEPENDENCIES,
|
| + matcher: isComputeInferableStaticVariableDependenciesTask);
|
| + expect(outputs, hasLength(1));
|
| + List<VariableElement> dependencies =
|
| + outputs[INFERABLE_STATIC_VARIABLE_DEPENDENCIES];
|
| + expect(dependencies, unorderedEquals([elementB]));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ComputeLibraryCycleTaskTest extends _AbstractDartTaskTest {
|
| + @override
|
| + void setUp() {
|
| + super.setUp();
|
| + enableStrongMode();
|
| + }
|
| +
|
| + void test_library_cycle_linear() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| +''',
|
| + '/b.dart': '''
|
| +import 'a.dart';
|
| + '''
|
| + });
|
| + List<Map<ResultDescriptor, dynamic>> results =
|
| + computeLibraryResultsMap(sources, LIBRARY_CYCLE);
|
| + List<LibraryElement> component0 = results[0][LIBRARY_CYCLE];
|
| + List<LibraryElement> component1 = results[1][LIBRARY_CYCLE];
|
| + expect(component0, hasLength(1));
|
| + expect(component1, hasLength(1));
|
| +
|
| + List<CompilationUnitElement> units0 = results[0][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units1 = results[1][LIBRARY_CYCLE_UNITS];
|
| + expect(units0, hasLength(1));
|
| + expect(units1, hasLength(1));
|
| +
|
| + List<CompilationUnitElement> dep0 = results[0][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep1 = results[1][LIBRARY_CYCLE_DEPENDENCIES];
|
| + expect(dep0, hasLength(1)); // dart:core
|
| + expect(dep1, hasLength(2)); // dart:core, a.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<Map<ResultDescriptor, dynamic>> results =
|
| + computeLibraryResultsMap(sources, LIBRARY_CYCLE).toList();
|
| + List<LibraryElement> component0 = results[0][LIBRARY_CYCLE];
|
| + List<LibraryElement> component1 = results[1][LIBRARY_CYCLE];
|
| + List<LibraryElement> component2 = results[2][LIBRARY_CYCLE];
|
| +
|
| + expect(component0, hasLength(3));
|
| + expect(component1, hasLength(3));
|
| + expect(component2, hasLength(3));
|
| +
|
| + List<CompilationUnitElement> units0 = results[0][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units1 = results[1][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units2 = results[2][LIBRARY_CYCLE_UNITS];
|
| + expect(units0, hasLength(3));
|
| + expect(units1, hasLength(3));
|
| + expect(units2, hasLength(3));
|
| +
|
| + List<CompilationUnitElement> dep0 = results[0][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep1 = results[1][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep2 = results[2][LIBRARY_CYCLE_DEPENDENCIES];
|
| + 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<Map<ResultDescriptor, dynamic>> results =
|
| + computeLibraryResultsMap(sources, LIBRARY_CYCLE).toList();
|
| + List<LibraryElement> component0 = results[0][LIBRARY_CYCLE];
|
| + expect(component0, hasLength(1));
|
| +
|
| + List<CompilationUnitElement> units0 = results[0][LIBRARY_CYCLE_UNITS];
|
| + expect(units0, hasLength(1));
|
| +
|
| + List<CompilationUnitElement> dep0 = results[0][LIBRARY_CYCLE_DEPENDENCIES];
|
| + expect(dep0, hasLength(1)); // dart:core
|
| + }
|
| +
|
| + void test_library_cycle_singleton() {
|
| + 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];
|
| + List<CompilationUnitElement> deps = outputs[LIBRARY_CYCLE_DEPENDENCIES];
|
| + expect(component, hasLength(1));
|
| + expect(units, hasLength(1));
|
| + expect(deps, hasLength(1));
|
| + }
|
| +
|
| + void test_library_cycle_tree() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| +''',
|
| + '/b.dart': '''
|
| + ''',
|
| + '/c.dart': '''
|
| + import 'a.dart';
|
| + import 'b.dart';
|
| + '''
|
| + });
|
| + List<Map<ResultDescriptor, dynamic>> results =
|
| + computeLibraryResultsMap(sources, LIBRARY_CYCLE);
|
| + List<LibraryElement> component0 = results[0][LIBRARY_CYCLE];
|
| + List<LibraryElement> component1 = results[1][LIBRARY_CYCLE];
|
| + List<LibraryElement> component2 = results[2][LIBRARY_CYCLE];
|
| + expect(component0, hasLength(1));
|
| + expect(component1, hasLength(1));
|
| + expect(component2, hasLength(1));
|
| +
|
| + List<CompilationUnitElement> units0 = results[0][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units1 = results[1][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units2 = results[2][LIBRARY_CYCLE_UNITS];
|
| + expect(units0, hasLength(1));
|
| + expect(units1, hasLength(1));
|
| + expect(units2, hasLength(1));
|
| +
|
| + List<CompilationUnitElement> dep0 = results[0][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep1 = results[1][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep2 = results[2][LIBRARY_CYCLE_DEPENDENCIES];
|
| + 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_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<Map<ResultDescriptor, dynamic>> results =
|
| + computeLibraryResultsMap(sources, LIBRARY_CYCLE).toList();
|
| + List<LibraryElement> component0 = results[0][LIBRARY_CYCLE];
|
| + List<LibraryElement> component1 = results[1][LIBRARY_CYCLE];
|
| + List<LibraryElement> component2 = results[2][LIBRARY_CYCLE];
|
| + List<LibraryElement> component3 = results[3][LIBRARY_CYCLE];
|
| +
|
| + expect(component0, hasLength(2));
|
| + expect(component1, hasLength(2));
|
| + expect(component2, hasLength(2));
|
| + expect(component3, hasLength(2));
|
| +
|
| + List<CompilationUnitElement> units0 = results[0][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units1 = results[1][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units2 = results[2][LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units3 = results[3][LIBRARY_CYCLE_UNITS];
|
| + expect(units0, hasLength(2));
|
| + expect(units1, hasLength(2));
|
| + expect(units2, hasLength(2));
|
| + expect(units3, hasLength(2));
|
| +
|
| + List<CompilationUnitElement> dep0 = results[0][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep1 = results[1][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep2 = results[2][LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep3 = results[3][LIBRARY_CYCLE_DEPENDENCIES];
|
| + 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
|
| + }
|
| +
|
| + void test_library_double_loop_parts() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| + import 'b.dart';
|
| + part 'aa.dart';
|
| + part 'ab.dart';
|
| +''',
|
| + '/b.dart': '''
|
| + import 'a.dart';
|
| +''',
|
| + '/aa.dart': '''
|
| +''',
|
| + '/ab.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';
|
| + part 'da.dart';
|
| + part 'db.dart';
|
| +''',
|
| + '/da.dart': '''
|
| +''',
|
| + '/db.dart': '''
|
| +'''
|
| + });
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[0], sources[0]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results0 = outputs;
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[1], sources[1]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results1 = outputs;
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[0], sources[2]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results2 = outputs;
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[0], sources[3]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results3 = outputs;
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[4], sources[4]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results4 = outputs;
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[5], sources[5]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results5 = outputs;
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[5], sources[6]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results6 = outputs;
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[5], sources[7]), LIBRARY_CYCLE);
|
| + Map<ResultDescriptor, dynamic> results7 = outputs;
|
| +
|
| + List<LibraryElement> component0 = results0[LIBRARY_CYCLE];
|
| + List<LibraryElement> component1 = results1[LIBRARY_CYCLE];
|
| + List<LibraryElement> component2 = results2[LIBRARY_CYCLE];
|
| + List<LibraryElement> component3 = results3[LIBRARY_CYCLE];
|
| + List<LibraryElement> component4 = results4[LIBRARY_CYCLE];
|
| + List<LibraryElement> component5 = results5[LIBRARY_CYCLE];
|
| + List<LibraryElement> component6 = results6[LIBRARY_CYCLE];
|
| + List<LibraryElement> component7 = results7[LIBRARY_CYCLE];
|
| +
|
| + expect(component0, hasLength(2));
|
| + expect(component1, hasLength(2));
|
| + expect(component2, hasLength(2));
|
| + expect(component3, hasLength(2));
|
| + expect(component4, hasLength(2));
|
| + expect(component5, hasLength(2));
|
| + expect(component6, hasLength(2));
|
| + expect(component7, hasLength(2));
|
| +
|
| + List<CompilationUnitElement> units0 = results0[LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units1 = results1[LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units2 = results2[LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units3 = results3[LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units4 = results4[LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units5 = results5[LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units6 = results6[LIBRARY_CYCLE_UNITS];
|
| + List<CompilationUnitElement> units7 = results7[LIBRARY_CYCLE_UNITS];
|
| + expect(units0, hasLength(4));
|
| + expect(units1, hasLength(4));
|
| + expect(units2, hasLength(4));
|
| + expect(units3, hasLength(4));
|
| + expect(units4, hasLength(4));
|
| + expect(units5, hasLength(4));
|
| + expect(units6, hasLength(4));
|
| + expect(units7, hasLength(4));
|
| +
|
| + List<CompilationUnitElement> dep0 = results0[LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep1 = results1[LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep2 = results2[LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep3 = results3[LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep4 = results4[LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep5 = results5[LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep6 = results6[LIBRARY_CYCLE_DEPENDENCIES];
|
| + List<CompilationUnitElement> dep7 = results7[LIBRARY_CYCLE_DEPENDENCIES];
|
| + expect(dep0, hasLength(1)); // dart:core
|
| + expect(dep1, hasLength(1)); // dart:core
|
| + expect(dep2, hasLength(1)); // dart:core
|
| + expect(dep3, hasLength(1)); // dart:core
|
| + expect(dep4, hasLength(5)); // dart:core, a.dart, aa.dart, ab.dart, b.dart
|
| + expect(dep5, hasLength(5)); // dart:core, a.dart, aa.dart, ab.dart, b.dart
|
| + expect(dep6, hasLength(5)); // dart:core, a.dart, aa.dart, ab.dart, b.dart
|
| + expect(dep7, hasLength(5)); // dart:core, a.dart, aa.dart, ab.dart, b.dart
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ContainingLibrariesTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_definingCompilationUnit() {
|
| + AnalysisTarget library = newSource('/test.dart', 'library test;');
|
| + computeResult(library, INCLUDED_PARTS);
|
| + computeResult(library, CONTAINING_LIBRARIES,
|
| + matcher: isContainingLibrariesTask);
|
| + expect(outputs, hasLength(1));
|
| + List<Source> containingLibraries = outputs[CONTAINING_LIBRARIES];
|
| + expect(containingLibraries, unorderedEquals([library]));
|
| + }
|
| +
|
| + test_perform_partInMultipleLibraries() {
|
| + AnalysisTarget library1 =
|
| + newSource('/lib1.dart', 'library test; part "part.dart";');
|
| + AnalysisTarget library2 =
|
| + newSource('/lib2.dart', 'library test; part "part.dart";');
|
| + AnalysisTarget part = newSource('/part.dart', 'part of test;');
|
| + computeResult(library1, INCLUDED_PARTS);
|
| + computeResult(library2, INCLUDED_PARTS);
|
| + computeResult(part, SOURCE_KIND);
|
| + computeResult(part, CONTAINING_LIBRARIES,
|
| + matcher: isContainingLibrariesTask);
|
| + expect(outputs, hasLength(1));
|
| + List<Source> containingLibraries = outputs[CONTAINING_LIBRARIES];
|
| + expect(containingLibraries, unorderedEquals([library1, library2]));
|
| + }
|
| +
|
| + test_perform_partInSingleLibrary() {
|
| + AnalysisTarget library =
|
| + newSource('/lib.dart', 'library test; part "part.dart";');
|
| + AnalysisTarget part = newSource('/part.dart', 'part of test;');
|
| + computeResult(library, INCLUDED_PARTS);
|
| + computeResult(part, SOURCE_KIND);
|
| + computeResult(part, CONTAINING_LIBRARIES,
|
| + matcher: isContainingLibrariesTask);
|
| + expect(outputs, hasLength(1));
|
| + List<Source> containingLibraries = outputs[CONTAINING_LIBRARIES];
|
| + expect(containingLibraries, unorderedEquals([library]));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class DartErrorsTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_definingCompilationUnit() {
|
| + AnalysisTarget library =
|
| + newSource('/test.dart', 'library test; import "dart:math";');
|
| + computeResult(library, INCLUDED_PARTS);
|
| + computeResult(library, DART_ERRORS, matcher: isDartErrorsTask);
|
| + expect(outputs, hasLength(1));
|
| + List<AnalysisError> errors = outputs[DART_ERRORS];
|
| + expect(errors, hasLength(1));
|
| + }
|
| +
|
| + test_perform_partInSingleLibrary() {
|
| + AnalysisTarget library = newSource(
|
| + '/lib.dart', 'library test; import "dart:math"; part "part.dart";');
|
| + AnalysisTarget part =
|
| + newSource('/part.dart', 'part of test; class A extends A {}');
|
| + computeResult(library, INCLUDED_PARTS);
|
| + computeResult(library, DART_ERRORS);
|
| + computeResult(part, DART_ERRORS, matcher: isDartErrorsTask);
|
| + expect(outputs, hasLength(1));
|
| + List<AnalysisError> errors = outputs[DART_ERRORS];
|
| + // This should contain only the errors in the part file, not the ones in the
|
| + // library.
|
| + expect(errors, hasLength(1));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class EvaluateUnitConstantsTaskTest extends _AbstractDartTaskTest {
|
| + test_perform() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +class C {
|
| + const C();
|
| +}
|
| +
|
| +@x
|
| +f() {}
|
| +
|
| +const x = const C();
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, RESOLVED_UNIT, matcher: isEvaluateUnitConstantsTask);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT];
|
| + CompilationUnitElement unitElement = unit.element;
|
| + expect(
|
| + (unitElement.types[0].constructors[0] as ConstructorElementImpl)
|
| + .isCycleFree,
|
| + isTrue);
|
| + expect(
|
| + (unitElement.functions[0].metadata[0] as ElementAnnotationImpl)
|
| + .evaluationResult,
|
| + isNotNull);
|
| + expect(
|
| + (unitElement.topLevelVariables[0] as TopLevelVariableElementImpl)
|
| + .evaluationResult,
|
| + isNotNull);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class GatherUsedImportedElementsTaskTest extends _AbstractDartTaskTest {
|
| + UsedImportedElements usedElements;
|
| + Set<String> usedElementNames;
|
| +
|
| + test_perform() {
|
| + newSource(
|
| + '/a.dart',
|
| + r'''
|
| +library lib_a;
|
| +class A {}
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + r'''
|
| +library lib_b;
|
| +class B {}
|
| +''');
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + r'''
|
| +import 'a.dart';
|
| +import 'b.dart';
|
| +main() {
|
| + new A();
|
| +}''');
|
| + _computeUsedElements(source);
|
| + // validate
|
| + expect(usedElementNames, unorderedEquals(['A']));
|
| + }
|
| +
|
| + void _computeUsedElements(Source source) {
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, USED_IMPORTED_ELEMENTS,
|
| + matcher: isGatherUsedImportedElementsTask);
|
| + usedElements = outputs[USED_IMPORTED_ELEMENTS];
|
| + usedElementNames = usedElements.elements.map((e) => e.name).toSet();
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class GatherUsedLocalElementsTaskTest extends _AbstractDartTaskTest {
|
| + UsedLocalElements usedElements;
|
| + Set<String> usedElementNames;
|
| +
|
| + fail_perform_forPart_afterLibraryUpdate() {
|
| + Source libSource = newSource(
|
| + '/my_lib.dart',
|
| + '''
|
| +library my_lib;
|
| +part 'my_part.dart';
|
| +foo() => null;
|
| +class _LocalClass {}
|
| +''');
|
| + Source partSource = newSource(
|
| + '/my_part.dart',
|
| + '''
|
| +part of my_lib;
|
| +bar() {
|
| + print(_LocalClass);
|
| +}
|
| +''');
|
| + AnalysisTarget libTarget = new LibrarySpecificUnit(libSource, libSource);
|
| + AnalysisTarget partTarget = new LibrarySpecificUnit(libSource, partSource);
|
| + computeResult(libTarget, USED_LOCAL_ELEMENTS);
|
| + computeResult(partTarget, USED_LOCAL_ELEMENTS);
|
| + // _LocalClass is used in my_part.dart
|
| + {
|
| + UsedLocalElements usedElements =
|
| + analysisCache.getValue(partTarget, USED_LOCAL_ELEMENTS);
|
| + expect(usedElements.elements, contains(predicate((Element e) {
|
| + return e.displayName == '_LocalClass';
|
| + })));
|
| + }
|
| + // change my_lib.dart and recompute
|
| + context.setContents(
|
| + libSource,
|
| + '''
|
| +library my_lib;
|
| +part 'my_part.dart';
|
| +String foo() => null;
|
| +class _LocalClass {}
|
| +''');
|
| + computeResult(libTarget, USED_LOCAL_ELEMENTS);
|
| + computeResult(partTarget, USED_LOCAL_ELEMENTS);
|
| + // _LocalClass should still be used in my_part.dart
|
| + {
|
| + UsedLocalElements usedElements =
|
| + analysisCache.getValue(partTarget, USED_LOCAL_ELEMENTS);
|
| + expect(usedElements.elements, contains(predicate((Element e) {
|
| + return e.displayName == '_LocalClass';
|
| + })));
|
| + }
|
| + }
|
| +
|
| + test_perform_localVariable() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + r'''
|
| +main() {
|
| + var v1 = 1;
|
| + var v2 = 2;
|
| + print(v2);
|
| +}''');
|
| + _computeUsedElements(source);
|
| + // validate
|
| + expect(usedElementNames, unorderedEquals(['v2']));
|
| + }
|
| +
|
| + test_perform_method() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + r'''
|
| +class A {
|
| + _m1() {}
|
| + _m2() {}
|
| +}
|
| +
|
| +main(A a, p) {
|
| + a._m2();
|
| + p._m3();
|
| +}
|
| +''');
|
| + _computeUsedElements(source);
|
| + // validate
|
| + expect(usedElementNames, unorderedEquals(['A', 'a', 'p', '_m2']));
|
| + expect(usedElements.members, unorderedEquals(['_m2', '_m3']));
|
| + }
|
| +
|
| + void _computeUsedElements(Source source) {
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, USED_LOCAL_ELEMENTS,
|
| + matcher: isGatherUsedLocalElementsTask);
|
| + usedElements = outputs[USED_LOCAL_ELEMENTS];
|
| + usedElementNames = usedElements.elements.map((e) => e.name).toSet();
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class GenerateHintsTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_bestPractices_missingReturn() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +int main() {
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.MISSING_RETURN]);
|
| + }
|
| +
|
| + test_perform_dart2js() {
|
| + AnalysisOptionsImpl options = new AnalysisOptionsImpl();
|
| + options.dart2jsHint = true;
|
| + prepareAnalysisContext(options);
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +main(p) {
|
| + if (p is double) {
|
| + print('double');
|
| + }
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.IS_DOUBLE]);
|
| + }
|
| +
|
| + test_perform_deadCode() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +main() {
|
| + if (false) {
|
| + print('how?');
|
| + }
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.DEAD_CODE]);
|
| + }
|
| +
|
| + test_perform_disabled() {
|
| + context.analysisOptions =
|
| + new AnalysisOptionsImpl.from(context.analysisOptions)..hint = false;
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +int main() {
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertNoErrors();
|
| + }
|
| +
|
| + test_perform_imports_duplicateImport() {
|
| + newSource(
|
| + '/a.dart',
|
| + r'''
|
| +library lib_a;
|
| +class A {}
|
| +''');
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + r'''
|
| +import 'a.dart';
|
| +import 'a.dart';
|
| +main() {
|
| + new A();
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.DUPLICATE_IMPORT]);
|
| + }
|
| +
|
| + test_perform_imports_unusedImport_one() {
|
| + newSource(
|
| + '/a.dart',
|
| + r'''
|
| +library lib_a;
|
| +class A {}
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + r'''
|
| +library lib_b;
|
| +class B {}
|
| +''');
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + r'''
|
| +import 'a.dart';
|
| +import 'b.dart';
|
| +main() {
|
| + new A();
|
| +}''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.UNUSED_IMPORT]);
|
| + }
|
| +
|
| + test_perform_imports_unusedImport_zero() {
|
| + newSource(
|
| + '/a.dart',
|
| + r'''
|
| +library lib_a;
|
| +class A {}
|
| +''');
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + r'''
|
| +import 'a.dart';
|
| +main() {
|
| + new A();
|
| +}''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertNoErrors();
|
| + }
|
| +
|
| + test_perform_overrideVerifier() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +class A {}
|
| +class B {
|
| + @override
|
| + m() {}
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(
|
| + <ErrorCode>[HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD]);
|
| + }
|
| +
|
| + test_perform_todo() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +main() {
|
| + // TODO(developer) foo bar
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[TodoCode.TODO]);
|
| + }
|
| +
|
| + test_perform_unusedLocalElements_class() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +class _A {}
|
| +class _B {}
|
| +main() {
|
| + new _A();
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[HintCode.UNUSED_ELEMENT]);
|
| + }
|
| +
|
| + test_perform_unusedLocalElements_localVariable() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +main() {
|
| + var v = 42;
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener
|
| + .assertErrorsWithCodes(<ErrorCode>[HintCode.UNUSED_LOCAL_VARIABLE]);
|
| + }
|
| +
|
| + test_perform_unusedLocalElements_method() {
|
| + Source source = newSource(
|
| + '/my_lib.dart',
|
| + '''
|
| +library my_lib;
|
| +part 'my_part.dart';
|
| +class A {
|
| + _ma() {}
|
| + _mb() {}
|
| + _mc() {}
|
| +}
|
| +''');
|
| + newSource(
|
| + '/my_part.dart',
|
| + '''
|
| +part of my_lib;
|
| +
|
| +f(A a) {
|
| + a._mb();
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, HINTS, matcher: isGenerateHintsTask);
|
| + // validate
|
| + _fillErrorListener(HINTS);
|
| + errorListener.assertErrorsWithCodes(
|
| + <ErrorCode>[HintCode.UNUSED_ELEMENT, HintCode.UNUSED_ELEMENT]);
|
| + }
|
| +}
|
| +
|
| +@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();
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +class A {
|
| + X f;
|
| + Y m(Z x) {}
|
| +}
|
| +class B extends A {
|
| + var f;
|
| + m(x) {}
|
| +}
|
| +class X {}
|
| +class Y {}
|
| +class Z {}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT8,
|
| + matcher: isInferInstanceMembersInUnitTask);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT8];
|
| + VariableDeclaration field = getFieldInClass(unit, 'B', 'f');
|
| + MethodDeclaration method = getMethodInClass(unit, 'B', 'm');
|
| + DartType typeX = getClass(unit, 'X').element.type;
|
| + DartType typeY = getClass(unit, 'Y').element.type;
|
| + DartType typeZ = getClass(unit, 'Z').element.type;
|
| +
|
| + expect(field.element.type, typeX);
|
| + expect(method.element.returnType, typeY);
|
| + expect(method.element.parameters[0].type, typeZ);
|
| + }
|
| +
|
| + void test_perform_cross_library_const() {
|
| + enableStrongMode();
|
| + AnalysisTarget firstSource = newSource(
|
| + '/first.dart',
|
| + '''
|
| +library first;
|
| +
|
| +const a = 'hello';
|
| +''');
|
| + AnalysisTarget secondSource = newSource(
|
| + '/second.dart',
|
| + '''
|
| +import 'first.dart';
|
| +
|
| +const b = a;
|
| +class M {
|
| + String c = a;
|
| +}
|
| +''');
|
| + computeResult(
|
| + new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT8,
|
| + matcher: isInferInstanceMembersInUnitTask);
|
| + CompilationUnit firstUnit = outputs[RESOLVED_UNIT8];
|
| + computeResult(
|
| + new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT8);
|
| + CompilationUnit secondUnit = outputs[RESOLVED_UNIT8];
|
| +
|
| + VariableDeclaration variableA = getTopLevelVariable(firstUnit, 'a');
|
| + VariableDeclaration variableB = getTopLevelVariable(secondUnit, 'b');
|
| + VariableDeclaration variableC = getFieldInClass(secondUnit, 'M', 'c');
|
| + InterfaceType stringType = context.typeProvider.stringType;
|
| +
|
| + expect(variableA.element.type, stringType);
|
| + expect(variableB.element.type, stringType);
|
| + expect(variableB.initializer.staticType, stringType);
|
| + expect(variableC.element.type, stringType);
|
| + expect(variableC.initializer.staticType, stringType);
|
| + }
|
| +
|
| + void test_perform_reresolution() {
|
| + enableStrongMode();
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const topLevel = '';
|
| +class C {
|
| + String field = topLevel;
|
| +}
|
| +''');
|
| + 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;
|
| + VariableElement field = fieldDecl.name.staticElement;
|
| +
|
| + InterfaceType stringType = context.typeProvider.stringType;
|
| + expect(topLevel.type, stringType);
|
| + expect(field.type, stringType);
|
| + expect(fieldDecl.initializer.staticType, stringType);
|
| + }
|
| +}
|
| +
|
| +@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(
|
| + '/test.dart',
|
| + '''
|
| +var f = (int x) {
|
| + int squared(int value) => value * value;
|
| + var xSquared = squared(x);
|
| + return xSquared;
|
| +};
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6,
|
| + matcher: isInferStaticVariableTypesInUnitTask);
|
| + }
|
| +
|
| + void test_perform_recursive() {
|
| + enableStrongMode();
|
| + AnalysisTarget firstSource = newSource(
|
| + '/first.dart',
|
| + '''
|
| +import 'second.dart';
|
| +
|
| +var a = new M();
|
| +var c = b;
|
| +''');
|
| + AnalysisTarget secondSource = newSource(
|
| + '/second.dart',
|
| + '''
|
| +import 'first.dart';
|
| +
|
| +var b = a;
|
| +class M {}
|
| +''');
|
| + computeResult(
|
| + new LibrarySpecificUnit(firstSource, firstSource), RESOLVED_UNIT6,
|
| + matcher: isInferStaticVariableTypesInUnitTask);
|
| + CompilationUnit firstUnit = outputs[RESOLVED_UNIT6];
|
| + computeResult(
|
| + new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT6);
|
| + CompilationUnit secondUnit = outputs[RESOLVED_UNIT6];
|
| +
|
| + VariableDeclaration variableA = getTopLevelVariable(firstUnit, 'a');
|
| + VariableDeclaration variableB = getTopLevelVariable(secondUnit, 'b');
|
| + VariableDeclaration variableC = getTopLevelVariable(firstUnit, 'c');
|
| + ClassDeclaration classM = getClass(secondUnit, 'M');
|
| + DartType typeM = classM.element.type;
|
| +
|
| + expect(variableA.element.type, typeM);
|
| + expect(variableB.element.type, typeM);
|
| + expect(variableB.initializer.staticType, typeM);
|
| + expect(variableC.element.type, typeM);
|
| + expect(variableC.initializer.staticType, typeM);
|
| + }
|
| +
|
| + void test_perform_simple() {
|
| + enableStrongMode();
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +var X = 1;
|
| +
|
| +var Y = () {
|
| + return 1 + X;
|
| +};
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT6,
|
| + matcher: isInferStaticVariableTypesInUnitTask);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT6];
|
| + TopLevelVariableDeclaration declaration = unit.declarations[1];
|
| + FunctionExpression function =
|
| + declaration.variables.variables[0].initializer;
|
| + BlockFunctionBody body = function.body;
|
| + ReturnStatement statement = body.block.statements[0];
|
| + Expression expression = statement.expression;
|
| + InterfaceType intType = context.typeProvider.intType;
|
| + expect(expression.staticType, intType);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class InferStaticVariableTypeTaskTest extends _AbstractDartTaskTest {
|
| + void test_getDeclaration_staticField() {
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +class C {
|
| + var field = '';
|
| +}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + VariableDeclaration declaration = getFieldInClass(unit, 'C', 'field');
|
| + VariableElement variable = declaration.name.staticElement;
|
| + InferStaticVariableTypeTask inferTask =
|
| + new InferStaticVariableTypeTask(task.context, variable);
|
| + expect(inferTask.getDeclaration(unit), declaration);
|
| + }
|
| +
|
| + void test_getDeclaration_topLevel() {
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +var topLevel = '';
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + VariableDeclaration declaration = getTopLevelVariable(unit, 'topLevel');
|
| + VariableElement variable = declaration.name.staticElement;
|
| + InferStaticVariableTypeTask inferTask =
|
| + new InferStaticVariableTypeTask(task.context, variable);
|
| + expect(inferTask.getDeclaration(unit), declaration);
|
| + }
|
| +
|
| + void test_perform() {
|
| + enableStrongMode();
|
| + AnalysisTarget source = newSource(
|
| + '/test3.dart',
|
| + '''
|
| +var topLevel3 = '';
|
| +class C {
|
| + var field3 = topLevel3;
|
| +}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + VariableDeclaration topLevelDecl = getTopLevelVariable(unit, 'topLevel3');
|
| + VariableDeclaration fieldDecl = getFieldInClass(unit, 'C', 'field3');
|
| + 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);
|
| + }
|
| +
|
| + void test_perform_const() {
|
| + enableStrongMode();
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const topLevel = "hello";
|
| +class C {
|
| + var field = topLevel;
|
| +}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + VariableElement topLevel =
|
| + getTopLevelVariable(unit, 'topLevel').name.staticElement;
|
| + VariableElement field =
|
| + getFieldInClass(unit, 'C', 'field').name.staticElement;
|
| +
|
| + computeResult(field, INFERRED_STATIC_VARIABLE,
|
| + matcher: isInferStaticVariableTypeTask);
|
| + InterfaceType stringType = context.typeProvider.stringType;
|
| + expect(topLevel.type, stringType);
|
| + expect(field.type, stringType);
|
| + }
|
| +
|
| + void test_perform_cycle() {
|
| + enableStrongMode();
|
| + 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_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + VariableElement piFirst =
|
| + getTopLevelVariable(unit, 'piFirst').name.staticElement;
|
| + VariableElement pi = getTopLevelVariable(unit, 'pi').name.staticElement;
|
| + VariableElement tau = getTopLevelVariable(unit, 'tau').name.staticElement;
|
| +
|
| + computeResult(piFirst, INFERRED_STATIC_VARIABLE,
|
| + matcher: isInferStaticVariableTypeTask);
|
| + expect(piFirst.type, context.typeProvider.boolType);
|
| + expect(pi.type.isDynamic, isTrue);
|
| + expect(tau.type.isDynamic, isTrue);
|
| + }
|
| +
|
| + void test_perform_error() {
|
| + enableStrongMode();
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +var a = '' / null;
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + VariableElement a = getTopLevelVariable(unit, 'a').name.staticElement;
|
| +
|
| + computeResult(a, INFERRED_STATIC_VARIABLE,
|
| + matcher: isInferStaticVariableTypeTask);
|
| + expect(a.type.isDynamic, isTrue);
|
| + }
|
| +
|
| + void test_perform_null() {
|
| + enableStrongMode();
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +var a = null;
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT5);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + VariableElement a = getTopLevelVariable(unit, 'a').name.staticElement;
|
| +
|
| + computeResult(a, INFERRED_STATIC_VARIABLE,
|
| + matcher: isInferStaticVariableTypeTask);
|
| + expect(a.type.isDynamic, isTrue);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class LibraryErrorsReadyTaskTest extends _AbstractDartTaskTest {
|
| + test_perform() {
|
| + Source library = newSource(
|
| + '/lib.dart',
|
| + r'''
|
| +library lib;
|
| +part 'part1.dart';
|
| +part 'part2.dart';
|
| +X v1;
|
| +''');
|
| + Source part1 = newSource(
|
| + '/part1.dart',
|
| + r'''
|
| +part of lib;
|
| +X v2;
|
| +''');
|
| + Source part2 = newSource(
|
| + '/part2.dart',
|
| + r'''
|
| +part of lib;
|
| +X v3;
|
| +''');
|
| + computeResult(library, LIBRARY_ERRORS_READY,
|
| + matcher: isLibraryErrorsReadyTask);
|
| + expect(outputs, hasLength(1));
|
| + bool ready = outputs[LIBRARY_ERRORS_READY];
|
| + expect(ready, isTrue);
|
| + expect(context.getErrors(library).errors, hasLength(1));
|
| + expect(context.getErrors(part1).errors, hasLength(1));
|
| + expect(context.getErrors(part2).errors, hasLength(1));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class LibraryUnitErrorsTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_definingCompilationUnit() {
|
| + AnalysisTarget library =
|
| + newSource('/test.dart', 'library test; import "dart:math";');
|
| + computeResult(
|
| + new LibrarySpecificUnit(library, library), LIBRARY_UNIT_ERRORS,
|
| + matcher: isLibraryUnitErrorsTask);
|
| + expect(outputs, hasLength(1));
|
| + List<AnalysisError> errors = outputs[LIBRARY_UNIT_ERRORS];
|
| + expect(errors, hasLength(1));
|
| + }
|
| +
|
| + test_perform_partInSingleLibrary() {
|
| + AnalysisTarget library =
|
| + newSource('/lib.dart', 'library test; part "part.dart";');
|
| + AnalysisTarget part = newSource('/part.dart', 'part of test;');
|
| + computeResult(new LibrarySpecificUnit(library, part), LIBRARY_UNIT_ERRORS,
|
| + matcher: isLibraryUnitErrorsTask);
|
| + expect(outputs, hasLength(1));
|
| + List<AnalysisError> errors = outputs[LIBRARY_UNIT_ERRORS];
|
| + expect(errors, hasLength(0));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ParseDartTaskTest extends _AbstractDartTaskTest {
|
| + Source source;
|
| +
|
| + test_perform() {
|
| + _performParseTask(r'''
|
| +part of lib;
|
| +class B {}''');
|
| + expect(outputs, hasLength(8));
|
| + expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
|
| + expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
|
| + _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
|
| + expect(outputs[INCLUDED_PARTS], hasLength(0));
|
| + expect(outputs[PARSE_ERRORS], hasLength(0));
|
| + expect(outputs[PARSED_UNIT], isNotNull);
|
| + expect(outputs[SOURCE_KIND], SourceKind.PART);
|
| + expect(outputs[UNITS], hasLength(1));
|
| + }
|
| +
|
| + test_perform_computeSourceKind_noDirectives_hasContainingLibrary() {
|
| + // Parse "lib.dart" to let the context know that "test.dart" is included.
|
| + computeResult(
|
| + newSource(
|
| + '/lib.dart',
|
| + r'''
|
| +library lib;
|
| +part 'test.dart';
|
| +'''),
|
| + PARSED_UNIT);
|
| + // If there are no the "part of" directive, then it is not a part.
|
| + _performParseTask('');
|
| + expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
|
| + }
|
| +
|
| + test_perform_computeSourceKind_noDirectives_noContainingLibrary() {
|
| + _performParseTask('');
|
| + expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
|
| + }
|
| +
|
| + test_perform_doesNotExist() {
|
| + _performParseTask(null);
|
| + expect(outputs, hasLength(8));
|
| + expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
|
| + expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
|
| + _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
|
| + expect(outputs[INCLUDED_PARTS], hasLength(0));
|
| + expect(outputs[PARSE_ERRORS], hasLength(0));
|
| + expect(outputs[PARSED_UNIT], isNotNull);
|
| + expect(outputs[SOURCE_KIND], SourceKind.UNKNOWN);
|
| + expect(outputs[UNITS], hasLength(1));
|
| + }
|
| +
|
| + test_perform_invalidDirectives() {
|
| + _performParseTask(r'''
|
| +library lib;
|
| +import '/does/not/exist.dart';
|
| +import '://invaliduri.dart';
|
| +export '${a}lib3.dart';
|
| +part 'part.dart';
|
| +class A {}''');
|
| + expect(outputs, hasLength(8));
|
| + expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
|
| + expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
|
| + _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
|
| + expect(outputs[INCLUDED_PARTS], hasLength(1));
|
| + expect(outputs[PARSE_ERRORS], hasLength(2));
|
| + expect(outputs[PARSED_UNIT], isNotNull);
|
| + expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
|
| + expect(outputs[UNITS], hasLength(2));
|
| + }
|
| +
|
| + test_perform_library() {
|
| + _performParseTask(r'''
|
| +library lib;
|
| +import 'lib2.dart';
|
| +export 'lib3.dart';
|
| +part 'part.dart';
|
| +class A {''');
|
| + expect(outputs, hasLength(8));
|
| + expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(1));
|
| + expect(outputs[EXPORTED_LIBRARIES], hasLength(1));
|
| + _assertHasCore(outputs[IMPORTED_LIBRARIES], 2);
|
| + expect(outputs[INCLUDED_PARTS], hasLength(1));
|
| + expect(outputs[PARSE_ERRORS], hasLength(1));
|
| + expect(outputs[PARSED_UNIT], isNotNull);
|
| + expect(outputs[SOURCE_KIND], SourceKind.LIBRARY);
|
| + expect(outputs[UNITS], hasLength(2));
|
| + }
|
| +
|
| + test_perform_library_selfReferenceAsPart() {
|
| + _performParseTask(r'''
|
| +library lib;
|
| +part 'test.dart';
|
| +''');
|
| + expect(outputs[INCLUDED_PARTS], unorderedEquals(<Source>[source]));
|
| + }
|
| +
|
| + test_perform_part() {
|
| + _performParseTask(r'''
|
| +part of lib;
|
| +class B {}''');
|
| + expect(outputs, hasLength(8));
|
| + expect(outputs[EXPLICITLY_IMPORTED_LIBRARIES], hasLength(0));
|
| + expect(outputs[EXPORTED_LIBRARIES], hasLength(0));
|
| + _assertHasCore(outputs[IMPORTED_LIBRARIES], 1);
|
| + expect(outputs[INCLUDED_PARTS], hasLength(0));
|
| + expect(outputs[PARSE_ERRORS], hasLength(0));
|
| + expect(outputs[PARSED_UNIT], isNotNull);
|
| + expect(outputs[SOURCE_KIND], SourceKind.PART);
|
| + expect(outputs[UNITS], hasLength(1));
|
| + }
|
| +
|
| + void _performParseTask(String content) {
|
| + source = newSource('/test.dart', content);
|
| + computeResult(source, PARSED_UNIT, matcher: isParseDartTask);
|
| + }
|
| +
|
| + static void _assertHasCore(List<Source> sources, int lenght) {
|
| + expect(sources, hasLength(lenght));
|
| + expect(sources, contains(predicate((Source s) {
|
| + return s.fullName.endsWith('core.dart');
|
| + })));
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class PartiallyResolveUnitReferencesTaskTest extends _AbstractDartTaskTest {
|
| + test_perform() {
|
| + enableStrongMode();
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +int a = b;
|
| +int b = c;
|
| +var d = 0;
|
| +class A {}
|
| +class C {
|
| + static final f = '';
|
| + var g = 0;
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, RESOLVED_UNIT5,
|
| + matcher: isPartiallyResolveUnitReferencesTask);
|
| + // Test the outputs
|
| + 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
|
| + TopLevelVariableDeclaration a = unit.declarations[0];
|
| + VariableDeclaration variableA = a.variables.variables[0];
|
| + SimpleIdentifier initializer = variableA.initializer;
|
| + expect(initializer.staticElement, isNotNull);
|
| + }
|
| +
|
| + test_perform_importExport() {
|
| + newSource(
|
| + '/a.dart',
|
| + '''
|
| +library a;
|
| +class A<T> {
|
| + T m() {}
|
| +}
|
| +''');
|
| + newSource(
|
| + '/b.dart',
|
| + '''
|
| +library b;
|
| +export 'a.dart';
|
| +''');
|
| + Source sourceC = newSource(
|
| + '/c.dart',
|
| + '''
|
| +library c;
|
| +import 'b.dart';
|
| +main() {
|
| + new A<int>().m();
|
| +}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(sourceC, sourceC), RESOLVED_UNIT5,
|
| + matcher: isPartiallyResolveUnitReferencesTask);
|
| + // validate
|
| + expect(outputs[INFERABLE_STATIC_VARIABLES_IN_UNIT], hasLength(0));
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + expect(unit, isNotNull);
|
| +
|
| + FunctionDeclaration mainFunction = unit.declarations[0];
|
| + expect(mainFunction.element, isNotNull);
|
| + BlockFunctionBody body = mainFunction.functionExpression.body;
|
| + List<Statement> statements = body.block.statements;
|
| + ExpressionStatement statement = statements[0];
|
| + MethodInvocation invocation = statement.expression;
|
| + MethodElement methodElement = invocation.methodName.staticElement;
|
| + expect(methodElement, isNull);
|
| + }
|
| +
|
| + test_perform_notResolved() {
|
| + enableStrongMode();
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +int A;
|
| +f1() {
|
| + A;
|
| +}
|
| +var f2 = () {
|
| + A;
|
| + void f3() {
|
| + A;
|
| + }
|
| +}
|
| +class C {
|
| + C() {
|
| + A;
|
| + }
|
| + m() {
|
| + A;
|
| + }
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, RESOLVED_UNIT5,
|
| + matcher: isPartiallyResolveUnitReferencesTask);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT5];
|
| + NodeList<CompilationUnitMember> declarations = unit.declarations;
|
| +
|
| + void expectReference(BlockFunctionBody body, bool isResolved) {
|
| + ExpressionStatement statement = body.block.statements[0];
|
| + SimpleIdentifier reference = statement.expression;
|
| + expect(reference.staticElement, isResolved ? isNotNull : isNull);
|
| + }
|
| + //
|
| + // The reference to 'A' in 'f1' should not be resolved.
|
| + //
|
| + FunctionDeclaration f1 = declarations[1];
|
| + expectReference(f1.functionExpression.body, false);
|
| + //
|
| + // The references to 'A' in 'f2' should be resolved.
|
| + //
|
| + TopLevelVariableDeclaration f2 = declarations[2];
|
| + FunctionExpression expression2 = f2.variables.variables[0].initializer;
|
| + BlockFunctionBody body2 = expression2.body;
|
| + expectReference(body2, true);
|
| +
|
| + FunctionDeclarationStatement statement2 = body2.block.statements[1];
|
| + BlockFunctionBody innerBody =
|
| + statement2.functionDeclaration.functionExpression.body;
|
| + expectReference(innerBody, true);
|
| + //
|
| + // The references to 'A' in 'C' should not be resolved.
|
| + //
|
| + ClassDeclaration c = declarations[3];
|
| + NodeList<ClassMember> members = c.members;
|
| +
|
| + ConstructorDeclaration constructor = members[0];
|
| + expectReference(constructor.body, false);
|
| +
|
| + MethodDeclaration method = members[1];
|
| + expectReference(method.body, false);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ResolveInstanceFieldsInUnitTaskTest extends _AbstractDartTaskTest {
|
| + @override
|
| + void setUp() {
|
| + super.setUp();
|
| + enableStrongMode();
|
| + }
|
| +
|
| + // Test inference of instance fields across units
|
| + void test_perform_inference_cross_unit_instance() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| + import 'b.dart';
|
| + class A {
|
| + final a2 = new B().b2;
|
| + }
|
| + ''',
|
| + '/b.dart': '''
|
| + class B {
|
| + final b2 = 1;
|
| + }
|
| + ''',
|
| + '/main.dart': '''
|
| + import "a.dart";
|
| +
|
| + test1() {
|
| + int x = 0;
|
| + x = new A().a2;
|
| + }
|
| + '''
|
| + });
|
| + InterfaceType intType = context.typeProvider.intType;
|
| + DartType dynamicType = context.typeProvider.dynamicType;
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT7);
|
| + CompilationUnit unit1 = outputs[RESOLVED_UNIT7];
|
| +
|
| + // B.b2 shoud be resolved on the rhs, but not yet inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b2"), dynamicType, intType);
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT7);
|
| + CompilationUnit unit0 = outputs[RESOLVED_UNIT7];
|
| +
|
| + // B.b2 should now be fully resolved and inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b2"), intType, intType);
|
| +
|
| + // A.a2 should now be resolved on the rhs, but not yet inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), dynamicType, intType);
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT7);
|
| + CompilationUnit unit2 = outputs[RESOLVED_UNIT7];
|
| +
|
| + // A.a2 should now be fully resolved and inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), intType, intType);
|
| +
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b2"), intType, intType);
|
| + }
|
| +
|
| + // Test inference of instance fields across units
|
| + void test_perform_inference_cross_unit_instance_cyclic() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| + import 'b.dart';
|
| + class A {
|
| + final a2 = new B().b2;
|
| + }
|
| + ''',
|
| + '/b.dart': '''
|
| + import 'a.dart';
|
| + class B {
|
| + final b2 = 1;
|
| + }
|
| + ''',
|
| + '/main.dart': '''
|
| + import "a.dart";
|
| +
|
| + test1() {
|
| + int x = 0;
|
| + x = new A().a2;
|
| + }
|
| + '''
|
| + });
|
| + InterfaceType intType = context.typeProvider.intType;
|
| + DartType dynamicType = context.typeProvider.dynamicType;
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT7);
|
| + CompilationUnit unit0 = outputs[RESOLVED_UNIT7];
|
| +
|
| + // A.a2 should now be resolved on the rhs, but not yet inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT7);
|
| + CompilationUnit unit2 = outputs[RESOLVED_UNIT7];
|
| +
|
| + // A.a2 should now be fully resolved and inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
|
| + }
|
| +
|
| + // Test inference of instance fields across units with cycles
|
| + void test_perform_inference_cross_unit_static_instance() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| + import 'b.dart';
|
| + class A {
|
| + static final a1 = B.b1;
|
| + final a2 = new B().b2;
|
| + }
|
| + ''',
|
| + '/b.dart': '''
|
| + class B {
|
| + static final b1 = 1;
|
| + final b2 = 1;
|
| + }
|
| + ''',
|
| + '/main.dart': '''
|
| + import "a.dart";
|
| +
|
| + test1() {
|
| + int x = 0;
|
| + // inference in A now works.
|
| + x = A.a1;
|
| + x = new A().a2;
|
| + }
|
| + '''
|
| + });
|
| + InterfaceType intType = context.typeProvider.intType;
|
| + DartType dynamicType = context.typeProvider.dynamicType;
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT7);
|
| + CompilationUnit unit1 = outputs[RESOLVED_UNIT7];
|
| +
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b1"), intType, intType);
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b2"), dynamicType, intType);
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT7);
|
| + CompilationUnit unit0 = outputs[RESOLVED_UNIT7];
|
| +
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a1"), intType, intType);
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), dynamicType, intType);
|
| +
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b1"), intType, intType);
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b2"), intType, intType);
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[2], sources[2]), RESOLVED_UNIT7);
|
| + CompilationUnit unit2 = outputs[RESOLVED_UNIT7];
|
| +
|
| + assertVariableDeclarationTypes(
|
| + 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);
|
| + }
|
| +
|
| + // Test inference between static and instance fields
|
| + void test_perform_inference_instance() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| + import 'b.dart';
|
| + class A {
|
| + final a2 = new B().b2;
|
| + }
|
| +
|
| + class B {
|
| + final b2 = 1;
|
| + }
|
| + ''',
|
| + '/main.dart': '''
|
| + import "a.dart";
|
| +
|
| + test1() {
|
| + int x = 0;
|
| + x = new A().a2;
|
| + }
|
| + '''
|
| + });
|
| + InterfaceType intType = context.typeProvider.intType;
|
| + DartType dynamicType = context.typeProvider.dynamicType;
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[0], sources[0]), RESOLVED_UNIT7);
|
| + CompilationUnit unit0 = outputs[RESOLVED_UNIT7];
|
| +
|
| + // A.a2 should now be resolved on the rhs, but not yet inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
|
| +
|
| + // B.b2 shoud be resolved on the rhs, but not yet inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "B", "b2"), dynamicType, intType);
|
| +
|
| + computeResult(
|
| + new LibrarySpecificUnit(sources[1], sources[1]), RESOLVED_UNIT7);
|
| + CompilationUnit unit1 = outputs[RESOLVED_UNIT7];
|
| +
|
| + // A.a2 should now be fully resolved and inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), dynamicType, dynamicType);
|
| +
|
| + // B.b2 should now be fully resolved and inferred.
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "B", "b2"), intType, intType);
|
| + }
|
| +}
|
| +
|
| +@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',
|
| + '''
|
| +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');
|
| + }
|
| + }
|
| +
|
| + 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');
|
| + }
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ResolveUnitTaskTest extends _AbstractDartTaskTest {
|
| + void test_perform() {
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +void f() {
|
| + var c = new C();
|
| + c.m();
|
| +}
|
| +class C {
|
| + void m() {
|
| + f();
|
| + }
|
| +}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9,
|
| + matcher: isResolveUnitTask);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT9];
|
| +
|
| + FunctionDeclaration f = unit.declarations[0];
|
| + _assertResolved(f.functionExpression.body);
|
| +
|
| + MethodDeclaration m = (unit.declarations[1] as ClassDeclaration).members[0];
|
| + _assertResolved(m.body);
|
| +
|
| + expect(outputs[RESOLVE_UNIT_ERRORS], hasLength(0));
|
| + }
|
| +
|
| + void _assertResolved(FunctionBody body) {
|
| + ResolutionVerifier verifier = new ResolutionVerifier();
|
| + body.accept(verifier);
|
| + verifier.assertResolved();
|
| + }
|
| +}
|
| +
|
| +@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');
|
| + }
|
| + }
|
| +
|
| + 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]);
|
| + }
|
| +
|
| + test_perform_typedef() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +typedef int F(G g);
|
| +typedef String G(int p);
|
| +''');
|
| + 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_perform_typedef_errors() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +typedef int F(NoSuchType p);
|
| +''');
|
| + 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]);
|
| + }
|
| +}
|
| +
|
| +@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_perform_buildClosureLibraryElements() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +main() {
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, RESOLVED_UNIT4,
|
| + matcher: isResolveVariableReferencesTask);
|
| + }
|
| +
|
| + test_perform_local() {
|
| + Source 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;
|
| + }
|
| +}
|
| +''');
|
| + 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_perform_parameter() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +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);
|
| + }
|
| +}
|
| +
|
| +@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);
|
| + }
|
| +
|
| + 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)]);
|
| +
|
| + 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');
|
| + }
|
| +
|
| + void _performScanTask(String content) {
|
| + AnalysisTarget target = newSource('/test.dart', content);
|
| + computeResult(target, TOKEN_STREAM, matcher: isScanDartTask);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class StrongModeInferenceTest extends _AbstractDartTaskTest {
|
| + @override
|
| + void setUp() {
|
| + super.setUp();
|
| + enableStrongMode();
|
| + }
|
| +
|
| + // 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(
|
| + '/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_UNIT9);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT9];
|
| + 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);
|
| + }
|
| +
|
| + 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_UNIT9);
|
| + CompilationUnit unit1 = outputs[RESOLVED_UNIT9];
|
| + computeResult(
|
| + new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT9);
|
| + CompilationUnit unit2 = outputs[RESOLVED_UNIT9];
|
| +
|
| + 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 that local variables in method bodies are inferred appropriately
|
| + void test_perform_inference_cross_unit_instance() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| + import 'b.dart';
|
| + class A {
|
| + final a2 = new B().b2;
|
| + }
|
| + ''',
|
| + '/b.dart': '''
|
| + class B {
|
| + final b2 = 1;
|
| + }
|
| + ''',
|
| + '/main.dart': '''
|
| + import "a.dart";
|
| +
|
| + test1() {
|
| + int x = 0;
|
| + x = new A().a2;
|
| + }
|
| + '''
|
| + });
|
| + 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;
|
| +
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit0, "A", "a2"), intType, intType);
|
| +
|
| + assertVariableDeclarationTypes(
|
| + getFieldInClass(unit1, "B", "b2"), intType, intType);
|
| +
|
| + List<Statement> statements =
|
| + getStatementsInTopLevelFunction(unit2, "test1");
|
| +
|
| + assertAssignmentStatementTypes(statements[1], intType, intType);
|
| + }
|
| +
|
| + // Test inference interactions between local variables and fields
|
| + 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);
|
| + }
|
| +
|
| + // 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_UNIT9);
|
| + CompilationUnit unit1 = outputs[RESOLVED_UNIT9];
|
| + computeResult(
|
| + new LibrarySpecificUnit(secondSource, secondSource), RESOLVED_UNIT9);
|
| + CompilationUnit unit2 = outputs[RESOLVED_UNIT9];
|
| +
|
| + 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");
|
| +
|
| + assertAssignmentStatementTypes(statements[0], intType, stringType);
|
| + assertAssignmentStatementTypes(statements[1], intType, stringType);
|
| + }
|
| +
|
| + // Test that inference does not propagate from null
|
| + void test_perform_inference_cross_unit_static_instance() {
|
| + List<Source> sources = newSources({
|
| + '/a.dart': '''
|
| + import 'b.dart';
|
| + class A {
|
| + static final a1 = B.b1;
|
| + final a2 = new B().b2;
|
| + }
|
| + ''',
|
| + '/b.dart': '''
|
| + class B {
|
| + static final b1 = 1;
|
| + final b2 = 1;
|
| + }
|
| + ''',
|
| + '/main.dart': '''
|
| + import "a.dart";
|
| +
|
| + test1() {
|
| + int x = 0;
|
| + // inference in A now works.
|
| + x = A.a1;
|
| + x = new A().a2;
|
| + }
|
| + '''
|
| + });
|
| + 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;
|
| +
|
| + assertVariableDeclarationTypes(
|
| + 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);
|
| + }
|
| +
|
| + // Test inference across units (non-cyclic)
|
| + void test_perform_inference_local_variables() {
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| + test() {
|
| + int x = 3;
|
| + x = "hi";
|
| + var y = 3;
|
| + y = "hi";
|
| + }
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT9];
|
| +
|
| + 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);
|
| + }
|
| +
|
| + // Test inference across units (cyclic)
|
| + void test_perform_inference_local_variables_fields() {
|
| + AnalysisTarget 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`
|
| + }
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT9];
|
| +
|
| + 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 inference of instance fields across units
|
| + void test_perform_inference_local_variables_topLevel() {
|
| + AnalysisTarget 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`
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT9];
|
| +
|
| + 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);
|
| + }
|
| +
|
| + // Test inference between static and instance fields
|
| + void test_perform_inference_null() {
|
| + AnalysisTarget 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";
|
| + }
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT9];
|
| +
|
| + 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 inference between fields and method bodies
|
| + void test_perform_local_explicit_disabled() {
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| + test() {
|
| + int x = 3;
|
| + x = "hi";
|
| + }
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), RESOLVED_UNIT9);
|
| + CompilationUnit unit = outputs[RESOLVED_UNIT9];
|
| +
|
| + 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);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class VerifyUnitTaskTest extends _AbstractDartTaskTest {
|
| + test_perform_constantError() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +main(int p) {
|
| + const v = p;
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, VERIFY_ERRORS, matcher: isVerifyUnitTask);
|
| + // validate
|
| + _fillErrorListener(VERIFY_ERRORS);
|
| + errorListener.assertErrorsWithCodes(<ErrorCode>[
|
| + CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
| + ]);
|
| + }
|
| +
|
| + test_perform_directiveError() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +import 'no-such-file.dart';
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, VERIFY_ERRORS, matcher: isVerifyUnitTask);
|
| + // validate
|
| + _fillErrorListener(VERIFY_ERRORS);
|
| + errorListener.assertErrorsWithCodes(
|
| + <ErrorCode>[CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
|
| + }
|
| +
|
| + void test_perform_reresolution() {
|
| + enableStrongMode();
|
| + AnalysisTarget source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +const topLevel = 3;
|
| +class C {
|
| + String field = topLevel;
|
| +}
|
| +''');
|
| + computeResult(new LibrarySpecificUnit(source, source), VERIFY_ERRORS);
|
| + // validate
|
| + _fillErrorListener(VERIFY_ERRORS);
|
| + errorListener.assertErrorsWithCodes(
|
| + <ErrorCode>[StaticTypeWarningCode.INVALID_ASSIGNMENT]);
|
| + }
|
| +
|
| + test_perform_verifyError() {
|
| + Source source = newSource(
|
| + '/test.dart',
|
| + '''
|
| +main() {
|
| + if (42) {
|
| + print('Not bool!');
|
| + }
|
| +}
|
| +''');
|
| + LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
|
| + computeResult(target, VERIFY_ERRORS, matcher: isVerifyUnitTask);
|
| + // validate
|
| + _fillErrorListener(VERIFY_ERRORS);
|
| + errorListener.assertErrorsWithCodes(
|
| + <ErrorCode>[StaticTypeWarningCode.NON_BOOL_CONDITION]);
|
| + }
|
| +}
|
| +
|
| +class _AbstractDartTaskTest extends AbstractContextTest {
|
| + Source emptySource;
|
| +
|
| + GatheringErrorListener errorListener = new GatheringErrorListener();
|
| +
|
| + void assertAssignmentStatementTypes(
|
| + Statement stmt, DartType leftType, DartType rightType) {
|
| + AssignmentExpression assgn = (stmt as ExpressionStatement).expression;
|
| + expect(assgn.leftHandSide.staticType, leftType);
|
| + expect(assgn.rightHandSide.staticType, rightType);
|
| + }
|
| +
|
| + void assertIsInvalid(AnalysisTarget target, ResultDescriptor descriptor) {
|
| + CacheEntry entry = context.getCacheEntry(target);
|
| + expect(entry.isInvalid(descriptor), isTrue);
|
| + }
|
| +
|
| + void assertIsValid(AnalysisTarget target, ResultDescriptor descriptor) {
|
| + CacheEntry entry = context.getCacheEntry(target);
|
| + expect(entry.isValid(descriptor), isTrue);
|
| + }
|
| +
|
| + void assertSameResults(List<ResultDescriptor> descriptors) {
|
| + descriptors.forEach((descriptor) {
|
| + var oldResult = oldOutputs[descriptor];
|
| + var newResult = outputs[descriptor];
|
| + expect(newResult, same(oldResult), reason: descriptor.name);
|
| + });
|
| + }
|
| +
|
| + void assertVariableDeclarationStatementTypes(
|
| + Statement stmt, DartType varType, DartType initializerType) {
|
| + VariableDeclaration decl =
|
| + (stmt as VariableDeclarationStatement).variables.variables[0];
|
| + assertVariableDeclarationTypes(decl, varType, initializerType);
|
| + }
|
| +
|
| + void assertVariableDeclarationTypes(
|
| + VariableDeclaration decl, DartType varType, DartType initializerType) {
|
| + expect(decl.element.type, varType);
|
| + expect(decl.initializer.staticType, initializerType);
|
| + }
|
| +
|
| + List<dynamic> computeLibraryResults(
|
| + List<Source> sources, ResultDescriptor result,
|
| + {isInstanceOf matcher: null}) {
|
| + dynamic compute(Source source) {
|
| + computeResult(new LibrarySpecificUnit(source, source), result,
|
| + matcher: matcher);
|
| + return outputs[result];
|
| + }
|
| + return sources.map(compute).toList();
|
| + }
|
| +
|
| + List<Map<ResultDescriptor, dynamic>> computeLibraryResultsMap(
|
| + List<Source> sources, ResultDescriptor result,
|
| + {isInstanceOf matcher: null}) {
|
| + Map<ResultDescriptor, dynamic> compute(Source source) {
|
| + computeResult(new LibrarySpecificUnit(source, source), result,
|
| + matcher: matcher);
|
| + return outputs;
|
| + }
|
| + return sources.map(compute).toList();
|
| + }
|
| +
|
| + /**
|
| + * Create a script object with a single fragment containing the given
|
| + * [scriptContent].
|
| + */
|
| + DartScript createScript(String scriptContent) {
|
| + 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);
|
| + return new DartScript(
|
| + source, [new ScriptFragment(97, 5, 36, scriptContent)]);
|
| + }
|
| +
|
| + /**
|
| + * Enable strong mode in the current analysis context.
|
| + */
|
| + void enableStrongMode() {
|
| + AnalysisOptionsImpl options = context.analysisOptions;
|
| + options.strongMode = true;
|
| + context.analysisOptions = options;
|
| + }
|
| +
|
| + /**
|
| + * Return the declaration of the class with the given [className] in the given
|
| + * compilation [unit].
|
| + */
|
| + ClassDeclaration getClass(CompilationUnit unit, String className) {
|
| + NodeList<CompilationUnitMember> unitMembers = unit.declarations;
|
| + for (CompilationUnitMember unitMember in unitMembers) {
|
| + if (unitMember is ClassDeclaration && unitMember.name.name == className) {
|
| + return unitMember;
|
| + }
|
| + }
|
| + fail('No class named $className in ${unit.element.source}');
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| + * Return the declaration of the field with the given [fieldName] in the class
|
| + * with the given [className] in the given compilation [unit].
|
| + */
|
| + VariableDeclaration getFieldInClass(
|
| + CompilationUnit unit, String className, String fieldName) {
|
| + ClassDeclaration unitMember = getClass(unit, className);
|
| + NodeList<ClassMember> classMembers = unitMember.members;
|
| + for (ClassMember classMember in classMembers) {
|
| + if (classMember is FieldDeclaration) {
|
| + NodeList<VariableDeclaration> fields = classMember.fields.variables;
|
| + for (VariableDeclaration field in fields) {
|
| + if (field.name.name == fieldName) {
|
| + return field;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + fail('No field named $fieldName in $className');
|
| + return null;
|
| + }
|
| +
|
| + /**
|
| + * Return the declaration of the method with the given [methodName] in the
|
| + * class with the given [className] in the given compilation [unit].
|
| + */
|
| + MethodDeclaration getMethodInClass(
|
| + CompilationUnit unit, String className, String methodName) {
|
| + ClassDeclaration unitMember = getClass(unit, className);
|
| + NodeList<ClassMember> classMembers = unitMember.members;
|
| + for (ClassMember classMember in classMembers) {
|
| + if (classMember is MethodDeclaration) {
|
| + if (classMember.name.name == methodName) {
|
| + return classMember;
|
| + }
|
| + }
|
| + }
|
| + fail('No method named $methodName in $className');
|
| + return null;
|
| + }
|
| +
|
| + List<Statement> getStatementsInMethod(
|
| + CompilationUnit unit, String className, String methodName) {
|
| + MethodDeclaration method = getMethodInClass(unit, className, methodName);
|
| + BlockFunctionBody body = method.body;
|
| + return body.block.statements;
|
| + }
|
| +
|
| + List<Statement> getStatementsInTopLevelFunction(
|
| + CompilationUnit unit, String functionName) {
|
| + FunctionDeclaration function = getTopLevelFunction(unit, functionName);
|
| + BlockFunctionBody body = function.functionExpression.body;
|
| + return body.block.statements;
|
| + }
|
| +
|
| + /**
|
| + * 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].
|
| + */
|
| + VariableDeclaration getTopLevelVariable(
|
| + CompilationUnit unit, String variableName) {
|
| + NodeList<CompilationUnitMember> unitMembers = unit.declarations;
|
| + for (CompilationUnitMember unitMember in unitMembers) {
|
| + if (unitMember is TopLevelVariableDeclaration) {
|
| + NodeList<VariableDeclaration> variables =
|
| + unitMember.variables.variables;
|
| + for (VariableDeclaration variable in variables) {
|
| + if (variable.name.name == variableName) {
|
| + return variable;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + void setUp() {
|
| + super.setUp();
|
| + emptySource = newSource('/test.dart');
|
| + }
|
| +
|
| + /**
|
| + * Fill [errorListener] with [result] errors in the current [task].
|
| + */
|
| + void _fillErrorListener(ResultDescriptor<List<AnalysisError>> result) {
|
| + List<AnalysisError> errors = task.outputs[result];
|
| + expect(errors, isNotNull, reason: result.name);
|
| + errorListener = new GatheringErrorListener();
|
| + errorListener.addAll(errors);
|
| + }
|
| +}
|
|
|