Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: pkg/analyzer/lib/src/generated/incremental_resolver.dart

Issue 750083002: Matching for import/export/part directives. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Match export combinators Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/incremental_resolver_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library engine.incremental_resolver; 5 library engine.incremental_resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'ast.dart'; 9 import 'ast.dart';
10 import 'element.dart'; 10 import 'element.dart';
11 import 'error.dart'; 11 import 'error.dart';
12 import 'java_engine.dart'; 12 import 'java_engine.dart';
13 import 'resolver.dart'; 13 import 'resolver.dart';
14 import 'scanner.dart'; 14 import 'scanner.dart';
15 import 'source.dart'; 15 import 'source.dart';
16 16
17 17
18 /** 18 /**
19 * Instances of the class [DeclarationMatcher] determine whether the element 19 * Instances of the class [DeclarationMatcher] determine whether the element
20 * model defined by a given AST structure matches an existing element model. 20 * model defined by a given AST structure matches an existing element model.
21 */ 21 */
22 class DeclarationMatcher extends RecursiveAstVisitor { 22 class DeclarationMatcher extends RecursiveAstVisitor {
23 /** 23 /**
24 * The libary containing the AST nodes being visited.
25 */
26 LibraryElement _enclosingLibrary;
27
28 /**
24 * The compilation unit containing the AST nodes being visited. 29 * The compilation unit containing the AST nodes being visited.
25 */ 30 */
26 CompilationUnitElement _enclosingUnit; 31 CompilationUnitElement _enclosingUnit;
27 32
28 /** 33 /**
29 * The function type alias containing the AST nodes being visited, or `null` i f we are not 34 * The function type alias containing the AST nodes being visited, or `null` i f we are not
30 * in the scope of a function type alias. 35 * in the scope of a function type alias.
31 */ 36 */
32 FunctionTypeAliasElement _enclosingAlias; 37 FunctionTypeAliasElement _enclosingAlias;
33 38
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 _hasConstructor = true; 144 _hasConstructor = true;
140 SimpleIdentifier constructorName = node.name; 145 SimpleIdentifier constructorName = node.name;
141 ConstructorElement element = constructorName == null ? 146 ConstructorElement element = constructorName == null ?
142 _enclosingClass.unnamedConstructor : 147 _enclosingClass.unnamedConstructor :
143 _enclosingClass.getNamedConstructor(constructorName.name); 148 _enclosingClass.getNamedConstructor(constructorName.name);
144 _processElement(element); 149 _processElement(element);
145 _assertCompatibleParameters(node.parameters, element.parameters); 150 _assertCompatibleParameters(node.parameters, element.parameters);
146 } 151 }
147 152
148 @override 153 @override
154 visitEnumConstantDeclaration(EnumConstantDeclaration node) {
155 String name = node.name.name;
156 FieldElement element = _findElement(_enclosingClass.fields, name);
157 _processElement(element);
158 }
159
160 @override
149 visitEnumDeclaration(EnumDeclaration node) { 161 visitEnumDeclaration(EnumDeclaration node) {
150 String name = node.name.name; 162 String name = node.name.name;
151 ClassElement element = _findElement(_enclosingUnit.enums, name); 163 ClassElement element = _findElement(_enclosingUnit.enums, name);
152 _enclosingClass = element; 164 _enclosingClass = element;
153 _processElement(element); 165 _processElement(element);
154 _assertTrue(element.isEnum); 166 _assertTrue(element.isEnum);
155 super.visitEnumDeclaration(node); 167 super.visitEnumDeclaration(node);
156 } 168 }
157 169
158 @override 170 @override
159 visitEnumConstantDeclaration(EnumConstantDeclaration node) { 171 visitExportDirective(ExportDirective node) {
160 String name = node.name.name; 172 String uri = _getStringValue(node.uri);
161 FieldElement element = _findElement(_enclosingClass.fields, name); 173 if (uri != null) {
162 _processElement(element); 174 ExportElement element =
175 _findUriReferencedElement(_enclosingLibrary.exports, uri);
176 _processElement(element);
177 _assertCombinators(node.combinators, element.combinators);
178 }
163 } 179 }
164 180
165 @override 181 @override
166 visitExportDirective(ExportDirective node) {
167 String uri = _getStringValue(node.uri);
168 if (uri != null) {
169 LibraryElement library = _enclosingUnit.library;
170 ExportElement exportElement = _findExport(
171 library.exports,
172 _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri));
173 _processElement(exportElement);
174 }
175 super.visitExportDirective(node);
176 }
177
178 @override
179 visitExpressionFunctionBody(ExpressionFunctionBody node) { 182 visitExpressionFunctionBody(ExpressionFunctionBody node) {
180 // ignore bodies 183 // ignore bodies
181 } 184 }
182 185
183 @override 186 @override
184 visitExtendsClause(ExtendsClause node) { 187 visitExtendsClause(ExtendsClause node) {
185 _assertSameType(node.superclass, _enclosingClass.supertype); 188 _assertSameType(node.superclass, _enclosingClass.supertype);
186 } 189 }
187 190
188 @override 191 @override
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 visitImplementsClause(ImplementsClause node) { 241 visitImplementsClause(ImplementsClause node) {
239 List<TypeName> nodes = node.interfaces; 242 List<TypeName> nodes = node.interfaces;
240 List<InterfaceType> types = _enclosingClass.interfaces; 243 List<InterfaceType> types = _enclosingClass.interfaces;
241 _assertSameTypes(nodes, types); 244 _assertSameTypes(nodes, types);
242 } 245 }
243 246
244 @override 247 @override
245 visitImportDirective(ImportDirective node) { 248 visitImportDirective(ImportDirective node) {
246 String uri = _getStringValue(node.uri); 249 String uri = _getStringValue(node.uri);
247 if (uri != null) { 250 if (uri != null) {
248 LibraryElement library = _enclosingUnit.library; 251 ImportElement element =
249 ImportElement importElement = _findImport( 252 _findUriReferencedElement(_enclosingLibrary.imports, uri);
250 library.imports, 253 _processElement(element);
251 _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri), 254 // match the prefix
252 node.prefix); 255 SimpleIdentifier prefixNode = node.prefix;
253 _processElement(importElement); 256 PrefixElement prefixElement = element.prefix;
257 if (prefixNode == null) {
258 _assertNull(prefixElement);
259 } else {
260 _assertNotNull(prefixElement);
261 _assertEquals(prefixNode.name, prefixElement.name);
262 }
263 // match combinators
264 _assertCombinators(node.combinators, element.combinators);
254 } 265 }
255 super.visitImportDirective(node);
256 } 266 }
257 267
258 @override 268 @override
259 visitMethodDeclaration(MethodDeclaration node) { 269 visitMethodDeclaration(MethodDeclaration node) {
260 // prepare element name 270 // prepare element name
261 String name = node.name.name; 271 String name = node.name.name;
262 if (name == TokenType.MINUS.lexeme && 272 if (name == TokenType.MINUS.lexeme &&
263 node.parameters.parameters.length == 0) { 273 node.parameters.parameters.length == 0) {
264 name = "unary-"; 274 name = "unary-";
265 } 275 }
(...skipping 15 matching lines...) Expand all
281 _processElement(element); 291 _processElement(element);
282 // TODO(scheglov) test returnType 292 // TODO(scheglov) test returnType
283 _assertSameType(node.returnType, element.returnType); 293 _assertSameType(node.returnType, element.returnType);
284 _assertCompatibleParameters(node.parameters, element.parameters); 294 _assertCompatibleParameters(node.parameters, element.parameters);
285 } 295 }
286 296
287 @override 297 @override
288 visitPartDirective(PartDirective node) { 298 visitPartDirective(PartDirective node) {
289 String uri = _getStringValue(node.uri); 299 String uri = _getStringValue(node.uri);
290 if (uri != null) { 300 if (uri != null) {
291 Source partSource =
292 _enclosingUnit.context.sourceFactory.resolveUri(_enclosingUnit.source, uri);
293 CompilationUnitElement element = 301 CompilationUnitElement element =
294 _findPart(_enclosingUnit.library.parts, partSource); 302 _findUriReferencedElement(_enclosingLibrary.parts, uri);
295 _processElement(element); 303 _processElement(element);
296 } 304 }
297 super.visitPartDirective(node); 305 super.visitPartDirective(node);
298 } 306 }
299 307
300 @override 308 @override
301 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { 309 visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
302 _inTopLevelVariableDeclaration = true; 310 _inTopLevelVariableDeclaration = true;
303 try { 311 try {
304 super.visitTopLevelVariableDeclaration(node); 312 super.visitTopLevelVariableDeclaration(node);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 element.type); 351 element.type);
344 } 352 }
345 353
346 @override 354 @override
347 visitWithClause(WithClause node) { 355 visitWithClause(WithClause node) {
348 List<TypeName> nodes = node.mixinTypes; 356 List<TypeName> nodes = node.mixinTypes;
349 List<InterfaceType> types = _enclosingClass.mixins; 357 List<InterfaceType> types = _enclosingClass.mixins;
350 _assertSameTypes(nodes, types); 358 _assertSameTypes(nodes, types);
351 } 359 }
352 360
361 void _assertCombinators(List<Combinator> nodeCombinators,
362 List<NamespaceCombinator> elementCombinators) {
363 // prepare shown/hidden names in the element
364 Set<String> showNames = new Set<String>();
365 Set<String> hideNames = new Set<String>();
366 for (NamespaceCombinator combinator in elementCombinators) {
367 if (combinator is ShowElementCombinator) {
368 showNames.addAll(combinator.shownNames);
369 } else if (combinator is HideElementCombinator) {
370 hideNames.addAll(combinator.hiddenNames);
371 }
372 }
373 // match combinators with the node
374 for (Combinator combinator in nodeCombinators) {
375 if (combinator is ShowCombinator) {
376 for (SimpleIdentifier nameNode in combinator.shownNames) {
377 String name = nameNode.name;
378 _assertTrue(showNames.remove(name));
379 }
380 } else if (combinator is HideCombinator) {
381 for (SimpleIdentifier nameNode in combinator.hiddenNames) {
382 String name = nameNode.name;
383 _assertTrue(hideNames.remove(name));
384 }
385 }
386 }
387 _assertTrue(showNames.isEmpty);
388 _assertTrue(hideNames.isEmpty);
389 }
390
353 void _assertCompatibleParameter(FormalParameter node, 391 void _assertCompatibleParameter(FormalParameter node,
354 ParameterElement element) { 392 ParameterElement element) {
355 if (node is SimpleFormalParameter) { 393 if (node is SimpleFormalParameter) {
356 _assertSameType(node.type, element.type); 394 _assertSameType(node.type, element.type);
357 } else { 395 } else {
358 // TODO(scheglov) support other parameter types 396 // TODO(scheglov) support other parameter types
359 _assertTrue(false); 397 _assertTrue(false);
360 } 398 }
361 // TODO(scheglov) check names of named parameters 399 // TODO(scheglov) check names of named parameters
362 } 400 }
(...skipping 19 matching lines...) Expand all
382 throw new _DeclarationMismatchException(); 420 throw new _DeclarationMismatchException();
383 } 421 }
384 } 422 }
385 423
386 void _assertNotNull(Element element) { 424 void _assertNotNull(Element element) {
387 if (element == null) { 425 if (element == null) {
388 throw new _DeclarationMismatchException(); 426 throw new _DeclarationMismatchException();
389 } 427 }
390 } 428 }
391 429
430 void _assertNull(Element element) {
431 if (element != null) {
432 throw new _DeclarationMismatchException();
433 }
434 }
435
392 void _assertSameType(TypeName node, DartType type) { 436 void _assertSameType(TypeName node, DartType type) {
393 // no return type == dynamic 437 // no return type == dynamic
394 if (node == null) { 438 if (node == null) {
395 return _assertTrue(type == null || type.isDynamic); 439 return _assertTrue(type == null || type.isDynamic);
396 } 440 }
397 // check specific type kinds 441 // check specific type kinds
398 String nodeName = node.name.name; 442 String nodeName = node.name.name;
399 if (type is InterfaceType) { 443 if (type is InterfaceType) {
400 _assertEquals(nodeName, type.name); 444 _assertEquals(nodeName, type.name);
401 // check arguments 445 // check arguments
(...skipping 22 matching lines...) Expand all
424 } 468 }
425 } 469 }
426 470
427 void _assertTrue(bool condition) { 471 void _assertTrue(bool condition) {
428 if (!condition) { 472 if (!condition) {
429 throw new _DeclarationMismatchException(); 473 throw new _DeclarationMismatchException();
430 } 474 }
431 } 475 }
432 476
433 /** 477 /**
434 * Given that the comparison is to begin with the given element, capture the e nclosing elements 478 * Given that the comparison is to begin with the given [element], capture
435 * that might be used while performing the comparison. 479 * the enclosing elements that might be used while performing the comparison.
436 *
437 * @param element the element corresponding to the AST structure to be compare d
438 */ 480 */
439 void _captureEnclosingElements(Element element) { 481 void _captureEnclosingElements(Element element) {
440 Element parent = 482 Element parent =
441 element is CompilationUnitElement ? element : element.enclosingElement; 483 element is CompilationUnitElement ? element : element.enclosingElement;
442 while (parent != null) { 484 while (parent != null) {
443 if (parent is CompilationUnitElement) { 485 if (parent is CompilationUnitElement) {
444 _enclosingUnit = parent as CompilationUnitElement; 486 _enclosingUnit = parent as CompilationUnitElement;
487 _enclosingLibrary = element.library;
445 } else if (parent is ClassElement) { 488 } else if (parent is ClassElement) {
446 if (_enclosingClass == null) { 489 if (_enclosingClass == null) {
447 _enclosingClass = parent as ClassElement; 490 _enclosingClass = parent as ClassElement;
448 } 491 }
449 } else if (parent is FunctionTypeAliasElement) { 492 } else if (parent is FunctionTypeAliasElement) {
450 if (_enclosingAlias == null) { 493 if (_enclosingAlias == null) {
451 _enclosingAlias = parent as FunctionTypeAliasElement; 494 _enclosingAlias = parent as FunctionTypeAliasElement;
452 } 495 }
453 } else if (parent is ParameterElement) { 496 } else if (parent is ParameterElement) {
454 if (_enclosingParameter == null) { 497 if (_enclosingParameter == null) {
(...skipping 10 matching lines...) Expand all
465 Element _findElement(List<Element> elements, String name) { 508 Element _findElement(List<Element> elements, String name) {
466 for (Element element in elements) { 509 for (Element element in elements) {
467 if (element.displayName == name) { 510 if (element.displayName == name) {
468 return element; 511 return element;
469 } 512 }
470 } 513 }
471 return null; 514 return null;
472 } 515 }
473 516
474 /** 517 /**
475 * Return the export element from the given array whose library has the given source, or
476 * `null` if there is no such export.
477 *
478 * @param exports the export elements being searched
479 * @param source the source of the library associated with the export element to being searched
480 * for
481 * @return the export element whose library has the given source
482 */
483 ExportElement _findExport(List<ExportElement> exports, Source source) {
484 for (ExportElement export in exports) {
485 if (export.exportedLibrary.source == source) {
486 return export;
487 }
488 }
489 return null;
490 }
491
492 /**
493 * Return the element in the given array of elements that was created for the declaration with the 518 * Return the element in the given array of elements that was created for the declaration with the
494 * given name. 519 * given name.
495 * 520 *
496 * @param elements the elements of the appropriate kind that exist in the curr ent context 521 * @param elements the elements of the appropriate kind that exist in the curr ent context
497 * @param identifier the name node in the declaration of the element to be ret urned 522 * @param identifier the name node in the declaration of the element to be ret urned
498 * @return the element created for the declaration with the given name 523 * @return the element created for the declaration with the given name
499 */ 524 */
500 Element _findIdentifier(List<Element> elements, 525 Element _findIdentifier(List<Element> elements,
501 SimpleIdentifier identifier) => 526 SimpleIdentifier identifier) =>
502 _findWithNameAndOffset(elements, identifier.name, identifier.offset); 527 _findWithNameAndOffset(elements, identifier.name, identifier.offset);
503 528
504 /** 529 /**
505 * Return the import element from the given array whose library has the given source and that has
506 * the given prefix, or `null` if there is no such import.
507 *
508 * @param imports the import elements being searched
509 * @param source the source of the library associated with the import element to being searched
510 * for
511 * @param prefix the prefix with which the library was imported
512 * @return the import element whose library has the given source and prefix
513 */
514 ImportElement _findImport(List<ImportElement> imports, Source source,
515 SimpleIdentifier prefix) {
516 for (ImportElement element in imports) {
517 if (element.importedLibrary.source == source) {
518 PrefixElement prefixElement = element.prefix;
519 if (prefix == null) {
520 if (prefixElement == null) {
521 return element;
522 }
523 } else {
524 if (prefixElement != null &&
525 prefix.name == prefixElement.displayName) {
526 return element;
527 }
528 }
529 }
530 }
531 return null;
532 }
533
534 /**
535 * Return the element for the part with the given source, or `null` if there i s no element
536 * for the given source.
537 *
538 * @param parts the elements for the parts
539 * @param partSource the source for the part whose element is to be returned
540 * @return the element for the part with the given source
541 */
542 CompilationUnitElement _findPart(List<CompilationUnitElement> parts,
543 Source partSource) {
544 for (CompilationUnitElement part in parts) {
545 if (part.source == partSource) {
546 return part;
547 }
548 }
549 return null;
550 }
551
552 /**
553 * Return the element in the given array of elements that was created for the declaration with the 530 * Return the element in the given array of elements that was created for the declaration with the
554 * given name at the given offset. 531 * given name at the given offset.
555 * 532 *
556 * @param elements the elements of the appropriate kind that exist in the curr ent context 533 * @param elements the elements of the appropriate kind that exist in the curr ent context
557 * @param name the name of the element to be returned 534 * @param name the name of the element to be returned
558 * @param offset the offset of the name of the element to be returned 535 * @param offset the offset of the name of the element to be returned
559 * @return the element with the given name and offset 536 * @return the element with the given name and offset
560 */ 537 */
561 Element _findWithNameAndOffset(List<Element> elements, String name, 538 Element _findWithNameAndOffset(List<Element> elements, String name,
562 int offset) { 539 int offset) {
563 for (Element element in elements) { 540 for (Element element in elements) {
564 if (element.displayName == name && element.nameOffset == offset) { 541 if (element.displayName == name && element.nameOffset == offset) {
565 return element; 542 return element;
566 } 543 }
567 } 544 }
568 return null; 545 return null;
569 } 546 }
570 547
571 void _gatherElements(Element element) { 548 void _gatherElements(Element element) {
572 element.accept(new _ElementsGatherer(this)); 549 _ElementsGatherer gatherer = new _ElementsGatherer(this);
550 element.accept(gatherer);
551 // TODO(scheglov) push into CompilationUnitElement
552 if (identical(_enclosingUnit, _enclosingLibrary.definingCompilationUnit)) {
553 gatherer.addElements(_enclosingLibrary.imports);
554 gatherer.addElements(_enclosingLibrary.exports);
555 gatherer.addElements(_enclosingLibrary.parts);
556 }
573 } 557 }
574 558
575 /** 559 /**
576 * Return the value of the given string literal, or `null` if the string is no t a constant 560 * Return the value of the given string literal, or `null` if the string is no t a constant
577 * string without any string interpolation. 561 * string without any string interpolation.
578 * 562 *
579 * @param literal the string literal whose value is to be returned 563 * @param literal the string literal whose value is to be returned
580 * @return the value of the given string literal 564 * @return the value of the given string literal
581 */ 565 */
582 String _getStringValue(StringLiteral literal) { 566 String _getStringValue(StringLiteral literal) {
583 if (literal is StringInterpolation) { 567 if (literal is StringInterpolation) {
584 return null; 568 return null;
585 } 569 }
586 return literal.stringValue; 570 return literal.stringValue;
587 } 571 }
588 572
589 void _processElement(Element element) { 573 void _processElement(Element element) {
590 _assertNotNull(element); 574 _assertNotNull(element);
591 if (!_allElements.contains(element)) { 575 if (!_allElements.contains(element)) {
592 throw new _DeclarationMismatchException(); 576 throw new _DeclarationMismatchException();
593 } 577 }
594 _unmatchedElements.remove(element); 578 _unmatchedElements.remove(element);
595 } 579 }
580
581 /**
582 * Return the [UriReferencedElement] from [elements] with the given [uri], or
583 * `null` if there is no such element.
584 */
585 static UriReferencedElement
586 _findUriReferencedElement(List<UriReferencedElement> elements, String uri) {
587 for (UriReferencedElement element in elements) {
588 if (element.uri == uri) {
589 return element;
590 }
591 }
592 return null;
593 }
596 } 594 }
597 595
598 596
599 /** 597 /**
600 * Instances of the class [IncrementalResolver] resolve the smallest portion of 598 * Instances of the class [IncrementalResolver] resolve the smallest portion of
601 * an AST structure that we currently know how to resolve. 599 * an AST structure that we currently know how to resolve.
602 */ 600 */
603 class IncrementalResolver { 601 class IncrementalResolver {
604 /** 602 /**
605 * The error listener that will be informed of any errors that are found 603 * The error listener that will be informed of any errors that are found
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 super.visitElement(element); 924 super.visitElement(element);
927 } 925 }
928 } 926 }
929 927
930 928
931 class _ElementsGatherer extends GeneralizingElementVisitor { 929 class _ElementsGatherer extends GeneralizingElementVisitor {
932 final DeclarationMatcher matcher; 930 final DeclarationMatcher matcher;
933 931
934 _ElementsGatherer(this.matcher); 932 _ElementsGatherer(this.matcher);
935 933
934 void addElements(List<Element> elements) {
935 for (Element element in elements) {
936 if (!element.isSynthetic) {
937 _addElement(element);
938 }
939 }
940 }
941
936 @override 942 @override
937 visitElement(Element element) { 943 visitElement(Element element) {
938 _addElement(element); 944 _addElement(element);
939 super.visitElement(element); 945 super.visitElement(element);
940 } 946 }
941 947
942 @override 948 @override
943 visitExecutableElement(ExecutableElement element) { 949 visitExecutableElement(ExecutableElement element) {
944 _addElement(element); 950 _addElement(element);
945 } 951 }
(...skipping 14 matching lines...) Expand all
960 // Don't visit children (such as property accessors). 966 // Don't visit children (such as property accessors).
961 } 967 }
962 968
963 void _addElement(Element element) { 969 void _addElement(Element element) {
964 if (element != null) { 970 if (element != null) {
965 matcher._allElements.add(element); 971 matcher._allElements.add(element);
966 matcher._unmatchedElements.add(element); 972 matcher._unmatchedElements.add(element);
967 } 973 }
968 } 974 }
969 } 975 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/incremental_resolver_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698