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

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

Powered by Google App Engine
This is Rietveld 408576698