| Index: pkg/analyzer/lib/src/generated/resolver.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
|
| index 9ba77b22a7070165a7c5f078f15db3671a8c31f8..3f1c0ed3e7638d871a9b04261d8f8aa9ee92354b 100644
|
| --- a/pkg/analyzer/lib/src/generated/resolver.dart
|
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart
|
| @@ -4104,26 +4104,8 @@ class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
|
| }
|
|
|
| @override
|
| - void visitPrefixedIdentifier(PrefixedIdentifier node) {
|
| - // If the prefixed identifier references some A.B, where A is a library
|
| - // prefix, then we can lookup the associated ImportDirective in
|
| - // prefixElementMap and remove it from the unusedImports list.
|
| - SimpleIdentifier prefixIdentifier = node.prefix;
|
| - Element element = prefixIdentifier.staticElement;
|
| - if (element is PrefixElement) {
|
| - List<Element> prefixedElements =
|
| - usedElements.prefixMap.putIfAbsent(element, () => <Element>[]);
|
| - prefixedElements.add(node.identifier.staticElement);
|
| - return;
|
| - }
|
| - // Otherwise, pass the prefixed identifier element and name onto
|
| - // visitIdentifier.
|
| - _visitIdentifier(element, prefixIdentifier.name);
|
| - }
|
| -
|
| - @override
|
| void visitSimpleIdentifier(SimpleIdentifier node) {
|
| - _visitIdentifier(node.staticElement, node.name);
|
| + _visitIdentifier(node, node.staticElement);
|
| }
|
|
|
| /**
|
| @@ -4134,7 +4116,7 @@ class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
|
| directive.metadata.accept(this);
|
| }
|
|
|
| - void _visitIdentifier(Element element, String name) {
|
| + void _visitIdentifier(SimpleIdentifier identifier, Element element) {
|
| if (element == null) {
|
| return;
|
| }
|
| @@ -4143,10 +4125,17 @@ class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
|
| if (element is MultiplyDefinedElement) {
|
| MultiplyDefinedElement multiplyDefinedElement = element;
|
| for (Element elt in multiplyDefinedElement.conflictingElements) {
|
| - _visitIdentifier(elt, name);
|
| + _visitIdentifier(identifier, elt);
|
| }
|
| return;
|
| - } else if (element is PrefixElement) {
|
| + }
|
| +
|
| + // Record `importPrefix.identifier` into 'prefixMap'.
|
| + if (_recordPrefixMap(identifier, element)) {
|
| + return;
|
| + }
|
| +
|
| + if (element is PrefixElement) {
|
| usedElements.prefixMap.putIfAbsent(element, () => <Element>[]);
|
| return;
|
| } else if (element.enclosingElement is! CompilationUnitElement) {
|
| @@ -4168,6 +4157,30 @@ class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
|
| // Remember the element.
|
| usedElements.elements.add(element);
|
| }
|
| +
|
| + /**
|
| + * If the given [identifier] is prefixed with a [PrefixElement], fill the
|
| + * corresponding `UsedImportedElements.prefixMap` entry and return `true`.
|
| + */
|
| + bool _recordPrefixMap(SimpleIdentifier identifier, Element element) {
|
| + bool recordIfTargetIsPrefixElement(Expression target) {
|
| + if (target is SimpleIdentifier && target.staticElement is PrefixElement) {
|
| + List<Element> prefixedElements = usedElements.prefixMap
|
| + .putIfAbsent(target.staticElement, () => <Element>[]);
|
| + prefixedElements.add(element);
|
| + return true;
|
| + }
|
| + return false;
|
| + }
|
| + AstNode parent = identifier.parent;
|
| + if (parent is MethodInvocation && parent.methodName == identifier) {
|
| + return recordIfTargetIsPrefixElement(parent.target);
|
| + }
|
| + if (parent is PrefixedIdentifier && parent.identifier == identifier) {
|
| + return recordIfTargetIsPrefixElement(parent.prefix);
|
| + }
|
| + return false;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -4652,15 +4665,16 @@ class ImportsVerifier {
|
| * hints
|
| */
|
| void generateUnusedShownNameHints(ErrorReporter reporter) {
|
| - _unusedShownNamesMap.forEach((ImportDirective importDirective,
|
| - List<SimpleIdentifier> identifiers) {
|
| + _unusedShownNamesMap.forEach(
|
| + (ImportDirective importDirective, List<SimpleIdentifier> identifiers) {
|
| if (_unusedImports.contains(importDirective)) {
|
| // This import is actually wholly unused, not just one or more shown names from it.
|
| // This is then an "unused import", rather than unused shown names.
|
| return;
|
| }
|
| for (Identifier identifier in identifiers) {
|
| - reporter.reportErrorForNode(HintCode.UNUSED_SHOWN_NAME, identifier, [identifier.name]);
|
| + reporter.reportErrorForNode(
|
| + HintCode.UNUSED_SHOWN_NAME, identifier, [identifier.name]);
|
| }
|
| });
|
| }
|
| @@ -4674,7 +4688,8 @@ class ImportsVerifier {
|
| return;
|
| }
|
| // Process import prefixes.
|
| - usedElements.prefixMap.forEach((PrefixElement prefix, List<Element> elements) {
|
| + usedElements.prefixMap
|
| + .forEach((PrefixElement prefix, List<Element> elements) {
|
| List<ImportDirective> importDirectives = _prefixElementMap[prefix];
|
| if (importDirectives != null) {
|
| for (ImportDirective importDirective in importDirectives) {
|
| @@ -4711,9 +4726,6 @@ class ImportsVerifier {
|
| String name = element.displayName;
|
| for (ImportDirective importDirective in importsLibrary) {
|
| Namespace namespace = _computeNamespace(importDirective);
|
| - if (importDirective.prefix != null) {
|
| - name = "${importDirective.prefix.name}.$name";
|
| - }
|
| if (namespace != null && namespace.get(name) != null) {
|
| _unusedImports.remove(importDirective);
|
| _removeFromUnusedShownNamesMap(element, importDirective);
|
| @@ -4723,35 +4735,6 @@ class ImportsVerifier {
|
| }
|
|
|
| /**
|
| - * Remove [element] from the list of names shown by [importDirective].
|
| - */
|
| - void _removeFromUnusedShownNamesMap(Element element,
|
| - ImportDirective importDirective) {
|
| - List<SimpleIdentifier> identifiers = _unusedShownNamesMap[importDirective];
|
| - if (identifiers == null) {
|
| - return;
|
| - }
|
| - for (Identifier identifier in identifiers) {
|
| - if (element is PropertyAccessorElement) {
|
| - // If the getter or setter of a variable is used, then the variable (the
|
| - // shown name) is used.
|
| - if (identifier.staticElement == element.variable) {
|
| - identifiers.remove(identifier);
|
| - break;
|
| - }
|
| - } else {
|
| - if (identifier.staticElement == element) {
|
| - identifiers.remove(identifier);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - if (identifiers.isEmpty) {
|
| - _unusedShownNamesMap.remove(importDirective);
|
| - }
|
| - }
|
| -
|
| - /**
|
| * Recursively add any exported library elements into the [libraryMap].
|
| */
|
| void _addAdditionalLibrariesForExports(LibraryElement library,
|
| @@ -4768,6 +4751,24 @@ class ImportsVerifier {
|
| }
|
|
|
| /**
|
| + * Add every shown name from [importDirective] into [_unusedShownNamesMap].
|
| + */
|
| + void _addShownNames(ImportDirective importDirective) {
|
| + if (importDirective.combinators == null) {
|
| + return;
|
| + }
|
| + List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
|
| + _unusedShownNamesMap[importDirective] = identifiers;
|
| + for (Combinator combinator in importDirective.combinators) {
|
| + if (combinator is ShowCombinator) {
|
| + for (SimpleIdentifier name in combinator.shownNames) {
|
| + identifiers.add(name);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Lookup and return the [Namespace] from the [_namespaceMap].
|
| *
|
| * If the map does not have the computed namespace, compute it and cache it in the map. If
|
| @@ -4808,21 +4809,32 @@ class ImportsVerifier {
|
| }
|
|
|
| /**
|
| - * Add every shown name from [importDirective] into [_unusedShownNamesMap].
|
| + * Remove [element] from the list of names shown by [importDirective].
|
| */
|
| - void _addShownNames(ImportDirective importDirective) {
|
| - if (importDirective.combinators == null) {
|
| + void _removeFromUnusedShownNamesMap(
|
| + Element element, ImportDirective importDirective) {
|
| + List<SimpleIdentifier> identifiers = _unusedShownNamesMap[importDirective];
|
| + if (identifiers == null) {
|
| return;
|
| }
|
| - List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
|
| - _unusedShownNamesMap[importDirective] = identifiers;
|
| - for (Combinator combinator in importDirective.combinators) {
|
| - if (combinator is ShowCombinator) {
|
| - for (SimpleIdentifier name in combinator.shownNames) {
|
| - identifiers.add(name);
|
| + for (Identifier identifier in identifiers) {
|
| + if (element is PropertyAccessorElement) {
|
| + // If the getter or setter of a variable is used, then the variable (the
|
| + // shown name) is used.
|
| + if (identifier.staticElement == element.variable) {
|
| + identifiers.remove(identifier);
|
| + break;
|
| + }
|
| + } else {
|
| + if (identifier.staticElement == element) {
|
| + identifiers.remove(identifier);
|
| + break;
|
| }
|
| }
|
| }
|
| + if (identifiers.isEmpty) {
|
| + _unusedShownNamesMap.remove(importDirective);
|
| + }
|
| }
|
| }
|
|
|
|
|