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