| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library analyzer.test.src.dart.constant.utilities_test; |
| 6 |
| 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 8 import 'package:analyzer/dart/ast/token.dart'; |
| 9 import 'package:analyzer/dart/element/element.dart'; |
| 10 import 'package:analyzer/src/dart/ast/token.dart'; |
| 11 import 'package:analyzer/src/dart/element/element.dart'; |
| 12 import 'package:analyzer/src/generated/constant.dart'; |
| 13 import 'package:analyzer/src/generated/engine.dart'; |
| 14 import 'package:analyzer/src/generated/resolver.dart'; |
| 15 import 'package:analyzer/src/generated/source.dart'; |
| 16 import 'package:analyzer/src/generated/source_io.dart'; |
| 17 import 'package:analyzer/src/generated/testing/ast_factory.dart'; |
| 18 import 'package:analyzer/src/generated/testing/element_factory.dart'; |
| 19 import 'package:analyzer/src/generated/testing/test_type_provider.dart'; |
| 20 import 'package:analyzer/src/generated/utilities_collection.dart'; |
| 21 import 'package:analyzer/src/task/dart.dart'; |
| 22 import 'package:unittest/unittest.dart'; |
| 23 |
| 24 import '../../../generated/engine_test.dart'; |
| 25 import '../../../generated/test_support.dart'; |
| 26 import '../../../reflective_tests.dart'; |
| 27 import '../../../utils.dart'; |
| 28 |
| 29 main() { |
| 30 initializeTestEnvironment(); |
| 31 runReflectiveTests(ConstantFinderTest); |
| 32 runReflectiveTests(ReferenceFinderTest); |
| 33 } |
| 34 |
| 35 @reflectiveTest |
| 36 class ConstantFinderTest { |
| 37 AstNode _node; |
| 38 TypeProvider _typeProvider; |
| 39 AnalysisContext _context; |
| 40 Source _source; |
| 41 |
| 42 void setUp() { |
| 43 _typeProvider = new TestTypeProvider(); |
| 44 _context = new _TestAnalysisContext(); |
| 45 _source = new TestSource(); |
| 46 } |
| 47 |
| 48 /** |
| 49 * Test an annotation that consists solely of an identifier (and hence |
| 50 * represents a reference to a compile-time constant variable). |
| 51 */ |
| 52 void test_visitAnnotation_constantVariable() { |
| 53 CompilationUnitElement compilationUnitElement = |
| 54 ElementFactory.compilationUnit('/test.dart', _source)..source = _source; |
| 55 ElementFactory.library(_context, 'L').definingCompilationUnit = |
| 56 compilationUnitElement; |
| 57 ElementAnnotationImpl elementAnnotation = |
| 58 new ElementAnnotationImpl(compilationUnitElement); |
| 59 _node = elementAnnotation.annotationAst = AstFactory.annotation( |
| 60 AstFactory.identifier3('x'))..elementAnnotation = elementAnnotation; |
| 61 expect(_findAnnotations(), contains(_node)); |
| 62 } |
| 63 |
| 64 /** |
| 65 * Test an annotation that represents the invocation of a constant |
| 66 * constructor. |
| 67 */ |
| 68 void test_visitAnnotation_invocation() { |
| 69 CompilationUnitElement compilationUnitElement = |
| 70 ElementFactory.compilationUnit('/test.dart', _source)..source = _source; |
| 71 ElementFactory.library(_context, 'L').definingCompilationUnit = |
| 72 compilationUnitElement; |
| 73 ElementAnnotationImpl elementAnnotation = |
| 74 new ElementAnnotationImpl(compilationUnitElement); |
| 75 _node = elementAnnotation.annotationAst = AstFactory.annotation2( |
| 76 AstFactory.identifier3('A'), null, AstFactory.argumentList()) |
| 77 ..elementAnnotation = elementAnnotation; |
| 78 expect(_findAnnotations(), contains(_node)); |
| 79 } |
| 80 |
| 81 void test_visitAnnotation_partOf() { |
| 82 // Analyzer ignores annotations on "part of" directives. |
| 83 Annotation annotation = AstFactory.annotation2( |
| 84 AstFactory.identifier3('A'), null, AstFactory.argumentList()); |
| 85 _node = AstFactory.partOfDirective2( |
| 86 <Annotation>[annotation], AstFactory.libraryIdentifier2(<String>['L'])); |
| 87 expect(_findConstants(), isEmpty); |
| 88 } |
| 89 |
| 90 void test_visitConstructorDeclaration_const() { |
| 91 ConstructorElement element = _setupConstructorDeclaration("A", true); |
| 92 expect(_findConstants(), contains(element)); |
| 93 } |
| 94 |
| 95 void test_visitConstructorDeclaration_nonConst() { |
| 96 _setupConstructorDeclaration("A", false); |
| 97 expect(_findConstants(), isEmpty); |
| 98 } |
| 99 |
| 100 void test_visitVariableDeclaration_const() { |
| 101 VariableElement element = _setupVariableDeclaration("v", true, true); |
| 102 expect(_findConstants(), contains(element)); |
| 103 } |
| 104 |
| 105 void test_visitVariableDeclaration_final_inClass() { |
| 106 _setupFieldDeclaration('C', 'f', Keyword.FINAL); |
| 107 expect(_findConstants(), isEmpty); |
| 108 } |
| 109 |
| 110 void test_visitVariableDeclaration_final_inClassWithConstConstructor() { |
| 111 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL, |
| 112 hasConstConstructor: true); |
| 113 expect(_findConstants(), contains(field.element)); |
| 114 } |
| 115 |
| 116 void test_visitVariableDeclaration_final_outsideClass() { |
| 117 _setupVariableDeclaration('v', false, true, isFinal: true); |
| 118 expect(_findConstants(), isEmpty); |
| 119 } |
| 120 |
| 121 void test_visitVariableDeclaration_noInitializer() { |
| 122 _setupVariableDeclaration("v", true, false); |
| 123 expect(_findConstants(), isEmpty); |
| 124 } |
| 125 |
| 126 void test_visitVariableDeclaration_nonConst() { |
| 127 _setupVariableDeclaration("v", false, true); |
| 128 expect(_findConstants(), isEmpty); |
| 129 } |
| 130 |
| 131 void test_visitVariableDeclaration_static_const_inClass() { |
| 132 VariableDeclaration field = |
| 133 _setupFieldDeclaration('C', 'f', Keyword.CONST, isStatic: true); |
| 134 expect(_findConstants(), contains(field.element)); |
| 135 } |
| 136 |
| 137 void |
| 138 test_visitVariableDeclaration_static_const_inClassWithConstConstructor() { |
| 139 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.CONST, |
| 140 isStatic: true, hasConstConstructor: true); |
| 141 expect(_findConstants(), contains(field.element)); |
| 142 } |
| 143 |
| 144 void |
| 145 test_visitVariableDeclaration_static_final_inClassWithConstConstructor() { |
| 146 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL, |
| 147 isStatic: true, hasConstConstructor: true); |
| 148 expect(_findConstants(), isNot(contains(field.element))); |
| 149 } |
| 150 |
| 151 void |
| 152 test_visitVariableDeclaration_uninitialized_final_inClassWithConstConstruc
tor() { |
| 153 VariableDeclaration field = _setupFieldDeclaration('C', 'f', Keyword.FINAL, |
| 154 isInitialized: false, hasConstConstructor: true); |
| 155 expect(_findConstants(), isNot(contains(field.element))); |
| 156 } |
| 157 |
| 158 void test_visitVariableDeclaration_uninitialized_static_const_inClass() { |
| 159 _setupFieldDeclaration('C', 'f', Keyword.CONST, |
| 160 isStatic: true, isInitialized: false); |
| 161 expect(_findConstants(), isEmpty); |
| 162 } |
| 163 |
| 164 List<Annotation> _findAnnotations() { |
| 165 Set<Annotation> annotations = new Set<Annotation>(); |
| 166 for (ConstantEvaluationTarget target in _findConstants()) { |
| 167 if (target is ElementAnnotationImpl) { |
| 168 expect(target.context, same(_context)); |
| 169 expect(target.source, same(_source)); |
| 170 annotations.add(target.annotationAst); |
| 171 } |
| 172 } |
| 173 return new List<Annotation>.from(annotations); |
| 174 } |
| 175 |
| 176 List<ConstantEvaluationTarget> _findConstants() { |
| 177 ConstantFinder finder = new ConstantFinder(_context, _source, _source); |
| 178 _node.accept(finder); |
| 179 List<ConstantEvaluationTarget> constants = finder.constantsToCompute; |
| 180 expect(constants, isNotNull); |
| 181 return constants; |
| 182 } |
| 183 |
| 184 ConstructorElement _setupConstructorDeclaration(String name, bool isConst) { |
| 185 Keyword constKeyword = isConst ? Keyword.CONST : null; |
| 186 ConstructorDeclaration constructorDeclaration = |
| 187 AstFactory.constructorDeclaration2( |
| 188 constKeyword, |
| 189 null, |
| 190 null, |
| 191 name, |
| 192 AstFactory.formalParameterList(), |
| 193 null, |
| 194 AstFactory.blockFunctionBody2()); |
| 195 ClassElement classElement = ElementFactory.classElement2(name); |
| 196 ConstructorElement element = |
| 197 ElementFactory.constructorElement(classElement, name, isConst); |
| 198 constructorDeclaration.element = element; |
| 199 _node = constructorDeclaration; |
| 200 return element; |
| 201 } |
| 202 |
| 203 VariableDeclaration _setupFieldDeclaration( |
| 204 String className, String fieldName, Keyword keyword, |
| 205 {bool isInitialized: true, |
| 206 bool isStatic: false, |
| 207 bool hasConstConstructor: false}) { |
| 208 VariableDeclaration variableDeclaration = isInitialized |
| 209 ? AstFactory.variableDeclaration2(fieldName, AstFactory.integer(0)) |
| 210 : AstFactory.variableDeclaration(fieldName); |
| 211 VariableElement fieldElement = ElementFactory.fieldElement( |
| 212 fieldName, |
| 213 isStatic, |
| 214 keyword == Keyword.FINAL, |
| 215 keyword == Keyword.CONST, |
| 216 _typeProvider.intType); |
| 217 variableDeclaration.name.staticElement = fieldElement; |
| 218 FieldDeclaration fieldDeclaration = AstFactory.fieldDeclaration2( |
| 219 isStatic, keyword, <VariableDeclaration>[variableDeclaration]); |
| 220 ClassDeclaration classDeclaration = |
| 221 AstFactory.classDeclaration(null, className, null, null, null, null); |
| 222 classDeclaration.members.add(fieldDeclaration); |
| 223 _node = classDeclaration; |
| 224 ClassElementImpl classElement = ElementFactory.classElement2(className); |
| 225 classElement.fields = <FieldElement>[fieldElement]; |
| 226 classDeclaration.name.staticElement = classElement; |
| 227 if (hasConstConstructor) { |
| 228 ConstructorDeclaration constructorDeclaration = |
| 229 AstFactory.constructorDeclaration2( |
| 230 Keyword.CONST, |
| 231 null, |
| 232 AstFactory.identifier3(className), |
| 233 null, |
| 234 AstFactory.formalParameterList(), |
| 235 null, |
| 236 AstFactory.blockFunctionBody2()); |
| 237 classDeclaration.members.add(constructorDeclaration); |
| 238 ConstructorElement constructorElement = |
| 239 ElementFactory.constructorElement(classElement, '', true); |
| 240 constructorDeclaration.element = constructorElement; |
| 241 classElement.constructors = <ConstructorElement>[constructorElement]; |
| 242 } else { |
| 243 classElement.constructors = ConstructorElement.EMPTY_LIST; |
| 244 } |
| 245 return variableDeclaration; |
| 246 } |
| 247 |
| 248 VariableElement _setupVariableDeclaration( |
| 249 String name, bool isConst, bool isInitialized, |
| 250 {isFinal: false}) { |
| 251 VariableDeclaration variableDeclaration = isInitialized |
| 252 ? AstFactory.variableDeclaration2(name, AstFactory.integer(0)) |
| 253 : AstFactory.variableDeclaration(name); |
| 254 SimpleIdentifier identifier = variableDeclaration.name; |
| 255 VariableElement element = ElementFactory.localVariableElement(identifier); |
| 256 identifier.staticElement = element; |
| 257 Keyword keyword = isConst ? Keyword.CONST : isFinal ? Keyword.FINAL : null; |
| 258 AstFactory.variableDeclarationList2(keyword, [variableDeclaration]); |
| 259 _node = variableDeclaration; |
| 260 return element; |
| 261 } |
| 262 } |
| 263 |
| 264 @reflectiveTest |
| 265 class ReferenceFinderTest { |
| 266 DirectedGraph<ConstantEvaluationTarget> _referenceGraph; |
| 267 VariableElement _head; |
| 268 Element _tail; |
| 269 |
| 270 void setUp() { |
| 271 _referenceGraph = new DirectedGraph<ConstantEvaluationTarget>(); |
| 272 _head = ElementFactory.topLevelVariableElement2("v1"); |
| 273 } |
| 274 |
| 275 void test_visitSimpleIdentifier_const() { |
| 276 _visitNode(_makeTailVariable("v2", true)); |
| 277 _assertOneArc(_tail); |
| 278 } |
| 279 |
| 280 void test_visitSuperConstructorInvocation_const() { |
| 281 _visitNode(_makeTailSuperConstructorInvocation("A", true)); |
| 282 _assertOneArc(_tail); |
| 283 } |
| 284 |
| 285 void test_visitSuperConstructorInvocation_nonConst() { |
| 286 _visitNode(_makeTailSuperConstructorInvocation("A", false)); |
| 287 _assertOneArc(_tail); |
| 288 } |
| 289 |
| 290 void test_visitSuperConstructorInvocation_unresolved() { |
| 291 SuperConstructorInvocation superConstructorInvocation = |
| 292 AstFactory.superConstructorInvocation(); |
| 293 _visitNode(superConstructorInvocation); |
| 294 _assertNoArcs(); |
| 295 } |
| 296 |
| 297 void _assertNoArcs() { |
| 298 Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head); |
| 299 expect(tails, hasLength(0)); |
| 300 } |
| 301 |
| 302 void _assertOneArc(Element tail) { |
| 303 Set<ConstantEvaluationTarget> tails = _referenceGraph.getTails(_head); |
| 304 expect(tails, hasLength(1)); |
| 305 expect(tails.first, same(tail)); |
| 306 } |
| 307 |
| 308 ReferenceFinder _createReferenceFinder(ConstantEvaluationTarget source) => |
| 309 new ReferenceFinder((ConstantEvaluationTarget dependency) { |
| 310 _referenceGraph.addEdge(source, dependency); |
| 311 }); |
| 312 SuperConstructorInvocation _makeTailSuperConstructorInvocation( |
| 313 String name, bool isConst) { |
| 314 List<ConstructorInitializer> initializers = |
| 315 new List<ConstructorInitializer>(); |
| 316 ConstructorDeclaration constructorDeclaration = |
| 317 AstFactory.constructorDeclaration(AstFactory.identifier3(name), null, |
| 318 AstFactory.formalParameterList(), initializers); |
| 319 if (isConst) { |
| 320 constructorDeclaration.constKeyword = new KeywordToken(Keyword.CONST, 0); |
| 321 } |
| 322 ClassElementImpl classElement = ElementFactory.classElement2(name); |
| 323 SuperConstructorInvocation superConstructorInvocation = |
| 324 AstFactory.superConstructorInvocation(); |
| 325 ConstructorElementImpl constructorElement = |
| 326 ElementFactory.constructorElement(classElement, name, isConst); |
| 327 _tail = constructorElement; |
| 328 superConstructorInvocation.staticElement = constructorElement; |
| 329 return superConstructorInvocation; |
| 330 } |
| 331 |
| 332 SimpleIdentifier _makeTailVariable(String name, bool isConst) { |
| 333 VariableDeclaration variableDeclaration = |
| 334 AstFactory.variableDeclaration(name); |
| 335 ConstLocalVariableElementImpl variableElement = |
| 336 ElementFactory.constLocalVariableElement(name); |
| 337 _tail = variableElement; |
| 338 variableElement.const3 = isConst; |
| 339 AstFactory.variableDeclarationList2( |
| 340 isConst ? Keyword.CONST : Keyword.VAR, [variableDeclaration]); |
| 341 SimpleIdentifier identifier = AstFactory.identifier3(name); |
| 342 identifier.staticElement = variableElement; |
| 343 return identifier; |
| 344 } |
| 345 |
| 346 void _visitNode(AstNode node) { |
| 347 node.accept(_createReferenceFinder(_head)); |
| 348 } |
| 349 } |
| 350 |
| 351 class _TestAnalysisContext extends TestAnalysisContext { |
| 352 @override |
| 353 InternalAnalysisContext getContextFor(Source source) => this; |
| 354 } |
| OLD | NEW |