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.generated.element_resolver_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/dart/element/type.dart'; |
| 11 import 'package:analyzer/src/dart/element/element.dart'; |
| 12 import 'package:analyzer/src/generated/element_resolver.dart'; |
| 13 import 'package:analyzer/src/generated/engine.dart'; |
| 14 import 'package:analyzer/src/generated/java_core.dart'; |
| 15 import 'package:analyzer/src/generated/java_engine_io.dart'; |
| 16 import 'package:analyzer/src/generated/resolver.dart'; |
| 17 import 'package:analyzer/src/generated/source_io.dart'; |
| 18 import 'package:analyzer/src/generated/testing/ast_factory.dart'; |
| 19 import 'package:analyzer/src/generated/testing/element_factory.dart'; |
| 20 import 'package:analyzer/src/generated/testing/test_type_provider.dart'; |
| 21 import 'package:unittest/unittest.dart'; |
| 22 |
| 23 import '../reflective_tests.dart'; |
| 24 import '../utils.dart'; |
| 25 import 'analysis_context_factory.dart'; |
| 26 import 'test_support.dart'; |
| 27 |
| 28 main() { |
| 29 initializeTestEnvironment(); |
| 30 runReflectiveTests(ElementResolverTest); |
| 31 } |
| 32 |
| 33 @reflectiveTest |
| 34 class ElementResolverTest extends EngineTestCase { |
| 35 /** |
| 36 * The error listener to which errors will be reported. |
| 37 */ |
| 38 GatheringErrorListener _listener; |
| 39 |
| 40 /** |
| 41 * The type provider used to access the types. |
| 42 */ |
| 43 TestTypeProvider _typeProvider; |
| 44 |
| 45 /** |
| 46 * The library containing the code being resolved. |
| 47 */ |
| 48 LibraryElementImpl _definingLibrary; |
| 49 |
| 50 /** |
| 51 * The resolver visitor that maintains the state for the resolver. |
| 52 */ |
| 53 ResolverVisitor _visitor; |
| 54 |
| 55 /** |
| 56 * The resolver being used to resolve the test cases. |
| 57 */ |
| 58 ElementResolver _resolver; |
| 59 |
| 60 void fail_visitExportDirective_combinators() { |
| 61 fail("Not yet tested"); |
| 62 // Need to set up the exported library so that the identifier can be |
| 63 // resolved. |
| 64 ExportDirective directive = AstFactory.exportDirective2(null, [ |
| 65 AstFactory.hideCombinator2(["A"]) |
| 66 ]); |
| 67 _resolveNode(directive); |
| 68 _listener.assertNoErrors(); |
| 69 } |
| 70 |
| 71 void fail_visitFunctionExpressionInvocation() { |
| 72 fail("Not yet tested"); |
| 73 _listener.assertNoErrors(); |
| 74 } |
| 75 |
| 76 void fail_visitImportDirective_combinators_noPrefix() { |
| 77 fail("Not yet tested"); |
| 78 // Need to set up the imported library so that the identifier can be |
| 79 // resolved. |
| 80 ImportDirective directive = AstFactory.importDirective3(null, null, [ |
| 81 AstFactory.showCombinator2(["A"]) |
| 82 ]); |
| 83 _resolveNode(directive); |
| 84 _listener.assertNoErrors(); |
| 85 } |
| 86 |
| 87 void fail_visitImportDirective_combinators_prefix() { |
| 88 fail("Not yet tested"); |
| 89 // Need to set up the imported library so that the identifiers can be |
| 90 // resolved. |
| 91 String prefixName = "p"; |
| 92 _definingLibrary.imports = <ImportElement>[ |
| 93 ElementFactory.importFor(null, ElementFactory.prefix(prefixName)) |
| 94 ]; |
| 95 ImportDirective directive = AstFactory.importDirective3(null, prefixName, [ |
| 96 AstFactory.showCombinator2(["A"]), |
| 97 AstFactory.hideCombinator2(["B"]) |
| 98 ]); |
| 99 _resolveNode(directive); |
| 100 _listener.assertNoErrors(); |
| 101 } |
| 102 |
| 103 void fail_visitRedirectingConstructorInvocation() { |
| 104 fail("Not yet tested"); |
| 105 _listener.assertNoErrors(); |
| 106 } |
| 107 |
| 108 @override |
| 109 void setUp() { |
| 110 super.setUp(); |
| 111 _listener = new GatheringErrorListener(); |
| 112 _typeProvider = new TestTypeProvider(); |
| 113 _resolver = _createResolver(); |
| 114 } |
| 115 |
| 116 void test_lookUpMethodInInterfaces() { |
| 117 InterfaceType intType = _typeProvider.intType; |
| 118 // |
| 119 // abstract class A { int operator[](int index); } |
| 120 // |
| 121 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 122 MethodElement operator = |
| 123 ElementFactory.methodElement("[]", intType, [intType]); |
| 124 classA.methods = <MethodElement>[operator]; |
| 125 // |
| 126 // class B implements A {} |
| 127 // |
| 128 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 129 classB.interfaces = <InterfaceType>[classA.type]; |
| 130 // |
| 131 // class C extends Object with B {} |
| 132 // |
| 133 ClassElementImpl classC = ElementFactory.classElement2("C"); |
| 134 classC.mixins = <InterfaceType>[classB.type]; |
| 135 // |
| 136 // class D extends C {} |
| 137 // |
| 138 ClassElementImpl classD = ElementFactory.classElement("D", classC.type); |
| 139 // |
| 140 // D a; |
| 141 // a[i]; |
| 142 // |
| 143 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 144 array.staticType = classD.type; |
| 145 IndexExpression expression = |
| 146 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 147 expect(_resolveIndexExpression(expression), same(operator)); |
| 148 _listener.assertNoErrors(); |
| 149 } |
| 150 |
| 151 void test_visitAssignmentExpression_compound() { |
| 152 InterfaceType intType = _typeProvider.intType; |
| 153 SimpleIdentifier leftHandSide = AstFactory.identifier3("a"); |
| 154 leftHandSide.staticType = intType; |
| 155 AssignmentExpression assignment = AstFactory.assignmentExpression( |
| 156 leftHandSide, TokenType.PLUS_EQ, AstFactory.integer(1)); |
| 157 _resolveNode(assignment); |
| 158 expect( |
| 159 assignment.staticElement, same(getMethod(_typeProvider.numType, "+"))); |
| 160 _listener.assertNoErrors(); |
| 161 } |
| 162 |
| 163 void test_visitAssignmentExpression_simple() { |
| 164 AssignmentExpression expression = AstFactory.assignmentExpression( |
| 165 AstFactory.identifier3("x"), TokenType.EQ, AstFactory.integer(0)); |
| 166 _resolveNode(expression); |
| 167 expect(expression.staticElement, isNull); |
| 168 _listener.assertNoErrors(); |
| 169 } |
| 170 |
| 171 void test_visitBinaryExpression_bangEq() { |
| 172 // String i; |
| 173 // var j; |
| 174 // i == j |
| 175 InterfaceType stringType = _typeProvider.stringType; |
| 176 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 177 left.staticType = stringType; |
| 178 BinaryExpression expression = AstFactory.binaryExpression( |
| 179 left, TokenType.BANG_EQ, AstFactory.identifier3("j")); |
| 180 _resolveNode(expression); |
| 181 var stringElement = stringType.element; |
| 182 expect(expression.staticElement, isNotNull); |
| 183 expect( |
| 184 expression.staticElement, |
| 185 stringElement.lookUpMethod( |
| 186 TokenType.EQ_EQ.lexeme, stringElement.library)); |
| 187 expect(expression.propagatedElement, isNull); |
| 188 _listener.assertNoErrors(); |
| 189 } |
| 190 |
| 191 void test_visitBinaryExpression_eq() { |
| 192 // String i; |
| 193 // var j; |
| 194 // i == j |
| 195 InterfaceType stringType = _typeProvider.stringType; |
| 196 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 197 left.staticType = stringType; |
| 198 BinaryExpression expression = AstFactory.binaryExpression( |
| 199 left, TokenType.EQ_EQ, AstFactory.identifier3("j")); |
| 200 _resolveNode(expression); |
| 201 var stringElement = stringType.element; |
| 202 expect( |
| 203 expression.staticElement, |
| 204 stringElement.lookUpMethod( |
| 205 TokenType.EQ_EQ.lexeme, stringElement.library)); |
| 206 expect(expression.propagatedElement, isNull); |
| 207 _listener.assertNoErrors(); |
| 208 } |
| 209 |
| 210 void test_visitBinaryExpression_plus() { |
| 211 // num i; |
| 212 // var j; |
| 213 // i + j |
| 214 InterfaceType numType = _typeProvider.numType; |
| 215 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 216 left.staticType = numType; |
| 217 BinaryExpression expression = AstFactory.binaryExpression( |
| 218 left, TokenType.PLUS, AstFactory.identifier3("j")); |
| 219 _resolveNode(expression); |
| 220 expect(expression.staticElement, getMethod(numType, "+")); |
| 221 expect(expression.propagatedElement, isNull); |
| 222 _listener.assertNoErrors(); |
| 223 } |
| 224 |
| 225 void test_visitBinaryExpression_plus_propagatedElement() { |
| 226 // var i = 1; |
| 227 // var j; |
| 228 // i + j |
| 229 InterfaceType numType = _typeProvider.numType; |
| 230 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 231 left.propagatedType = numType; |
| 232 BinaryExpression expression = AstFactory.binaryExpression( |
| 233 left, TokenType.PLUS, AstFactory.identifier3("j")); |
| 234 _resolveNode(expression); |
| 235 expect(expression.staticElement, isNull); |
| 236 expect(expression.propagatedElement, getMethod(numType, "+")); |
| 237 _listener.assertNoErrors(); |
| 238 } |
| 239 |
| 240 void test_visitBreakStatement_withLabel() { |
| 241 // loop: while (true) { |
| 242 // break loop; |
| 243 // } |
| 244 String label = "loop"; |
| 245 LabelElementImpl labelElement = new LabelElementImpl.forNode( |
| 246 AstFactory.identifier3(label), false, false); |
| 247 BreakStatement breakStatement = AstFactory.breakStatement2(label); |
| 248 Expression condition = AstFactory.booleanLiteral(true); |
| 249 WhileStatement whileStatement = |
| 250 AstFactory.whileStatement(condition, breakStatement); |
| 251 expect(_resolveBreak(breakStatement, labelElement, whileStatement), |
| 252 same(labelElement)); |
| 253 expect(breakStatement.target, same(whileStatement)); |
| 254 _listener.assertNoErrors(); |
| 255 } |
| 256 |
| 257 void test_visitBreakStatement_withoutLabel() { |
| 258 BreakStatement statement = AstFactory.breakStatement(); |
| 259 _resolveStatement(statement, null, null); |
| 260 _listener.assertNoErrors(); |
| 261 } |
| 262 |
| 263 void test_visitCommentReference_prefixedIdentifier_class_getter() { |
| 264 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 265 // set accessors |
| 266 String propName = "p"; |
| 267 PropertyAccessorElement getter = |
| 268 ElementFactory.getterElement(propName, false, _typeProvider.intType); |
| 269 PropertyAccessorElement setter = |
| 270 ElementFactory.setterElement(propName, false, _typeProvider.intType); |
| 271 classA.accessors = <PropertyAccessorElement>[getter, setter]; |
| 272 // set name scope |
| 273 _visitor.nameScope = new EnclosedScope(null) |
| 274 ..defineNameWithoutChecking('A', classA); |
| 275 // prepare "A.p" |
| 276 PrefixedIdentifier prefixed = AstFactory.identifier5('A', 'p'); |
| 277 CommentReference commentReference = new CommentReference(null, prefixed); |
| 278 // resolve |
| 279 _resolveNode(commentReference); |
| 280 expect(prefixed.prefix.staticElement, classA); |
| 281 expect(prefixed.identifier.staticElement, getter); |
| 282 _listener.assertNoErrors(); |
| 283 } |
| 284 |
| 285 void test_visitCommentReference_prefixedIdentifier_class_method() { |
| 286 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 287 // set method |
| 288 MethodElement method = |
| 289 ElementFactory.methodElement("m", _typeProvider.intType); |
| 290 classA.methods = <MethodElement>[method]; |
| 291 // set name scope |
| 292 _visitor.nameScope = new EnclosedScope(null) |
| 293 ..defineNameWithoutChecking('A', classA); |
| 294 // prepare "A.m" |
| 295 PrefixedIdentifier prefixed = AstFactory.identifier5('A', 'm'); |
| 296 CommentReference commentReference = new CommentReference(null, prefixed); |
| 297 // resolve |
| 298 _resolveNode(commentReference); |
| 299 expect(prefixed.prefix.staticElement, classA); |
| 300 expect(prefixed.identifier.staticElement, method); |
| 301 _listener.assertNoErrors(); |
| 302 } |
| 303 |
| 304 void test_visitConstructorName_named() { |
| 305 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 306 String constructorName = "a"; |
| 307 ConstructorElement constructor = |
| 308 ElementFactory.constructorElement2(classA, constructorName); |
| 309 classA.constructors = <ConstructorElement>[constructor]; |
| 310 ConstructorName name = AstFactory.constructorName( |
| 311 AstFactory.typeName(classA), constructorName); |
| 312 _resolveNode(name); |
| 313 expect(name.staticElement, same(constructor)); |
| 314 _listener.assertNoErrors(); |
| 315 } |
| 316 |
| 317 void test_visitConstructorName_unnamed() { |
| 318 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 319 String constructorName = null; |
| 320 ConstructorElement constructor = |
| 321 ElementFactory.constructorElement2(classA, constructorName); |
| 322 classA.constructors = <ConstructorElement>[constructor]; |
| 323 ConstructorName name = AstFactory.constructorName( |
| 324 AstFactory.typeName(classA), constructorName); |
| 325 _resolveNode(name); |
| 326 expect(name.staticElement, same(constructor)); |
| 327 _listener.assertNoErrors(); |
| 328 } |
| 329 |
| 330 void test_visitContinueStatement_withLabel() { |
| 331 // loop: while (true) { |
| 332 // continue loop; |
| 333 // } |
| 334 String label = "loop"; |
| 335 LabelElementImpl labelElement = new LabelElementImpl.forNode( |
| 336 AstFactory.identifier3(label), false, false); |
| 337 ContinueStatement continueStatement = AstFactory.continueStatement(label); |
| 338 Expression condition = AstFactory.booleanLiteral(true); |
| 339 WhileStatement whileStatement = |
| 340 AstFactory.whileStatement(condition, continueStatement); |
| 341 expect(_resolveContinue(continueStatement, labelElement, whileStatement), |
| 342 same(labelElement)); |
| 343 expect(continueStatement.target, same(whileStatement)); |
| 344 _listener.assertNoErrors(); |
| 345 } |
| 346 |
| 347 void test_visitContinueStatement_withoutLabel() { |
| 348 ContinueStatement statement = AstFactory.continueStatement(); |
| 349 _resolveStatement(statement, null, null); |
| 350 _listener.assertNoErrors(); |
| 351 } |
| 352 |
| 353 void test_visitEnumDeclaration() { |
| 354 CompilationUnitElementImpl compilationUnitElement = |
| 355 ElementFactory.compilationUnit('foo.dart'); |
| 356 ClassElementImpl enumElement = |
| 357 ElementFactory.enumElement(_typeProvider, ('E')); |
| 358 compilationUnitElement.enums = <ClassElement>[enumElement]; |
| 359 EnumDeclaration enumNode = AstFactory.enumDeclaration2('E', []); |
| 360 Annotation annotationNode = |
| 361 AstFactory.annotation(AstFactory.identifier3('a')); |
| 362 annotationNode.element = ElementFactory.classElement2('A'); |
| 363 annotationNode.elementAnnotation = |
| 364 new ElementAnnotationImpl(compilationUnitElement); |
| 365 enumNode.metadata.add(annotationNode); |
| 366 enumNode.name.staticElement = enumElement; |
| 367 List<ElementAnnotation> metadata = <ElementAnnotation>[ |
| 368 annotationNode.elementAnnotation |
| 369 ]; |
| 370 _resolveNode(enumNode); |
| 371 expect(metadata[0].element, annotationNode.element); |
| 372 } |
| 373 |
| 374 void test_visitExportDirective_noCombinators() { |
| 375 ExportDirective directive = AstFactory.exportDirective2(null); |
| 376 directive.element = ElementFactory |
| 377 .exportFor(ElementFactory.library(_definingLibrary.context, "lib")); |
| 378 _resolveNode(directive); |
| 379 _listener.assertNoErrors(); |
| 380 } |
| 381 |
| 382 void test_visitFieldFormalParameter() { |
| 383 String fieldName = "f"; |
| 384 InterfaceType intType = _typeProvider.intType; |
| 385 FieldElementImpl fieldElement = |
| 386 ElementFactory.fieldElement(fieldName, false, false, false, intType); |
| 387 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 388 classA.fields = <FieldElement>[fieldElement]; |
| 389 FieldFormalParameter parameter = |
| 390 AstFactory.fieldFormalParameter2(fieldName); |
| 391 FieldFormalParameterElementImpl parameterElement = |
| 392 ElementFactory.fieldFormalParameter(parameter.identifier); |
| 393 parameterElement.field = fieldElement; |
| 394 parameterElement.type = intType; |
| 395 parameter.identifier.staticElement = parameterElement; |
| 396 _resolveInClass(parameter, classA); |
| 397 expect(parameter.element.type, same(intType)); |
| 398 } |
| 399 |
| 400 void test_visitImportDirective_noCombinators_noPrefix() { |
| 401 ImportDirective directive = AstFactory.importDirective3(null, null); |
| 402 directive.element = ElementFactory.importFor( |
| 403 ElementFactory.library(_definingLibrary.context, "lib"), null); |
| 404 _resolveNode(directive); |
| 405 _listener.assertNoErrors(); |
| 406 } |
| 407 |
| 408 void test_visitImportDirective_noCombinators_prefix() { |
| 409 String prefixName = "p"; |
| 410 ImportElement importElement = ElementFactory.importFor( |
| 411 ElementFactory.library(_definingLibrary.context, "lib"), |
| 412 ElementFactory.prefix(prefixName)); |
| 413 _definingLibrary.imports = <ImportElement>[importElement]; |
| 414 ImportDirective directive = AstFactory.importDirective3(null, prefixName); |
| 415 directive.element = importElement; |
| 416 _resolveNode(directive); |
| 417 _listener.assertNoErrors(); |
| 418 } |
| 419 |
| 420 void test_visitImportDirective_withCombinators() { |
| 421 ShowCombinator combinator = AstFactory.showCombinator2(["A", "B", "C"]); |
| 422 ImportDirective directive = |
| 423 AstFactory.importDirective3(null, null, [combinator]); |
| 424 LibraryElementImpl library = |
| 425 ElementFactory.library(_definingLibrary.context, "lib"); |
| 426 TopLevelVariableElementImpl varA = |
| 427 ElementFactory.topLevelVariableElement2("A"); |
| 428 TopLevelVariableElementImpl varB = |
| 429 ElementFactory.topLevelVariableElement2("B"); |
| 430 TopLevelVariableElementImpl varC = |
| 431 ElementFactory.topLevelVariableElement2("C"); |
| 432 CompilationUnitElementImpl unit = |
| 433 library.definingCompilationUnit as CompilationUnitElementImpl; |
| 434 unit.accessors = <PropertyAccessorElement>[ |
| 435 varA.getter, |
| 436 varA.setter, |
| 437 varB.getter, |
| 438 varC.setter |
| 439 ]; |
| 440 unit.topLevelVariables = <TopLevelVariableElement>[varA, varB, varC]; |
| 441 directive.element = ElementFactory.importFor(library, null); |
| 442 _resolveNode(directive); |
| 443 expect(combinator.shownNames[0].staticElement, same(varA)); |
| 444 expect(combinator.shownNames[1].staticElement, same(varB)); |
| 445 expect(combinator.shownNames[2].staticElement, same(varC)); |
| 446 _listener.assertNoErrors(); |
| 447 } |
| 448 |
| 449 void test_visitIndexExpression_get() { |
| 450 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 451 InterfaceType intType = _typeProvider.intType; |
| 452 MethodElement getter = |
| 453 ElementFactory.methodElement("[]", intType, [intType]); |
| 454 classA.methods = <MethodElement>[getter]; |
| 455 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 456 array.staticType = classA.type; |
| 457 IndexExpression expression = |
| 458 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 459 expect(_resolveIndexExpression(expression), same(getter)); |
| 460 _listener.assertNoErrors(); |
| 461 } |
| 462 |
| 463 void test_visitIndexExpression_set() { |
| 464 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 465 InterfaceType intType = _typeProvider.intType; |
| 466 MethodElement setter = |
| 467 ElementFactory.methodElement("[]=", intType, [intType]); |
| 468 classA.methods = <MethodElement>[setter]; |
| 469 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 470 array.staticType = classA.type; |
| 471 IndexExpression expression = |
| 472 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 473 AstFactory.assignmentExpression( |
| 474 expression, TokenType.EQ, AstFactory.integer(0)); |
| 475 expect(_resolveIndexExpression(expression), same(setter)); |
| 476 _listener.assertNoErrors(); |
| 477 } |
| 478 |
| 479 void test_visitInstanceCreationExpression_named() { |
| 480 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 481 String constructorName = "a"; |
| 482 ConstructorElement constructor = |
| 483 ElementFactory.constructorElement2(classA, constructorName); |
| 484 classA.constructors = <ConstructorElement>[constructor]; |
| 485 ConstructorName name = AstFactory.constructorName( |
| 486 AstFactory.typeName(classA), constructorName); |
| 487 name.staticElement = constructor; |
| 488 InstanceCreationExpression creation = |
| 489 AstFactory.instanceCreationExpression(Keyword.NEW, name); |
| 490 _resolveNode(creation); |
| 491 expect(creation.staticElement, same(constructor)); |
| 492 _listener.assertNoErrors(); |
| 493 } |
| 494 |
| 495 void test_visitInstanceCreationExpression_unnamed() { |
| 496 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 497 String constructorName = null; |
| 498 ConstructorElement constructor = |
| 499 ElementFactory.constructorElement2(classA, constructorName); |
| 500 classA.constructors = <ConstructorElement>[constructor]; |
| 501 ConstructorName name = AstFactory.constructorName( |
| 502 AstFactory.typeName(classA), constructorName); |
| 503 name.staticElement = constructor; |
| 504 InstanceCreationExpression creation = |
| 505 AstFactory.instanceCreationExpression(Keyword.NEW, name); |
| 506 _resolveNode(creation); |
| 507 expect(creation.staticElement, same(constructor)); |
| 508 _listener.assertNoErrors(); |
| 509 } |
| 510 |
| 511 void test_visitInstanceCreationExpression_unnamed_namedParameter() { |
| 512 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 513 String constructorName = null; |
| 514 ConstructorElementImpl constructor = |
| 515 ElementFactory.constructorElement2(classA, constructorName); |
| 516 String parameterName = "a"; |
| 517 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 518 constructor.parameters = <ParameterElement>[parameter]; |
| 519 classA.constructors = <ConstructorElement>[constructor]; |
| 520 ConstructorName name = AstFactory.constructorName( |
| 521 AstFactory.typeName(classA), constructorName); |
| 522 name.staticElement = constructor; |
| 523 InstanceCreationExpression creation = AstFactory.instanceCreationExpression( |
| 524 Keyword.NEW, |
| 525 name, |
| 526 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); |
| 527 _resolveNode(creation); |
| 528 expect(creation.staticElement, same(constructor)); |
| 529 expect( |
| 530 (creation.argumentList.arguments[0] as NamedExpression) |
| 531 .name |
| 532 .label |
| 533 .staticElement, |
| 534 same(parameter)); |
| 535 _listener.assertNoErrors(); |
| 536 } |
| 537 |
| 538 void test_visitMethodInvocation() { |
| 539 InterfaceType numType = _typeProvider.numType; |
| 540 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 541 left.staticType = numType; |
| 542 String methodName = "abs"; |
| 543 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName); |
| 544 _resolveNode(invocation); |
| 545 expect(invocation.methodName.staticElement, |
| 546 same(getMethod(numType, methodName))); |
| 547 _listener.assertNoErrors(); |
| 548 } |
| 549 |
| 550 void test_visitMethodInvocation_namedParameter() { |
| 551 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 552 String methodName = "m"; |
| 553 String parameterName = "p"; |
| 554 MethodElementImpl method = ElementFactory.methodElement(methodName, null); |
| 555 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 556 method.parameters = <ParameterElement>[parameter]; |
| 557 classA.methods = <MethodElement>[method]; |
| 558 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 559 left.staticType = classA.type; |
| 560 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName, |
| 561 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); |
| 562 _resolveNode(invocation); |
| 563 expect(invocation.methodName.staticElement, same(method)); |
| 564 expect( |
| 565 (invocation.argumentList.arguments[0] as NamedExpression) |
| 566 .name |
| 567 .label |
| 568 .staticElement, |
| 569 same(parameter)); |
| 570 _listener.assertNoErrors(); |
| 571 } |
| 572 |
| 573 void test_visitPostfixExpression() { |
| 574 InterfaceType numType = _typeProvider.numType; |
| 575 SimpleIdentifier operand = AstFactory.identifier3("i"); |
| 576 operand.staticType = numType; |
| 577 PostfixExpression expression = |
| 578 AstFactory.postfixExpression(operand, TokenType.PLUS_PLUS); |
| 579 _resolveNode(expression); |
| 580 expect(expression.staticElement, getMethod(numType, "+")); |
| 581 _listener.assertNoErrors(); |
| 582 } |
| 583 |
| 584 void test_visitPrefixedIdentifier_dynamic() { |
| 585 DartType dynamicType = _typeProvider.dynamicType; |
| 586 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 587 VariableElementImpl variable = ElementFactory.localVariableElement(target); |
| 588 variable.type = dynamicType; |
| 589 target.staticElement = variable; |
| 590 target.staticType = dynamicType; |
| 591 PrefixedIdentifier identifier = |
| 592 AstFactory.identifier(target, AstFactory.identifier3("b")); |
| 593 _resolveNode(identifier); |
| 594 expect(identifier.staticElement, isNull); |
| 595 expect(identifier.identifier.staticElement, isNull); |
| 596 _listener.assertNoErrors(); |
| 597 } |
| 598 |
| 599 void test_visitPrefixedIdentifier_nonDynamic() { |
| 600 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 601 String getterName = "b"; |
| 602 PropertyAccessorElement getter = |
| 603 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 604 classA.accessors = <PropertyAccessorElement>[getter]; |
| 605 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 606 VariableElementImpl variable = ElementFactory.localVariableElement(target); |
| 607 variable.type = classA.type; |
| 608 target.staticElement = variable; |
| 609 target.staticType = classA.type; |
| 610 PrefixedIdentifier identifier = |
| 611 AstFactory.identifier(target, AstFactory.identifier3(getterName)); |
| 612 _resolveNode(identifier); |
| 613 expect(identifier.staticElement, same(getter)); |
| 614 expect(identifier.identifier.staticElement, same(getter)); |
| 615 _listener.assertNoErrors(); |
| 616 } |
| 617 |
| 618 void test_visitPrefixedIdentifier_staticClassMember_getter() { |
| 619 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 620 // set accessors |
| 621 String propName = "b"; |
| 622 PropertyAccessorElement getter = |
| 623 ElementFactory.getterElement(propName, false, _typeProvider.intType); |
| 624 PropertyAccessorElement setter = |
| 625 ElementFactory.setterElement(propName, false, _typeProvider.intType); |
| 626 classA.accessors = <PropertyAccessorElement>[getter, setter]; |
| 627 // prepare "A.m" |
| 628 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 629 target.staticElement = classA; |
| 630 target.staticType = classA.type; |
| 631 PrefixedIdentifier identifier = |
| 632 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 633 // resolve |
| 634 _resolveNode(identifier); |
| 635 expect(identifier.staticElement, same(getter)); |
| 636 expect(identifier.identifier.staticElement, same(getter)); |
| 637 _listener.assertNoErrors(); |
| 638 } |
| 639 |
| 640 void test_visitPrefixedIdentifier_staticClassMember_method() { |
| 641 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 642 // set methods |
| 643 String propName = "m"; |
| 644 MethodElement method = |
| 645 ElementFactory.methodElement("m", _typeProvider.intType); |
| 646 classA.methods = <MethodElement>[method]; |
| 647 // prepare "A.m" |
| 648 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 649 target.staticElement = classA; |
| 650 target.staticType = classA.type; |
| 651 PrefixedIdentifier identifier = |
| 652 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 653 AstFactory.assignmentExpression( |
| 654 identifier, TokenType.EQ, AstFactory.nullLiteral()); |
| 655 // resolve |
| 656 _resolveNode(identifier); |
| 657 expect(identifier.staticElement, same(method)); |
| 658 expect(identifier.identifier.staticElement, same(method)); |
| 659 _listener.assertNoErrors(); |
| 660 } |
| 661 |
| 662 void test_visitPrefixedIdentifier_staticClassMember_setter() { |
| 663 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 664 // set accessors |
| 665 String propName = "b"; |
| 666 PropertyAccessorElement getter = |
| 667 ElementFactory.getterElement(propName, false, _typeProvider.intType); |
| 668 PropertyAccessorElement setter = |
| 669 ElementFactory.setterElement(propName, false, _typeProvider.intType); |
| 670 classA.accessors = <PropertyAccessorElement>[getter, setter]; |
| 671 // prepare "A.b = null" |
| 672 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 673 target.staticElement = classA; |
| 674 target.staticType = classA.type; |
| 675 PrefixedIdentifier identifier = |
| 676 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 677 AstFactory.assignmentExpression( |
| 678 identifier, TokenType.EQ, AstFactory.nullLiteral()); |
| 679 // resolve |
| 680 _resolveNode(identifier); |
| 681 expect(identifier.staticElement, same(setter)); |
| 682 expect(identifier.identifier.staticElement, same(setter)); |
| 683 _listener.assertNoErrors(); |
| 684 } |
| 685 |
| 686 void test_visitPrefixExpression() { |
| 687 InterfaceType numType = _typeProvider.numType; |
| 688 SimpleIdentifier operand = AstFactory.identifier3("i"); |
| 689 operand.staticType = numType; |
| 690 PrefixExpression expression = |
| 691 AstFactory.prefixExpression(TokenType.PLUS_PLUS, operand); |
| 692 _resolveNode(expression); |
| 693 expect(expression.staticElement, getMethod(numType, "+")); |
| 694 _listener.assertNoErrors(); |
| 695 } |
| 696 |
| 697 void test_visitPropertyAccess_getter_identifier() { |
| 698 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 699 String getterName = "b"; |
| 700 PropertyAccessorElement getter = |
| 701 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 702 classA.accessors = <PropertyAccessorElement>[getter]; |
| 703 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 704 target.staticType = classA.type; |
| 705 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); |
| 706 _resolveNode(access); |
| 707 expect(access.propertyName.staticElement, same(getter)); |
| 708 _listener.assertNoErrors(); |
| 709 } |
| 710 |
| 711 void test_visitPropertyAccess_getter_super() { |
| 712 // |
| 713 // class A { |
| 714 // int get b; |
| 715 // } |
| 716 // class B { |
| 717 // ... super.m ... |
| 718 // } |
| 719 // |
| 720 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 721 String getterName = "b"; |
| 722 PropertyAccessorElement getter = |
| 723 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 724 classA.accessors = <PropertyAccessorElement>[getter]; |
| 725 SuperExpression target = AstFactory.superExpression(); |
| 726 target.staticType = ElementFactory.classElement("B", classA.type).type; |
| 727 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); |
| 728 AstFactory.methodDeclaration2( |
| 729 null, |
| 730 null, |
| 731 null, |
| 732 null, |
| 733 AstFactory.identifier3("m"), |
| 734 AstFactory.formalParameterList(), |
| 735 AstFactory.expressionFunctionBody(access)); |
| 736 _resolveNode(access); |
| 737 expect(access.propertyName.staticElement, same(getter)); |
| 738 _listener.assertNoErrors(); |
| 739 } |
| 740 |
| 741 void test_visitPropertyAccess_setter_this() { |
| 742 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 743 String setterName = "b"; |
| 744 PropertyAccessorElement setter = |
| 745 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 746 classA.accessors = <PropertyAccessorElement>[setter]; |
| 747 ThisExpression target = AstFactory.thisExpression(); |
| 748 target.staticType = classA.type; |
| 749 PropertyAccess access = AstFactory.propertyAccess2(target, setterName); |
| 750 AstFactory.assignmentExpression( |
| 751 access, TokenType.EQ, AstFactory.integer(0)); |
| 752 _resolveNode(access); |
| 753 expect(access.propertyName.staticElement, same(setter)); |
| 754 _listener.assertNoErrors(); |
| 755 } |
| 756 |
| 757 void test_visitSimpleIdentifier_classScope() { |
| 758 InterfaceType doubleType = _typeProvider.doubleType; |
| 759 String fieldName = "NAN"; |
| 760 SimpleIdentifier node = AstFactory.identifier3(fieldName); |
| 761 _resolveInClass(node, doubleType.element); |
| 762 expect(node.staticElement, getGetter(doubleType, fieldName)); |
| 763 _listener.assertNoErrors(); |
| 764 } |
| 765 |
| 766 void test_visitSimpleIdentifier_dynamic() { |
| 767 SimpleIdentifier node = AstFactory.identifier3("dynamic"); |
| 768 _resolveIdentifier(node); |
| 769 expect(node.staticElement, same(_typeProvider.dynamicType.element)); |
| 770 expect(node.staticType, same(_typeProvider.typeType)); |
| 771 _listener.assertNoErrors(); |
| 772 } |
| 773 |
| 774 void test_visitSimpleIdentifier_lexicalScope() { |
| 775 SimpleIdentifier node = AstFactory.identifier3("i"); |
| 776 VariableElementImpl element = ElementFactory.localVariableElement(node); |
| 777 expect(_resolveIdentifier(node, [element]), same(element)); |
| 778 _listener.assertNoErrors(); |
| 779 } |
| 780 |
| 781 void test_visitSimpleIdentifier_lexicalScope_field_setter() { |
| 782 InterfaceType intType = _typeProvider.intType; |
| 783 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 784 String fieldName = "a"; |
| 785 FieldElement field = |
| 786 ElementFactory.fieldElement(fieldName, false, false, false, intType); |
| 787 classA.fields = <FieldElement>[field]; |
| 788 classA.accessors = <PropertyAccessorElement>[field.getter, field.setter]; |
| 789 SimpleIdentifier node = AstFactory.identifier3(fieldName); |
| 790 AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0)); |
| 791 _resolveInClass(node, classA); |
| 792 Element element = node.staticElement; |
| 793 EngineTestCase.assertInstanceOf((obj) => obj is PropertyAccessorElement, |
| 794 PropertyAccessorElement, element); |
| 795 expect((element as PropertyAccessorElement).isSetter, isTrue); |
| 796 _listener.assertNoErrors(); |
| 797 } |
| 798 |
| 799 void test_visitSuperConstructorInvocation() { |
| 800 ClassElementImpl superclass = ElementFactory.classElement2("A"); |
| 801 ConstructorElementImpl superConstructor = |
| 802 ElementFactory.constructorElement2(superclass, null); |
| 803 superclass.constructors = <ConstructorElement>[superConstructor]; |
| 804 ClassElementImpl subclass = |
| 805 ElementFactory.classElement("B", superclass.type); |
| 806 ConstructorElementImpl subConstructor = |
| 807 ElementFactory.constructorElement2(subclass, null); |
| 808 subclass.constructors = <ConstructorElement>[subConstructor]; |
| 809 SuperConstructorInvocation invocation = |
| 810 AstFactory.superConstructorInvocation(); |
| 811 _resolveInClass(invocation, subclass); |
| 812 expect(invocation.staticElement, superConstructor); |
| 813 _listener.assertNoErrors(); |
| 814 } |
| 815 |
| 816 void test_visitSuperConstructorInvocation_namedParameter() { |
| 817 ClassElementImpl superclass = ElementFactory.classElement2("A"); |
| 818 ConstructorElementImpl superConstructor = |
| 819 ElementFactory.constructorElement2(superclass, null); |
| 820 String parameterName = "p"; |
| 821 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 822 superConstructor.parameters = <ParameterElement>[parameter]; |
| 823 superclass.constructors = <ConstructorElement>[superConstructor]; |
| 824 ClassElementImpl subclass = |
| 825 ElementFactory.classElement("B", superclass.type); |
| 826 ConstructorElementImpl subConstructor = |
| 827 ElementFactory.constructorElement2(subclass, null); |
| 828 subclass.constructors = <ConstructorElement>[subConstructor]; |
| 829 SuperConstructorInvocation invocation = AstFactory |
| 830 .superConstructorInvocation([ |
| 831 AstFactory.namedExpression2(parameterName, AstFactory.integer(0)) |
| 832 ]); |
| 833 _resolveInClass(invocation, subclass); |
| 834 expect(invocation.staticElement, superConstructor); |
| 835 expect( |
| 836 (invocation.argumentList.arguments[0] as NamedExpression) |
| 837 .name |
| 838 .label |
| 839 .staticElement, |
| 840 same(parameter)); |
| 841 _listener.assertNoErrors(); |
| 842 } |
| 843 |
| 844 /** |
| 845 * Create the resolver used by the tests. |
| 846 * |
| 847 * @return the resolver that was created |
| 848 */ |
| 849 ElementResolver _createResolver() { |
| 850 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 851 FileBasedSource source = |
| 852 new FileBasedSource(FileUtilities2.createFile("/test.dart")); |
| 853 CompilationUnitElementImpl definingCompilationUnit = |
| 854 new CompilationUnitElementImpl("test.dart"); |
| 855 definingCompilationUnit.librarySource = |
| 856 definingCompilationUnit.source = source; |
| 857 _definingLibrary = ElementFactory.library(context, "test"); |
| 858 _definingLibrary.definingCompilationUnit = definingCompilationUnit; |
| 859 _visitor = new ResolverVisitor( |
| 860 _definingLibrary, source, _typeProvider, _listener, |
| 861 nameScope: new LibraryScope(_definingLibrary, _listener)); |
| 862 try { |
| 863 return _visitor.elementResolver; |
| 864 } catch (exception) { |
| 865 throw new IllegalArgumentException( |
| 866 "Could not create resolver", exception); |
| 867 } |
| 868 } |
| 869 |
| 870 /** |
| 871 * Return the element associated with the label of [statement] after the |
| 872 * resolver has resolved it. [labelElement] is the label element to be |
| 873 * defined in the statement's label scope, and [labelTarget] is the statement |
| 874 * the label resolves to. |
| 875 */ |
| 876 Element _resolveBreak(BreakStatement statement, LabelElementImpl labelElement, |
| 877 Statement labelTarget) { |
| 878 _resolveStatement(statement, labelElement, labelTarget); |
| 879 return statement.label.staticElement; |
| 880 } |
| 881 |
| 882 /** |
| 883 * Return the element associated with the label [statement] after the |
| 884 * resolver has resolved it. [labelElement] is the label element to be |
| 885 * defined in the statement's label scope, and [labelTarget] is the AST node |
| 886 * the label resolves to. |
| 887 * |
| 888 * @param statement the statement to be resolved |
| 889 * @param labelElement the label element to be defined in the statement's labe
l scope |
| 890 * @return the element to which the statement's label was resolved |
| 891 */ |
| 892 Element _resolveContinue(ContinueStatement statement, |
| 893 LabelElementImpl labelElement, AstNode labelTarget) { |
| 894 _resolveStatement(statement, labelElement, labelTarget); |
| 895 return statement.label.staticElement; |
| 896 } |
| 897 |
| 898 /** |
| 899 * Return the element associated with the given identifier after the resolver
has resolved the |
| 900 * identifier. |
| 901 * |
| 902 * @param node the expression to be resolved |
| 903 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 904 * being resolved |
| 905 * @return the element to which the expression was resolved |
| 906 */ |
| 907 Element _resolveIdentifier(Identifier node, [List<Element> definedElements]) { |
| 908 _resolveNode(node, definedElements); |
| 909 return node.staticElement; |
| 910 } |
| 911 |
| 912 /** |
| 913 * Return the element associated with the given identifier after the resolver
has resolved the |
| 914 * identifier. |
| 915 * |
| 916 * @param node the expression to be resolved |
| 917 * @param enclosingClass the element representing the class enclosing the iden
tifier |
| 918 * @return the element to which the expression was resolved |
| 919 */ |
| 920 void _resolveInClass(AstNode node, ClassElement enclosingClass) { |
| 921 try { |
| 922 Scope outerScope = _visitor.nameScope; |
| 923 try { |
| 924 _visitor.enclosingClass = enclosingClass; |
| 925 EnclosedScope innerScope = new ClassScope( |
| 926 new TypeParameterScope(outerScope, enclosingClass), enclosingClass); |
| 927 _visitor.nameScope = innerScope; |
| 928 node.accept(_resolver); |
| 929 } finally { |
| 930 _visitor.enclosingClass = null; |
| 931 _visitor.nameScope = outerScope; |
| 932 } |
| 933 } catch (exception) { |
| 934 throw new IllegalArgumentException("Could not resolve node", exception); |
| 935 } |
| 936 } |
| 937 |
| 938 /** |
| 939 * Return the element associated with the given expression after the resolver
has resolved the |
| 940 * expression. |
| 941 * |
| 942 * @param node the expression to be resolved |
| 943 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 944 * being resolved |
| 945 * @return the element to which the expression was resolved |
| 946 */ |
| 947 Element _resolveIndexExpression(IndexExpression node, |
| 948 [List<Element> definedElements]) { |
| 949 _resolveNode(node, definedElements); |
| 950 return node.staticElement; |
| 951 } |
| 952 |
| 953 /** |
| 954 * Return the element associated with the given identifier after the resolver
has resolved the |
| 955 * identifier. |
| 956 * |
| 957 * @param node the expression to be resolved |
| 958 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 959 * being resolved |
| 960 * @return the element to which the expression was resolved |
| 961 */ |
| 962 void _resolveNode(AstNode node, [List<Element> definedElements]) { |
| 963 try { |
| 964 Scope outerScope = _visitor.nameScope; |
| 965 try { |
| 966 EnclosedScope innerScope = new EnclosedScope(outerScope); |
| 967 if (definedElements != null) { |
| 968 for (Element element in definedElements) { |
| 969 innerScope.define(element); |
| 970 } |
| 971 } |
| 972 _visitor.nameScope = innerScope; |
| 973 node.accept(_resolver); |
| 974 } finally { |
| 975 _visitor.nameScope = outerScope; |
| 976 } |
| 977 } catch (exception) { |
| 978 throw new IllegalArgumentException("Could not resolve node", exception); |
| 979 } |
| 980 } |
| 981 |
| 982 /** |
| 983 * Return the element associated with the label of the given statement after t
he resolver has |
| 984 * resolved the statement. |
| 985 * |
| 986 * @param statement the statement to be resolved |
| 987 * @param labelElement the label element to be defined in the statement's labe
l scope |
| 988 * @return the element to which the statement's label was resolved |
| 989 */ |
| 990 void _resolveStatement( |
| 991 Statement statement, LabelElementImpl labelElement, AstNode labelTarget) { |
| 992 try { |
| 993 LabelScope outerScope = _visitor.labelScope; |
| 994 try { |
| 995 LabelScope innerScope; |
| 996 if (labelElement == null) { |
| 997 innerScope = outerScope; |
| 998 } else { |
| 999 innerScope = new LabelScope( |
| 1000 outerScope, labelElement.name, labelTarget, labelElement); |
| 1001 } |
| 1002 _visitor.labelScope = innerScope; |
| 1003 statement.accept(_resolver); |
| 1004 } finally { |
| 1005 _visitor.labelScope = outerScope; |
| 1006 } |
| 1007 } catch (exception) { |
| 1008 throw new IllegalArgumentException("Could not resolve node", exception); |
| 1009 } |
| 1010 } |
| 1011 } |
OLD | NEW |