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

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

Issue 1863103002: Add an UNUSED_SHOWN_NAMES hint to the analyzer (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months 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
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 analyzer.src.generated.resolver; 5 library analyzer.src.generated.resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 4093 matching lines...) Expand 10 before | Expand all | Expand 10 after
4104 } 4104 }
4105 4105
4106 @override 4106 @override
4107 void visitPrefixedIdentifier(PrefixedIdentifier node) { 4107 void visitPrefixedIdentifier(PrefixedIdentifier node) {
4108 // If the prefixed identifier references some A.B, where A is a library 4108 // If the prefixed identifier references some A.B, where A is a library
4109 // prefix, then we can lookup the associated ImportDirective in 4109 // prefix, then we can lookup the associated ImportDirective in
4110 // prefixElementMap and remove it from the unusedImports list. 4110 // prefixElementMap and remove it from the unusedImports list.
4111 SimpleIdentifier prefixIdentifier = node.prefix; 4111 SimpleIdentifier prefixIdentifier = node.prefix;
4112 Element element = prefixIdentifier.staticElement; 4112 Element element = prefixIdentifier.staticElement;
4113 if (element is PrefixElement) { 4113 if (element is PrefixElement) {
4114 usedElements.prefixes.add(element); 4114 List<SimpleIdentifier> list = usedElements.prefixes[element];
Brian Wilkerson 2016/04/06 15:17:40 usedElements.prefixes.putIfAbsent(element, () => <
srawlins 2016/04/07 15:27:23 Done.
4115 if (list == null) {
4116 list = <SimpleIdentifier>[];
4117 usedElements.prefixes[element] = list;
4118 }
4119 list.add(node.identifier);
4115 return; 4120 return;
4116 } 4121 }
4117 // Otherwise, pass the prefixed identifier element and name onto 4122 // Otherwise, pass the prefixed identifier element and name onto
4118 // visitIdentifier. 4123 // visitIdentifier.
4119 _visitIdentifier(element, prefixIdentifier.name); 4124 _visitIdentifier(element, prefixIdentifier.name);
4120 } 4125 }
4121 4126
4122 @override 4127 @override
4123 void visitSimpleIdentifier(SimpleIdentifier node) { 4128 void visitSimpleIdentifier(SimpleIdentifier node) {
4124 _visitIdentifier(node.staticElement, node.name); 4129 _visitIdentifier(node.staticElement, node.name);
(...skipping 13 matching lines...) Expand all
4138 } 4143 }
4139 // If the element is multiply defined then call this method recursively for 4144 // If the element is multiply defined then call this method recursively for
4140 // each of the conflicting elements. 4145 // each of the conflicting elements.
4141 if (element is MultiplyDefinedElement) { 4146 if (element is MultiplyDefinedElement) {
4142 MultiplyDefinedElement multiplyDefinedElement = element; 4147 MultiplyDefinedElement multiplyDefinedElement = element;
4143 for (Element elt in multiplyDefinedElement.conflictingElements) { 4148 for (Element elt in multiplyDefinedElement.conflictingElements) {
4144 _visitIdentifier(elt, name); 4149 _visitIdentifier(elt, name);
4145 } 4150 }
4146 return; 4151 return;
4147 } else if (element is PrefixElement) { 4152 } else if (element is PrefixElement) {
4148 usedElements.prefixes.add(element); 4153 List<SimpleIdentifier> list = usedElements.prefixes[element];
4154 if (list == null) {
4155 list = <SimpleIdentifier>[];
4156 usedElements.prefixes[element] = list;
4157 }
4149 return; 4158 return;
4150 } else if (element.enclosingElement is! CompilationUnitElement) { 4159 } else if (element.enclosingElement is! CompilationUnitElement) {
4151 // Identifiers that aren't a prefix element and whose enclosing element 4160 // Identifiers that aren't a prefix element and whose enclosing element
4152 // isn't a CompilationUnit are ignored- this covers the case the 4161 // isn't a CompilationUnit are ignored- this covers the case the
4153 // identifier is a relative-reference, a reference to an identifier not 4162 // identifier is a relative-reference, a reference to an identifier not
4154 // imported by this library. 4163 // imported by this library.
4155 return; 4164 return;
4156 } 4165 }
4157 // Ignore if an unknown library. 4166 // Ignore if an unknown library.
4158 LibraryElement containingLibrary = element.library; 4167 LibraryElement containingLibrary = element.library;
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
4368 CompilationUnit definingUnit = _compilationUnits[0]; 4377 CompilationUnit definingUnit = _compilationUnits[0];
4369 ErrorReporter definingUnitErrorReporter = 4378 ErrorReporter definingUnitErrorReporter =
4370 new ErrorReporter(_errorListener, definingUnit.element.source); 4379 new ErrorReporter(_errorListener, definingUnit.element.source);
4371 { 4380 {
4372 ImportsVerifier importsVerifier = new ImportsVerifier(); 4381 ImportsVerifier importsVerifier = new ImportsVerifier();
4373 importsVerifier.addImports(definingUnit); 4382 importsVerifier.addImports(definingUnit);
4374 importsVerifier 4383 importsVerifier
4375 .removeUsedElements(_usedImportedElementsVisitor.usedElements); 4384 .removeUsedElements(_usedImportedElementsVisitor.usedElements);
4376 importsVerifier.generateDuplicateImportHints(definingUnitErrorReporter); 4385 importsVerifier.generateDuplicateImportHints(definingUnitErrorReporter);
4377 importsVerifier.generateUnusedImportHints(definingUnitErrorReporter); 4386 importsVerifier.generateUnusedImportHints(definingUnitErrorReporter);
4387 importsVerifier.generateUnusedShownNameHints(definingUnitErrorReporter);
4378 } 4388 }
4379 _library.accept(new UnusedLocalElementsVerifier( 4389 _library.accept(new UnusedLocalElementsVerifier(
4380 _errorListener, _usedLocalElementsVisitor.usedElements)); 4390 _errorListener, _usedLocalElementsVisitor.usedElements));
4381 }); 4391 });
4382 } 4392 }
4383 4393
4384 void _generateForCompilationUnit(CompilationUnit unit, Source source) { 4394 void _generateForCompilationUnit(CompilationUnit unit, Source source) {
4385 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); 4395 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source);
4386 unit.accept(_usedImportedElementsVisitor); 4396 unit.accept(_usedImportedElementsVisitor);
4387 // dead code analysis 4397 // dead code analysis
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
4450 /** 4460 /**
4451 * Initialize a newly created scope to represent a switch statement or loop 4461 * Initialize a newly created scope to represent a switch statement or loop
4452 * nested within the current scope. [statement] is the statement associated 4462 * nested within the current scope. [statement] is the statement associated
4453 * with the newly created scope. 4463 * with the newly created scope.
4454 */ 4464 */
4455 ImplicitLabelScope nest(Statement statement) => 4465 ImplicitLabelScope nest(Statement statement) =>
4456 new ImplicitLabelScope._(this, statement); 4466 new ImplicitLabelScope._(this, statement);
4457 } 4467 }
4458 4468
4459 /** 4469 /**
4460 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the 4470 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the source code
4461 * source code verifying that all of the imports are used, otherwise a 4471 * verifying that all of the imports are used, otherwise a [HintCode.UNUSED_IMPO RT] hint is
4462 * [HintCode.UNUSED_IMPORT] is generated with 4472 * generated with [generateUnusedImportHints].
4463 * [generateUnusedImportHints]. 4473 *
4474 * Additionally, [generateDuplicateImportHints] generates [HintCode.DUPLICATE_IM PORT] hints and
4475 * [HintCode.UNUSED_SHOWN_NAME] hints.
4464 * 4476 *
4465 * While this class does not yet have support for an "Organize Imports" action, this logic built up 4477 * While this class does not yet have support for an "Organize Imports" action, this logic built up
4466 * in this class could be used for such an action in the future. 4478 * in this class could be used for such an action in the future.
4467 */ 4479 */
4468 class ImportsVerifier { 4480 class ImportsVerifier {
4469 /** 4481 /**
4470 * A list of [ImportDirective]s that the current library imports, as identifie rs are visited 4482 * A list of [ImportDirective]s that the current library imports, but does not use.
4471 * by this visitor and an import has been identified as being used by the libr ary, the 4483 *
4472 * [ImportDirective] is removed from this list. After all the sources in the l ibrary have 4484 * As identifiers are visited by this visitor and an import has been identifie d as being used
4473 * been evaluated, this list represents the set of unused imports. 4485 * by the library, the [ImportDirective] is removed from this list. After all the sources in the
4486 * library have been evaluated, this list represents the set of unused imports .
4474 * 4487 *
4475 * See [ImportsVerifier.generateUnusedImportErrors]. 4488 * See [ImportsVerifier.generateUnusedImportErrors].
4476 */ 4489 */
4477 final List<ImportDirective> _unusedImports = <ImportDirective>[]; 4490 final List<ImportDirective> _unusedImports = <ImportDirective>[];
4478 4491
4479 /** 4492 /**
4480 * After the list of [unusedImports] has been computed, this list is a proper subset of the 4493 * After the list of [unusedImports] has been computed, this list is a proper subset of the
4481 * unused imports that are listed more than once. 4494 * unused imports that are listed more than once.
4482 */ 4495 */
4483 final List<ImportDirective> _duplicateImports = <ImportDirective>[]; 4496 final List<ImportDirective> _duplicateImports = <ImportDirective>[];
4484 4497
4485 /** 4498 /**
4486 * This is a map between the set of [LibraryElement]s that the current library imports, and 4499 * This is a map between the set of [LibraryElement]s that the current library imports, and the
4487 * a list of [ImportDirective]s that imports the library. In cases where the c urrent library 4500 * list of [ImportDirective]s that import each [LibraryElement]. In cases wher e the current
4488 * imports a library with a single directive (such as `import lib1.dart;`), th e library 4501 * library imports a library with a single directive (such as `import lib1.dar t;`), the library
4489 * element will map to a list of one [ImportDirective], which will then be rem oved from the 4502 * element will map to a list of one [ImportDirective], which will then be rem oved from the
4490 * [unusedImports] list. In cases where the current library imports a library with multiple 4503 * [unusedImports] list. In cases where the current library imports a library with multiple
4491 * directives (such as `import lib1.dart; import lib1.dart show C;`), the 4504 * directives (such as `import lib1.dart; import lib1.dart show C;`), the [Lib raryElement] will
4492 * [LibraryElement] will be mapped to a list of the import directives, and the namespace 4505 * be mapped to a list of the import directives, and the namespace will need t o be used to
4493 * will need to be used to compute the correct [ImportDirective] being used, s ee 4506 * compute the correct [ImportDirective] being used; see [_namespaceMap].
4494 * [namespaceMap].
4495 */ 4507 */
4496 final HashMap<LibraryElement, List<ImportDirective>> _libraryMap = 4508 final HashMap<LibraryElement, List<ImportDirective>> _libraryMap =
4497 new HashMap<LibraryElement, List<ImportDirective>>(); 4509 new HashMap<LibraryElement, List<ImportDirective>>();
4498 4510
4499 /** 4511 /**
4500 * In cases where there is more than one import directive per library element, this mapping is 4512 * In cases where there is more than one import directive per library element, this mapping is
4501 * used to determine which of the multiple import directives are used by gener ating a 4513 * used to determine which of the multiple import directives are used by gener ating a
4502 * [Namespace] for each of the imports to do lookups in the same way that they are done from 4514 * [Namespace] for each of the imports to do lookups in the same way that they are done from
4503 * the [ElementResolver]. 4515 * the [ElementResolver].
4504 */ 4516 */
4505 final HashMap<ImportDirective, Namespace> _namespaceMap = 4517 final HashMap<ImportDirective, Namespace> _namespaceMap =
4506 new HashMap<ImportDirective, Namespace>(); 4518 new HashMap<ImportDirective, Namespace>();
4507 4519
4508 /** 4520 /**
4509 * This is a map between prefix elements and the import directives from which they are derived. In 4521 * This is a map between prefix elements and the import directives from which they are derived. In
4510 * cases where a type is referenced via a prefix element, the import directive can be marked as 4522 * cases where a type is referenced via a prefix element, the import directive can be marked as
4511 * used (removed from the unusedImports) by looking at the resolved `lib` in ` lib.X`, 4523 * used (removed from the unusedImports) by looking at the resolved `lib` in ` lib.X`,
4512 * instead of looking at which library the `lib.X` resolves. 4524 * instead of looking at which library the `lib.X` resolves.
4513 * 4525 *
4514 * TODO (jwren) Since multiple [ImportDirective]s can share the same [PrefixEl ement], 4526 * TODO (jwren) Since multiple [ImportDirective]s can share the same [PrefixEl ement],
4515 * it is possible to have an unreported unused import in situations where two imports use the same 4527 * it is possible to have an unreported unused import in situations where two imports use the same
4516 * prefix and at least one import directive is used. 4528 * prefix and at least one import directive is used.
4517 */ 4529 */
4518 final HashMap<PrefixElement, List<ImportDirective>> _prefixElementMap = 4530 final HashMap<PrefixElement, List<ImportDirective>> _prefixElementMap =
4519 new HashMap<PrefixElement, List<ImportDirective>>(); 4531 new HashMap<PrefixElement, List<ImportDirective>>();
4520 4532
4533 /**
4534 * A map of identifiers that the current library's imports show, but that the library does not
4535 * use.
4536 *
4537 * Each import directive maps to a list of the identifiers that are imported v ia the "show"
4538 * keyword.
4539 *
4540 * As each identifier is visited by this visitor, it is identified as being us ed by the library,
4541 * and the identifier is removed from this map (under the import that imported it). After all the
4542 * sources in the library have been evaluated, each list in this map's values present the set of
4543 * unused shown elements.
4544 *
4545 * See [ImportsVerifier.generateUnusedShownNameHints].
4546 */
4547 final HashMap<ImportDirective, List<SimpleIdentifier>> _unusedShownNamesMap =
4548 new HashMap<ImportDirective, List<SimpleIdentifier>>();
4549
4521 void addImports(CompilationUnit node) { 4550 void addImports(CompilationUnit node) {
4522 for (Directive directive in node.directives) { 4551 for (Directive directive in node.directives) {
4523 if (directive is ImportDirective) { 4552 if (directive is ImportDirective) {
4524 ImportDirective importDirective = directive; 4553 ImportDirective importDirective = directive;
4525 LibraryElement libraryElement = importDirective.uriElement; 4554 LibraryElement libraryElement = importDirective.uriElement;
4526 if (libraryElement != null) { 4555 if (libraryElement == null) {
4527 _unusedImports.add(importDirective); 4556 continue;
Brian Wilkerson 2016/04/06 15:17:40 FWIW, I actually preferred the code the way it was
srawlins 2016/04/07 15:27:23 Acknowledged.
4528 // 4557 }
4529 // Initialize prefixElementMap 4558 _unusedImports.add(importDirective);
4530 // 4559 //
4531 if (importDirective.asKeyword != null) { 4560 // Initialize prefixElementMap
4532 SimpleIdentifier prefixIdentifier = importDirective.prefix; 4561 //
4533 if (prefixIdentifier != null) { 4562 if (importDirective.asKeyword != null) {
4534 Element element = prefixIdentifier.staticElement; 4563 SimpleIdentifier prefixIdentifier = importDirective.prefix;
4535 if (element is PrefixElement) { 4564 if (prefixIdentifier != null) {
4536 PrefixElement prefixElementKey = element; 4565 Element element = prefixIdentifier.staticElement;
4537 List<ImportDirective> list = 4566 if (element is PrefixElement) {
4538 _prefixElementMap[prefixElementKey]; 4567 PrefixElement prefixElementKey = element;
4539 if (list == null) { 4568 List<ImportDirective> list = _prefixElementMap[prefixElementKey];
4540 list = new List<ImportDirective>(); 4569 if (list == null) {
4541 _prefixElementMap[prefixElementKey] = list; 4570 list = new List<ImportDirective>();
4542 } 4571 _prefixElementMap[prefixElementKey] = list;
4543 list.add(importDirective);
4544 } 4572 }
4545 // TODO (jwren) Can the element ever not be a PrefixElement? 4573 list.add(importDirective);
4546 } 4574 }
4575 // TODO (jwren) Can the element ever not be a PrefixElement?
4547 } 4576 }
4548 //
4549 // Initialize libraryMap: libraryElement -> importDirective
4550 //
4551 _putIntoLibraryMap(libraryElement, importDirective);
4552 //
4553 // For this new addition to the libraryMap, also recursively add any
4554 // exports from the libraryElement.
4555 //
4556 _addAdditionalLibrariesForExports(
4557 libraryElement, importDirective, new List<LibraryElement>());
4558 } 4577 }
4578 //
4579 // Initialize libraryMap: libraryElement -> importDirective
4580 //
4581 _putIntoLibraryMap(libraryElement, importDirective);
4582 //
4583 // For this new addition to the libraryMap, also recursively add any
4584 // exports from the libraryElement.
4585 //
4586 _addAdditionalLibrariesForExports(
4587 libraryElement, importDirective, new List<LibraryElement>());
4588 _addShownNames(importDirective);
4559 } 4589 }
4560 } 4590 }
4561 if (_unusedImports.length > 1) { 4591 if (_unusedImports.length > 1) {
4562 // order the list of unusedImports to find duplicates in faster than 4592 // order the list of unusedImports to find duplicates in faster than
4563 // O(n^2) time 4593 // O(n^2) time
4564 List<ImportDirective> importDirectiveArray = 4594 List<ImportDirective> importDirectiveArray =
4565 new List<ImportDirective>.from(_unusedImports); 4595 new List<ImportDirective>.from(_unusedImports);
4566 importDirectiveArray.sort(ImportDirective.COMPARATOR); 4596 importDirectiveArray.sort(ImportDirective.COMPARATOR);
4567 ImportDirective currentDirective = importDirectiveArray[0]; 4597 ImportDirective currentDirective = importDirectiveArray[0];
4568 for (int i = 1; i < importDirectiveArray.length; i++) { 4598 for (int i = 1; i < importDirectiveArray.length; i++) {
(...skipping 22 matching lines...) Expand all
4591 * hints to 4621 * hints to
4592 */ 4622 */
4593 void generateDuplicateImportHints(ErrorReporter errorReporter) { 4623 void generateDuplicateImportHints(ErrorReporter errorReporter) {
4594 for (ImportDirective duplicateImport in _duplicateImports) { 4624 for (ImportDirective duplicateImport in _duplicateImports) {
4595 errorReporter.reportErrorForNode( 4625 errorReporter.reportErrorForNode(
4596 HintCode.DUPLICATE_IMPORT, duplicateImport.uri); 4626 HintCode.DUPLICATE_IMPORT, duplicateImport.uri);
4597 } 4627 }
4598 } 4628 }
4599 4629
4600 /** 4630 /**
4601 * After all of the compilation units have been visited by this visitor, this method can be called 4631 * Report an [HintCode.UNUSED_IMPORT] hint for each unused import.
4602 * to report an [HintCode.UNUSED_IMPORT] hint for each of the import directive s in the
4603 * [unusedImports] list.
4604 * 4632 *
4605 * @param errorReporter the error reporter to report the set of [HintCode.UNUS ED_IMPORT] 4633 * Only call this method after all of the compilation units have been visited by this visitor.
4606 * hints to 4634 *
4635 * @param errorReporter the error reporter used to report the set of [HintCode .UNUSED_IMPORT]
4636 * hints
4607 */ 4637 */
4608 void generateUnusedImportHints(ErrorReporter errorReporter) { 4638 void generateUnusedImportHints(ErrorReporter errorReporter) {
4609 for (ImportDirective unusedImport in _unusedImports) { 4639 for (ImportDirective unusedImport in _unusedImports) {
4610 // Check that the import isn't dart:core 4640 // Check that the import isn't dart:core
4611 ImportElement importElement = unusedImport.element; 4641 ImportElement importElement = unusedImport.element;
4612 if (importElement != null) { 4642 if (importElement != null) {
4613 LibraryElement libraryElement = importElement.importedLibrary; 4643 LibraryElement libraryElement = importElement.importedLibrary;
4614 if (libraryElement != null && libraryElement.isDartCore) { 4644 if (libraryElement != null && libraryElement.isDartCore) {
4615 continue; 4645 continue;
4616 } 4646 }
4617 } 4647 }
4618 errorReporter.reportErrorForNode( 4648 errorReporter.reportErrorForNode(
4619 HintCode.UNUSED_IMPORT, unusedImport.uri); 4649 HintCode.UNUSED_IMPORT, unusedImport.uri);
4620 } 4650 }
4621 } 4651 }
4622 4652
4623 /** 4653 /**
4654 * Report an [HintCode.UNUSED_SHOWN_NAME] hint for each unused shown name.
4655 *
4656 * Only call this method after all of the compilation units have been visited by this visitor.
4657 *
4658 * @param errorReporter the error reporter used to report the set of [HintCode .UNUSED_SHOWN_NAME]
4659 * hints
4660 */
4661 void generateUnusedShownNameHints(ErrorReporter reporter) {
4662 _unusedShownNamesMap.forEach((ImportDirective importDirective,
4663 List<SimpleIdentifier> identifiers) {
4664 if (_unusedImports.contains(importDirective)) {
4665 // This import is actually wholly unused, not just one or more shown nam es from it.
4666 // This is then an "unused import", rather than unused shown names.
4667 return;
4668 }
4669 for (var identifier in identifiers) {
Brian Wilkerson 2016/04/06 15:17:40 nit: we fully type annotate everything in the anal
srawlins 2016/04/07 15:27:23 Done.
4670 reporter.reportErrorForNode(HintCode.UNUSED_SHOWN_NAME, identifier);
4671 }
4672 });
4673 }
4674
4675 /**
4624 * Remove elements from [_unusedImports] using the given [usedElements]. 4676 * Remove elements from [_unusedImports] using the given [usedElements].
4625 */ 4677 */
4626 void removeUsedElements(UsedImportedElements usedElements) { 4678 void removeUsedElements(UsedImportedElements usedElements) {
4627 // Stop if all the imports are known to be used. 4679 // Stop if all the imports and shown names are known to be used.
4628 if (_unusedImports.isEmpty) { 4680 if (_unusedImports.isEmpty && _unusedShownNamesMap.isEmpty) {
4629 return; 4681 return;
4630 } 4682 }
4631 // Process import prefixes. 4683 // Process import prefixes.
4632 for (PrefixElement prefix in usedElements.prefixes) { 4684 usedElements.prefixes.forEach((PrefixElement prefix, List<SimpleIdentifier> elements) {
4633 List<ImportDirective> importDirectives = _prefixElementMap[prefix]; 4685 List<ImportDirective> importDirectives = _prefixElementMap[prefix];
4634 if (importDirectives != null) { 4686 if (importDirectives != null) {
4635 for (ImportDirective importDirective in importDirectives) { 4687 for (ImportDirective importDirective in importDirectives) {
4636 _unusedImports.remove(importDirective); 4688 _unusedImports.remove(importDirective);
4689 for (SimpleIdentifier element in elements) {
4690 _removeFromUnusedShownNamesMap(element.staticElement, importDirectiv e);
4691 }
4637 } 4692 }
4638 } 4693 }
4639 } 4694 });
4640 // Process top-level elements. 4695 // Process top-level elements.
4641 for (Element element in usedElements.elements) { 4696 for (Element element in usedElements.elements) {
4642 // Stop if all the imports are known to be used. 4697 // Stop if all the imports and shown names are known to be used.
4643 if (_unusedImports.isEmpty) { 4698 if (_unusedImports.isEmpty && _unusedShownNamesMap.isEmpty) {
4644 return; 4699 return;
4645 } 4700 }
4646 // Prepare import directives for this library. 4701 // Prepare import directives for this element's library.
4647 LibraryElement library = element.library; 4702 LibraryElement library = element.library;
4648 List<ImportDirective> importsLibrary = _libraryMap[library]; 4703 List<ImportDirective> importsLibrary = _libraryMap[library];
4649 if (importsLibrary == null) { 4704 if (importsLibrary == null) {
4705 // element's library is not imported. Must be the current library.
4650 continue; 4706 continue;
4651 } 4707 }
4652 // If there is only one import directive for this library, then it must be 4708 // If there is only one import directive for this library, then it must be
4653 // the directive that this element is imported with, remove it from the 4709 // the directive that this element is imported with, remove it from the
4654 // unusedImports list. 4710 // unusedImports list.
4655 if (importsLibrary.length == 1) { 4711 if (importsLibrary.length == 1) {
4656 ImportDirective usedImportDirective = importsLibrary[0]; 4712 ImportDirective usedImportDirective = importsLibrary[0];
4657 _unusedImports.remove(usedImportDirective); 4713 _unusedImports.remove(usedImportDirective);
4714 _removeFromUnusedShownNamesMap(element, usedImportDirective);
4658 continue; 4715 continue;
4659 } 4716 }
4660 // Otherwise, find import directives using namespaces. 4717 // Otherwise, find import directives using namespaces.
4661 String name = element.displayName; 4718 String name = element.displayName;
4662 for (ImportDirective importDirective in importsLibrary) { 4719 for (ImportDirective importDirective in importsLibrary) {
4663 Namespace namespace = _computeNamespace(importDirective); 4720 Namespace namespace = _computeNamespace(importDirective);
4664 if (namespace != null && namespace.get(name) != null) { 4721 if (namespace != null && namespace.get(name) != null) {
4665 _unusedImports.remove(importDirective); 4722 _unusedImports.remove(importDirective);
4723 _removeFromUnusedShownNamesMap(element, importDirective);
4666 } 4724 }
4667 } 4725 }
4668 } 4726 }
4669 } 4727 }
4670 4728
4671 /** 4729 /**
4730 * Remove [element] from the list of names shown by [importDirective].
4731 */
4732 void _removeFromUnusedShownNamesMap(Element element,
4733 ImportDirective importDirective) {
4734 List<SimpleIdentifier> list = _unusedShownNamesMap[importDirective];
scheglov 2016/04/06 15:34:39 Could you use a more specific name than "list"?
srawlins 2016/04/07 15:27:23 Done.
4735 if (list == null) {
4736 return;
4737 }
4738 for (var identifier in list) {
4739 if (identifier.staticElement == element) {
4740 list.remove(identifier);
4741 break;
4742 }
4743 }
4744 if (list.isEmpty) {
4745 _unusedShownNamesMap.remove(importDirective);
4746 }
4747 }
4748
4749 /**
4672 * Recursively add any exported library elements into the [libraryMap]. 4750 * Recursively add any exported library elements into the [libraryMap].
4673 */ 4751 */
4674 void _addAdditionalLibrariesForExports(LibraryElement library, 4752 void _addAdditionalLibrariesForExports(LibraryElement library,
4675 ImportDirective importDirective, List<LibraryElement> exportPath) { 4753 ImportDirective importDirective, List<LibraryElement> exportPath) {
4676 if (exportPath.contains(library)) { 4754 if (exportPath.contains(library)) {
4677 return; 4755 return;
4678 } 4756 }
4679 exportPath.add(library); 4757 exportPath.add(library);
4680 for (LibraryElement exportedLibraryElt in library.exportedLibraries) { 4758 for (LibraryElement exportedLibraryElt in library.exportedLibraries) {
4681 _putIntoLibraryMap(exportedLibraryElt, importDirective); 4759 _putIntoLibraryMap(exportedLibraryElt, importDirective);
4682 _addAdditionalLibrariesForExports( 4760 _addAdditionalLibrariesForExports(
4683 exportedLibraryElt, importDirective, exportPath); 4761 exportedLibraryElt, importDirective, exportPath);
4684 } 4762 }
4685 } 4763 }
4686 4764
4687 /** 4765 /**
4688 * Lookup and return the [Namespace] from the [namespaceMap], if the map does not 4766 * Lookup and return the [Namespace] from the [_namespaceMap].
4689 * have the computed namespace, compute it and cache it in the map. If the imp ort directive is not 4767 *
4690 * resolved or is not resolvable, `null` is returned. 4768 * If the map does not have the computed namespace, compute it and cache it in the map. If
4769 * [importDirective] is not resolved or is not resolvable, `null` is returned.
4691 * 4770 *
4692 * @param importDirective the import directive used to compute the returned na mespace 4771 * @param importDirective the import directive used to compute the returned na mespace
4693 * @return the computed or looked up [Namespace] 4772 * @return the computed or looked up [Namespace]
4694 */ 4773 */
4695 Namespace _computeNamespace(ImportDirective importDirective) { 4774 Namespace _computeNamespace(ImportDirective importDirective) {
4696 Namespace namespace = _namespaceMap[importDirective]; 4775 Namespace namespace = _namespaceMap[importDirective];
4697 if (namespace == null) { 4776 if (namespace == null) {
4698 // If the namespace isn't in the namespaceMap, then compute and put it in 4777 // If the namespace isn't in the namespaceMap, then compute and put it in
4699 // the map. 4778 // the map.
4700 ImportElement importElement = importDirective.element; 4779 ImportElement importElement = importDirective.element;
(...skipping 14 matching lines...) Expand all
4715 */ 4794 */
4716 void _putIntoLibraryMap( 4795 void _putIntoLibraryMap(
4717 LibraryElement libraryElement, ImportDirective importDirective) { 4796 LibraryElement libraryElement, ImportDirective importDirective) {
4718 List<ImportDirective> importList = _libraryMap[libraryElement]; 4797 List<ImportDirective> importList = _libraryMap[libraryElement];
4719 if (importList == null) { 4798 if (importList == null) {
4720 importList = new List<ImportDirective>(); 4799 importList = new List<ImportDirective>();
4721 _libraryMap[libraryElement] = importList; 4800 _libraryMap[libraryElement] = importList;
4722 } 4801 }
4723 importList.add(importDirective); 4802 importList.add(importDirective);
4724 } 4803 }
4804
4805 /**
4806 * Add every shown name from [importDirective] into [_unusedShownNamesMap].
4807 */
4808 void _addShownNames(ImportDirective importDirective) {
4809 if (importDirective.combinators == null) {
4810 return;
4811 }
4812 List list = new List<SimpleIdentifier>();
scheglov 2016/04/06 15:34:39 1. Add type arguments. 2. Use a better name.
srawlins 2016/04/07 15:27:23 Done.
4813 _unusedShownNamesMap[importDirective] = list;
4814 for (Combinator combinator in importDirective.combinators) {
4815 if (combinator is ShowCombinator) {
4816 for (SimpleIdentifier name in combinator.shownNames) {
4817 list.add(name);
4818 }
4819 }
4820 }
4821 }
4725 } 4822 }
4726 4823
4727 /** 4824 /**
4728 * Maintains and manages contextual type information used for 4825 * Maintains and manages contextual type information used for
4729 * inferring types. 4826 * inferring types.
4730 */ 4827 */
4731 class InferenceContext { 4828 class InferenceContext {
4732 // TODO(leafp): Consider replacing these node properties with a 4829 // TODO(leafp): Consider replacing these node properties with a
4733 // hash table help in an instance of this class. 4830 // hash table help in an instance of this class.
4734 static const String _typeProperty = 4831 static const String _typeProperty =
(...skipping 7826 matching lines...) Expand 10 before | Expand all | Expand 10 after
12561 } 12658 }
12562 12659
12563 /** 12660 /**
12564 * A container with information about used imports prefixes and used imported 12661 * A container with information about used imports prefixes and used imported
12565 * elements. 12662 * elements.
12566 */ 12663 */
12567 class UsedImportedElements { 12664 class UsedImportedElements {
12568 /** 12665 /**
12569 * The set of referenced [PrefixElement]s. 12666 * The set of referenced [PrefixElement]s.
12570 */ 12667 */
12571 final Set<PrefixElement> prefixes = new HashSet<PrefixElement>(); 12668 final Map<PrefixElement, List<SimpleIdentifier>> prefixes =
scheglov 2016/04/06 15:34:39 1. Instances of the class UsedImportedElements are
srawlins 2016/04/07 15:27:23 Done.
12669 new HashMap<PrefixElement, List<SimpleIdentifier>>();
12572 12670
12573 /** 12671 /**
12574 * The set of referenced top-level [Element]s. 12672 * The set of referenced top-level [Element]s.
12575 */ 12673 */
12576 final Set<Element> elements = new HashSet<Element>(); 12674 final Set<Element> elements = new HashSet<Element>();
12577 } 12675 }
12578 12676
12579 /** 12677 /**
12580 * A container with sets of used [Element]s. 12678 * A container with sets of used [Element]s.
12581 * All these elements are defined in a single compilation unit or a library. 12679 * All these elements are defined in a single compilation unit or a library.
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
12977 nonFields.add(node); 13075 nonFields.add(node);
12978 return null; 13076 return null;
12979 } 13077 }
12980 13078
12981 @override 13079 @override
12982 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); 13080 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this);
12983 13081
12984 @override 13082 @override
12985 Object visitWithClause(WithClause node) => null; 13083 Object visitWithClause(WithClause node) => null;
12986 } 13084 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698