mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 13:28:03 +00:00
Add HintCode for duplicate shown/hidden names
Bug: https://github.com/dart-lang/sdk/issues/33182 Change-Id: Ibb82c44357bc59044340c6d8b1904c7815d19215 Reviewed-on: https://dart-review.googlesource.com/57161 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
parent
e7bad54986
commit
cc9c8f93f5
|
@ -257,6 +257,8 @@ const List<ErrorCode> errorCodeValues = const [
|
|||
HintCode.DEPRECATED_MIXIN_FUNCTION,
|
||||
HintCode.DIVISION_OPTIMIZATION,
|
||||
HintCode.DUPLICATE_IMPORT,
|
||||
HintCode.DUPLICATE_HIDDEN_NAME,
|
||||
HintCode.DUPLICATE_SHOWN_NAME,
|
||||
HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE,
|
||||
HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE,
|
||||
HintCode.GENERIC_METHOD_COMMENT,
|
||||
|
|
|
@ -334,6 +334,7 @@ class LibraryAnalyzer {
|
|||
verifier.addImports(unit);
|
||||
_usedImportedElementsList.forEach(verifier.removeUsedElements);
|
||||
verifier.generateDuplicateImportHints(errorReporter);
|
||||
verifier.generateDuplicateShownHiddenNameHints(errorReporter);
|
||||
verifier.generateUnusedImportHints(errorReporter);
|
||||
verifier.generateUnusedShownNameHints(errorReporter);
|
||||
}
|
||||
|
|
|
@ -131,6 +131,22 @@ class HintCode extends ErrorCode {
|
|||
'DUPLICATE_IMPORT', "Duplicate import.",
|
||||
correction: "Try removing all but one import of the library.");
|
||||
|
||||
/**
|
||||
* Duplicate hidden names.
|
||||
*/
|
||||
static const HintCode DUPLICATE_HIDDEN_NAME =
|
||||
const HintCode('DUPLICATE_HIDDEN_NAME', "Duplicate hidden name.",
|
||||
correction: "Try removing the repeated name from the list of hidden "
|
||||
"members.");
|
||||
|
||||
/**
|
||||
* Duplicate shown names.
|
||||
*/
|
||||
static const HintCode DUPLICATE_SHOWN_NAME =
|
||||
const HintCode('DUPLICATE_SHOWN_NAME', "Duplicate shown name.",
|
||||
correction: "Try removing the repeated name from the list of shown "
|
||||
"members.");
|
||||
|
||||
/**
|
||||
* It is a bad practice for a source file in a package "lib" directory
|
||||
* hierarchy to traverse outside that directory hierarchy. For example, a
|
||||
|
|
|
@ -4076,6 +4076,20 @@ class ImportsVerifier {
|
|||
final HashMap<ImportDirective, List<SimpleIdentifier>> _unusedShownNamesMap =
|
||||
new HashMap<ImportDirective, List<SimpleIdentifier>>();
|
||||
|
||||
/**
|
||||
* A map of names that are hidden more than once.
|
||||
*/
|
||||
final HashMap<NamespaceDirective, List<SimpleIdentifier>>
|
||||
_duplicateHiddenNamesMap =
|
||||
new HashMap<NamespaceDirective, List<SimpleIdentifier>>();
|
||||
|
||||
/**
|
||||
* A map of names that are shown more than once.
|
||||
*/
|
||||
final HashMap<NamespaceDirective, List<SimpleIdentifier>>
|
||||
_duplicateShownNamesMap =
|
||||
new HashMap<NamespaceDirective, List<SimpleIdentifier>>();
|
||||
|
||||
void addImports(CompilationUnit node) {
|
||||
for (Directive directive in node.directives) {
|
||||
if (directive is ImportDirective) {
|
||||
|
@ -4105,6 +4119,9 @@ class ImportsVerifier {
|
|||
}
|
||||
_addShownNames(directive);
|
||||
}
|
||||
if (directive is NamespaceDirective) {
|
||||
_addDuplicateShownHiddenNames(directive);
|
||||
}
|
||||
}
|
||||
if (_unusedImports.length > 1) {
|
||||
// order the list of unusedImports to find duplicates in faster than
|
||||
|
@ -4199,6 +4216,37 @@ class ImportsVerifier {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a [HintCode.DUPLICATE_SHOWN_HIDDEN_NAME] hint for each duplicate
|
||||
* shown or hidden name.
|
||||
*
|
||||
* Only call this method after all of the compilation units have been visited
|
||||
* by this visitor.
|
||||
*
|
||||
* @param errorReporter the error reporter used to report the set of
|
||||
* [HintCode.UNUSED_SHOWN_NAME] hints
|
||||
*/
|
||||
void generateDuplicateShownHiddenNameHints(ErrorReporter reporter) {
|
||||
_duplicateHiddenNamesMap.forEach(
|
||||
(NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
|
||||
int length = identifiers.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
Identifier identifier = identifiers[i];
|
||||
reporter.reportErrorForNode(
|
||||
HintCode.DUPLICATE_HIDDEN_NAME, identifier, [identifier.name]);
|
||||
}
|
||||
});
|
||||
_duplicateShownNamesMap.forEach(
|
||||
(NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
|
||||
int length = identifiers.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
Identifier identifier = identifiers[i];
|
||||
reporter.reportErrorForNode(
|
||||
HintCode.DUPLICATE_SHOWN_NAME, identifier, [identifier.name]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove elements from [_unusedImports] using the given [usedElements].
|
||||
*/
|
||||
|
@ -4262,6 +4310,43 @@ class ImportsVerifier {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add duplicate shown and hidden names from [directive] into
|
||||
* [_duplicateHiddenNamesMap] and [_duplicateShownNamesMap].
|
||||
*/
|
||||
void _addDuplicateShownHiddenNames(NamespaceDirective directive) {
|
||||
if (directive.combinators == null) {
|
||||
return;
|
||||
}
|
||||
for (Combinator combinator in directive.combinators) {
|
||||
// Use a Set to find duplicates in faster than O(n^2) time.
|
||||
Set<Element> identifiers = new Set<Element>();
|
||||
if (combinator is HideCombinator) {
|
||||
for (SimpleIdentifier name in combinator.hiddenNames) {
|
||||
if (name.staticElement != null) {
|
||||
if (!identifiers.add(name.staticElement)) {
|
||||
// [name] is a duplicate.
|
||||
List<SimpleIdentifier> duplicateNames = _duplicateHiddenNamesMap
|
||||
.putIfAbsent(directive, () => new List<SimpleIdentifier>());
|
||||
duplicateNames.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (combinator is ShowCombinator) {
|
||||
for (SimpleIdentifier name in combinator.shownNames) {
|
||||
if (name.staticElement != null) {
|
||||
if (!identifiers.add(name.staticElement)) {
|
||||
// [name] is a duplicate.
|
||||
List<SimpleIdentifier> duplicateNames = _duplicateShownNamesMap
|
||||
.putIfAbsent(directive, () => new List<SimpleIdentifier>());
|
||||
duplicateNames.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup and return the [Namespace] from the [_namespaceMap].
|
||||
*
|
||||
|
|
|
@ -2836,6 +2836,7 @@ class GenerateHintsTask extends SourceBasedAnalysisTask {
|
|||
verifier.addImports(unit);
|
||||
usedImportedElementsList.forEach(verifier.removeUsedElements);
|
||||
verifier.generateDuplicateImportHints(errorReporter);
|
||||
verifier.generateDuplicateShownHiddenNameHints(errorReporter);
|
||||
verifier.generateUnusedImportHints(errorReporter);
|
||||
verifier.generateUnusedShownNameHints(errorReporter);
|
||||
}
|
||||
|
|
|
@ -1241,6 +1241,32 @@ class B {}''');
|
|||
verify([source]);
|
||||
}
|
||||
|
||||
test_duplicateShownHiddenName_hidden() async {
|
||||
Source source = addSource(r'''
|
||||
library L;
|
||||
export 'lib1.dart' hide A, B, A;''');
|
||||
addNamedSource("/lib1.dart", r'''
|
||||
library lib1;
|
||||
class A {}
|
||||
class B {}''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source, [HintCode.DUPLICATE_HIDDEN_NAME]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_duplicateShownHiddenName_shown() async {
|
||||
Source source = addSource(r'''
|
||||
library L;
|
||||
export 'lib1.dart' show A, B, A;''');
|
||||
addNamedSource("/lib1.dart", r'''
|
||||
library lib1;
|
||||
class A {}
|
||||
class B {}''');
|
||||
await computeAnalysisResult(source);
|
||||
assertErrors(source, [HintCode.DUPLICATE_SHOWN_NAME]);
|
||||
verify([source]);
|
||||
}
|
||||
|
||||
test_factory__expr_return_null_OK() async {
|
||||
Source source = addSource(r'''
|
||||
import 'package:meta/meta.dart';
|
||||
|
|
Loading…
Reference in a new issue