| Index: packages/analyzer/test/src/dart/constant/utilities_test.dart
|
| diff --git a/packages/analyzer/test/src/dart/constant/utilities_test.dart b/packages/analyzer/test/src/dart/constant/utilities_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..aa9bd5c88f7990c1c7d1ad8e7b33e0a6ed11c7fb
|
| --- /dev/null
|
| +++ b/packages/analyzer/test/src/dart/constant/utilities_test.dart
|
| @@ -0,0 +1,363 @@
|
| +// Copyright (c) 2016, 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 analyzer.test.src.dart.constant.utilities_test;
|
| +
|
| +import 'package:analyzer/dart/ast/ast.dart';
|
| +import 'package:analyzer/dart/ast/token.dart';
|
| +import 'package:analyzer/dart/element/element.dart';
|
| +import 'package:analyzer/src/dart/ast/token.dart';
|
| +import 'package:analyzer/src/dart/element/element.dart';
|
| +import 'package:analyzer/src/generated/constant.dart';
|
| +import 'package:analyzer/src/generated/engine.dart';
|
| +import 'package:analyzer/src/generated/resolver.dart';
|
| +import 'package:analyzer/src/generated/source.dart';
|
| +import 'package:analyzer/src/generated/source_io.dart';
|
| +import 'package:analyzer/src/generated/testing/ast_factory.dart';
|
| +import 'package:analyzer/src/generated/testing/element_factory.dart';
|
| +import 'package:analyzer/src/generated/testing/test_type_provider.dart';
|
| +import 'package:analyzer/src/generated/utilities_collection.dart';
|
| +import 'package:analyzer/src/task/dart.dart';
|
| +import 'package:test_reflective_loader/test_reflective_loader.dart';
|
| +import 'package:unittest/unittest.dart';
|
| +
|
| +import '../../../generated/engine_test.dart';
|
| +import '../../../generated/test_support.dart';
|
| +import '../../../utils.dart';
|
| +
|
| +main() {
|
| + initializeTestEnvironment();
|
| + defineReflectiveTests(ConstantFinderTest);
|
| + defineReflectiveTests(ReferenceFinderTest);
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ConstantFinderTest {
|
| + AstNode _node;
|
| + TypeProvider _typeProvider;
|
| + AnalysisContext _context;
|
| + Source _source;
|
| +
|
| + void setUp() {
|
| + _typeProvider = new TestTypeProvider();
|
| + _context = new _TestAnalysisContext();
|
| + _source = new TestSource();
|
| + }
|
| +
|
| + /**
|
| + * Test an annotation that consists solely of an identifier (and hence
|
| + * represents a reference to a compile-time constant variable).
|
| + */
|
| + void test_visitAnnotation_constantVariable() {
|
| + CompilationUnitElement compilationUnitElement =
|
| + ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
|
| + ElementFactory.library(_context, 'L').definingCompilationUnit =
|
| + compilationUnitElement;
|
| + ElementAnnotationImpl elementAnnotation =
|
| + new ElementAnnotationImpl(compilationUnitElement);
|
| + _node = elementAnnotation.annotationAst = AstFactory.annotation(
|
| + AstFactory.identifier3('x'))..elementAnnotation = elementAnnotation;
|
| + expect(_findAnnotations(), contains(_node));
|
| + }
|
| +
|
| + void test_visitAnnotation_enumConstant() {
|
| + // Analyzer ignores annotations on enum constant declarations.
|
| + Annotation annotation = AstFactory.annotation2(
|
| + AstFactory.identifier3('A'), null, AstFactory.argumentList());
|
| + _node = new EnumConstantDeclaration(
|
| + null, <Annotation>[annotation], AstFactory.identifier3('C'));
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + /**
|
| + * Test an annotation that represents the invocation of a constant
|
| + * constructor.
|
| + */
|
| + void test_visitAnnotation_invocation() {
|
| + CompilationUnitElement compilationUnitElement =
|
| + ElementFactory.compilationUnit('/test.dart', _source)..source = _source;
|
| + ElementFactory.library(_context, 'L').definingCompilationUnit =
|
| + compilationUnitElement;
|
| + ElementAnnotationImpl elementAnnotation =
|
| + new ElementAnnotationImpl(compilationUnitElement);
|
| + _node = elementAnnotation.annotationAst = AstFactory.annotation2(
|
| + AstFactory.identifier3('A'), null, AstFactory.argumentList())
|
| + ..elementAnnotation = elementAnnotation;
|
| + expect(_findAnnotations(), contains(_node));
|
| + }
|
| +
|
| + void test_visitAnnotation_partOf() {
|
| + // Analyzer ignores annotations on "part of" directives.
|
| + Annotation annotation = AstFactory.annotation2(
|
| + AstFactory.identifier3('A'), null, AstFactory.argumentList());
|
| + _node = AstFactory.partOfDirective2(
|
| + <Annotation>[annotation], AstFactory.libraryIdentifier2(<String>['L']));
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + void test_visitConstructorDeclaration_const() {
|
| + ConstructorElement element = _setupConstructorDeclaration("A", true);
|
| + expect(_findConstants(), contains(element));
|
| + }
|
| +
|
| + void test_visitConstructorDeclaration_nonConst() {
|
| + _setupConstructorDeclaration("A", false);
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_const() {
|
| + VariableElement element = _setupVariableDeclaration("v", true, true);
|
| + expect(_findConstants(), contains(element));
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_final_inClass() {
|
| + _setupFieldDeclaration('C', 'f', Keyword.FINAL);
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_final_inClassWithConstConstructor() {
|
| + VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
|
| + hasConstConstructor: true);
|
| + expect(_findConstants(), contains(field.element));
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_final_outsideClass() {
|
| + _setupVariableDeclaration('v', false, true, isFinal: true);
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_noInitializer() {
|
| + _setupVariableDeclaration("v", true, false);
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_nonConst() {
|
| + _setupVariableDeclaration("v", false, true);
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_static_const_inClass() {
|
| + VariableDeclaration field =
|
| + _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true);
|
| + expect(_findConstants(), contains(field.element));
|
| + }
|
| +
|
| + void
|
| + test_visitVariableDeclaration_static_const_inClassWithConstConstructor() {
|
| + VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST,
|
| + isStatic: true, hasConstConstructor: true);
|
| + expect(_findConstants(), contains(field.element));
|
| + }
|
| +
|
| + void
|
| + test_visitVariableDeclaration_static_final_inClassWithConstConstructor() {
|
| + VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
|
| + isStatic: true, hasConstConstructor: true);
|
| + expect(_findConstants(), isNot(contains(field.element)));
|
| + }
|
| +
|
| + void
|
| + test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstructor() {
|
| + VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL,
|
| + isInitialized: false, hasConstConstructor: true);
|
| + expect(_findConstants(), isNot(contains(field.element)));
|
| + }
|
| +
|
| + void test_visitVariableDeclaration_uninitialized_static_const_inClass() {
|
| + _setupFieldDeclaration('C', 'f', Keyword.CONST,
|
| + isStatic: true, isInitialized: false);
|
| + expect(_findConstants(), isEmpty);
|
| + }
|
| +
|
| + List<Annotation> _findAnnotations() {
|
| + Set<Annotation> annotations = new Set<Annotation>();
|
| + for (ConstantEvaluationTarget target in _findConstants()) {
|
| + if (target is ElementAnnotationImpl) {
|
| + expect(target.context, same(_context));
|
| + expect(target.source, same(_source));
|
| + annotations.add(target.annotationAst);
|
| + }
|
| + }
|
| + return new List<Annotation>.from(annotations);
|
| + }
|
| +
|
| + List<ConstantEvaluationTarget> _findConstants() {
|
| + ConstantFinder finder = new ConstantFinder();
|
| + _node.accept(finder);
|
| + List<ConstantEvaluationTarget> constants = finder.constantsToCompute;
|
| + expect(constants, isNotNull);
|
| + return constants;
|
| + }
|
| +
|
| + ConstructorElement _setupConstructorDeclaration(String name, bool isConst) {
|
| + Keyword constKeyword = isConst ? Keyword.CONST : null;
|
| + ConstructorDeclaration constructorDeclaration =
|
| + AstFactory.constructorDeclaration2(
|
| + constKeyword,
|
| + null,
|
| + null,
|
| + name,
|
| + AstFactory.formalParameterList(),
|
| + null,
|
| + AstFactory.blockFunctionBody2());
|
| + ClassElement classElement = ElementFactory.classElement2(name);
|
| + ConstructorElement element =
|
| + ElementFactory.constructorElement(classElement, name, isConst);
|
| + constructorDeclaration.element = element;
|
| + _node = constructorDeclaration;
|
| + return element;
|
| + }
|
| +
|
| + VariableDeclaration _setupFieldDeclaration(
|
| + String className, String fieldName, Keyword keyword,
|
| + {bool isInitialized: true,
|
| + bool isStatic: false,
|
| + bool hasConstConstructor: false}) {
|
| + VariableDeclaration variableDeclaration = isInitialized
|
| + ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0))
|
| + : AstFactory.variableDeclaration(fieldName);
|
| + VariableElement fieldElement = ElementFactory.fieldElement(
|
| + fieldName,
|
| + isStatic,
|
| + keyword == Keyword.FINAL,
|
| + keyword == Keyword.CONST,
|
| + _typeProvider.intType);
|
| + variableDeclaration.name.staticElement = fieldElement;
|
| + FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2(
|
| + isStatic, keyword, <VariableDeclaration>[variableDeclaration]);
|
| + ClassDeclaration classDeclaration =
|
| + AstFactory.classDeclaration(null, className, null, null, null, null);
|
| + classDeclaration.members.add(fieldDeclaration);
|
| + _node = classDeclaration;
|
| + ClassElementImpl classElement = ElementFactory.classElement2(className);
|
| + classElement.fields = <FieldElement>[fieldElement];
|
| + classDeclaration.name.staticElement = classElement;
|
| + if (hasConstConstructor) {
|
| + ConstructorDeclaration constructorDeclaration =
|
| + AstFactory.constructorDeclaration2(
|
| + Keyword.CONST,
|
| + null,
|
| + AstFactory.identifier3(className),
|
| + null,
|
| + AstFactory.formalParameterList(),
|
| + null,
|
| + AstFactory.blockFunctionBody2());
|
| + classDeclaration.members.add(constructorDeclaration);
|
| + ConstructorElement constructorElement =
|
| + ElementFactory.constructorElement(classElement, '', true);
|
| + constructorDeclaration.element = constructorElement;
|
| + classElement.constructors = <ConstructorElement>[constructorElement];
|
| + } else {
|
| + classElement.constructors = ConstructorElement.EMPTY_LIST;
|
| + }
|
| + return variableDeclaration;
|
| + }
|
| +
|
| + VariableElement _setupVariableDeclaration(
|
| + String name, bool isConst, bool isInitialized,
|
| + {isFinal: false}) {
|
| + VariableDeclaration variableDeclaration = isInitialized
|
| + ? AstFactory.variableDeclaration2(name, AstFactory.integer(0))
|
| + : AstFactory.variableDeclaration(name);
|
| + SimpleIdentifier identifier = variableDeclaration.name;
|
| + VariableElement element = ElementFactory.localVariableElement(identifier);
|
| + identifier.staticElement = element;
|
| + Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null;
|
| + AstFactory.variableDeclarationList2(keyword, [variableDeclaration]);
|
| + _node = variableDeclaration;
|
| + return element;
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class ReferenceFinderTest {
|
| + DirectedGraph<ConstantEvaluationTarget> _referenceGraph;
|
| + VariableElement _head;
|
| + Element _tail;
|
| +
|
| + void setUp() {
|
| + _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>();
|
| + _head = ElementFactory.topLevelVariableElement2("v1");
|
| + }
|
| +
|
| + void test_visitSimpleIdentifier_const() {
|
| + _visitNode(_makeTailVariable("v2", true));
|
| + _assertOneArc(_tail);
|
| + }
|
| +
|
| + void test_visitSuperConstructorInvocation_const() {
|
| + _visitNode(_makeTailSuperConstructorInvocation("A", true));
|
| + _assertOneArc(_tail);
|
| + }
|
| +
|
| + void test_visitSuperConstructorInvocation_nonConst() {
|
| + _visitNode(_makeTailSuperConstructorInvocation("A", false));
|
| + _assertOneArc(_tail);
|
| + }
|
| +
|
| + void test_visitSuperConstructorInvocation_unresolved() {
|
| + SuperConstructorInvocation superConstructorInvocation =
|
| + AstFactory.superConstructorInvocation();
|
| + _visitNode(superConstructorInvocation);
|
| + _assertNoArcs();
|
| + }
|
| +
|
| + void _assertNoArcs() {
|
| + Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
|
| + expect(tails, hasLength(0));
|
| + }
|
| +
|
| + void _assertOneArc(Element tail) {
|
| + Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head);
|
| + expect(tails, hasLength(1));
|
| + expect(tails.first, same(tail));
|
| + }
|
| +
|
| + ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) =>
|
| + new ReferenceFinder((ConstantEvaluationTarget dependency) {
|
| + _referenceGraph.addEdge(source, dependency);
|
| + });
|
| + SuperConstructorInvocation _makeTailSuperConstructorInvocation(
|
| + String name, bool isConst) {
|
| + List<ConstructorInitializer> initializers =
|
| + new List<ConstructorInitializer>();
|
| + ConstructorDeclaration constructorDeclaration =
|
| + AstFactory.constructorDeclaration(AstFactory.identifier3(name), null,
|
| + AstFactory.formalParameterList(), initializers);
|
| + if (isConst) {
|
| + constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0);
|
| + }
|
| + ClassElementImpl classElement = ElementFactory.classElement2(name);
|
| + SuperConstructorInvocation superConstructorInvocation =
|
| + AstFactory.superConstructorInvocation();
|
| + ConstructorElementImpl constructorElement =
|
| + ElementFactory.constructorElement(classElement, name, isConst);
|
| + _tail = constructorElement;
|
| + superConstructorInvocation.staticElement = constructorElement;
|
| + return superConstructorInvocation;
|
| + }
|
| +
|
| + SimpleIdentifier _makeTailVariable(String name, bool isConst) {
|
| + VariableDeclaration variableDeclaration =
|
| + AstFactory.variableDeclaration(name);
|
| + ConstLocalVariableElementImpl variableElement =
|
| + ElementFactory.constLocalVariableElement(name);
|
| + _tail = variableElement;
|
| + variableElement.const3 = isConst;
|
| + AstFactory.variableDeclarationList2(
|
| + isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]);
|
| + SimpleIdentifier identifier = AstFactory.identifier3(name);
|
| + identifier.staticElement = variableElement;
|
| + return identifier;
|
| + }
|
| +
|
| + void _visitNode(AstNode node) {
|
| + node.accept(_createReferenceFinder(_head));
|
| + }
|
| +}
|
| +
|
| +class _TestAnalysisContext extends TestAnalysisContext {
|
| + @override
|
| + InternalAnalysisContext getContextFor(Source source) => this;
|
| +}
|
|
|