Revert "Parts. Track used imports while resolving library files."

This reverts commit 49c6679e4a.

Reason for revert: breaks google3

Original change's description:
> Parts. Track used imports while resolving library files.
>
> Change-Id: Ic23ec9ca49d93382449bfe2650089eb43099c3e4
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/382680
> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>

Change-Id: Ia954aea30c6ef61197ddaeca53a5179745c30908
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/382903
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Phil Quitslund <pquitslund@google.com>
This commit is contained in:
Konstantin Shcheglov
2024-08-30 13:56:36 +00:00
committed by Commit Queue
parent 71efc19cc7
commit 70aed6a93c
24 changed files with 140 additions and 403 deletions
@@ -161,7 +161,7 @@ void f(Old o) {}
import '$importUri';
void f(New o) {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_replacedBy() async {
@@ -193,6 +193,6 @@ import 'dart:io';
int f() {
return FileMode.read;
}
''');
''', errorFilter: ignoreUnusedImport);
}
}
@@ -95,7 +95,7 @@ import '$importUri';
void f() {
CupertinoAlertDialog(content: 'x');
}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void>
@@ -171,7 +171,7 @@ import '$importUri';
void f() {
CupertinoPopupSurface(child: 'x');
}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void>
@@ -125,7 +125,7 @@ import '$importUri';
void f() {
New.c();
}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_constructor_unnamed_deprecated() async {
@@ -175,7 +175,7 @@ import '$importUri';
void f() {
New();
}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_constructor_unnamed_removed_prefixed() async {
@@ -234,7 +234,7 @@ class C extends Old {}
import '$importUri';
class C extends New {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_inImplements_deprecated() async {
@@ -270,7 +270,7 @@ class C implements Old {}
import '$importUri';
class C implements New {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_inOn_deprecated() async {
@@ -306,7 +306,7 @@ extension E on Old {}
import '$importUri';
extension E on New {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_inTypeAnnotation_deprecated() async {
@@ -342,7 +342,7 @@ void f(Old o) {}
import '$importUri';
void f(New o) {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_inTypeArgument_deprecated() async {
@@ -430,7 +430,7 @@ class C with Old {}
import '$importUri';
class C with New {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_staticField_deprecated() async {
@@ -472,7 +472,7 @@ var s = Old.empty;
import '$importUri';
var s = New.empty;
''');
''', errorFilter: ignoreUnusedImport);
}
}
@@ -693,7 +693,7 @@ var l = Old('a').double;
import '$importUri';
var l = New('a').double;
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_staticField_deprecated() async {
@@ -735,7 +735,7 @@ var s = Old.empty;
import '$importUri';
var s = New.empty;
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_staticField_removed_prefixed() async {
@@ -1176,7 +1176,7 @@ import '$importUri';
void f() {
b;
}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_topLevel_reference_removed_prefixed() async {
@@ -1417,7 +1417,7 @@ class C with Old {}
import '$importUri';
class C with New {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_inWith_removed_prefixed() async {
@@ -1515,7 +1515,7 @@ import '$importUri';
void f() {
b();
}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_removed_prefixed() async {
@@ -1661,7 +1661,7 @@ void f(Old o) {}
import '$importUri';
void f(New o) {}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_removed_prefixed() async {
@@ -1068,7 +1068,7 @@ import '$importUri';
f() {
expect(true, true);
}
''');
''', errorFilter: ignoreUnusedImport);
}
Future<void> test_new_element_uris_single() async {
@@ -1102,7 +1102,7 @@ import '$importUri';
main() {
expect(true, true);
}
''');
''', errorFilter: ignoreUnusedImport);
}
}
@@ -49,7 +49,7 @@ void f(Foo o) {}
import '$importUri';
void f(Bar o) {}
''');
''', errorFilter: ignoreUnusedImport);
}
}
@@ -96,6 +96,6 @@ import '$importUri';
main() {
expect(true, true);
}
''');
''', errorFilter: ignoreUnusedImport);
}
}
@@ -6,7 +6,6 @@ import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/scope.dart';
import 'package:analyzer/src/ignore_comments/ignore_info.dart';
/// Information about a file being analyzed.
@@ -17,7 +16,6 @@ class FileAnalysis {
final CompilationUnitImpl unit;
final CompilationUnitElementImpl element;
final IgnoreInfo ignoreInfo;
late ImportsTracking importsTracking;
FileAnalysis({
required this.file,
@@ -182,18 +182,11 @@ class LibraryAnalyzer {
_testingData?.recordFlowAnalysisDataForTesting(
file.uri, flowAnalysisHelper.dataForTesting!);
var resolverVisitor = ResolverVisitor(
_inheritance,
_libraryElement,
libraryResolutionContext,
file.source,
_typeProvider,
errorListener,
featureSet: _libraryElement.featureSet,
analysisOptions: _library.file.analysisOptions,
flowAnalysisHelper: flowAnalysisHelper,
libraryFragment: unitElement,
);
var resolverVisitor = ResolverVisitor(_inheritance, _libraryElement,
libraryResolutionContext, file.source, _typeProvider, errorListener,
featureSet: _libraryElement.featureSet,
analysisOptions: _library.file.analysisOptions,
flowAnalysisHelper: flowAnalysisHelper);
_testingData?.recordTypeConstraintGenerationDataForTesting(
file.uri, resolverVisitor.inferenceHelper.dataForTesting!);
@@ -505,9 +498,7 @@ class LibraryAnalyzer {
// Verify imports.
{
var verifier = ImportsVerifier(
fileAnalysis: fileAnalysis,
);
ImportsVerifier verifier = ImportsVerifier();
verifier.addImports(unit);
usedImportedElements.forEach(verifier.removeUsedElements);
verifier.generateDuplicateExportWarnings(errorReporter);
@@ -627,24 +618,10 @@ class LibraryAnalyzer {
fileElement: _libraryElement.definingCompilationUnit,
);
// Configure scopes for all files to track imports usages.
// Associate tracking objects with file objects.
for (var fileAnalysis in _libraryFiles.values) {
var scope = fileAnalysis.element.scope;
var tracking = scope.importsTrackingInit();
fileAnalysis.importsTracking = tracking;
}
for (var fileAnalysis in _libraryFiles.values) {
_resolveFile(fileAnalysis);
}
// Stop tracking usages by scopes.
for (var fileAnalysis in _libraryFiles.values) {
var scope = fileAnalysis.element.scope;
scope.importsTrackingDestroy();
}
_computeConstants();
}
@@ -934,18 +911,11 @@ class LibraryAnalyzer {
_testingData?.recordFlowAnalysisDataForTesting(
fileAnalysis.file.uri, flowAnalysisHelper.dataForTesting!);
var resolver = ResolverVisitor(
_inheritance,
_libraryElement,
libraryResolutionContext,
source,
_typeProvider,
errorListener,
analysisOptions: _library.file.analysisOptions,
featureSet: unit.featureSet,
flowAnalysisHelper: flowAnalysisHelper,
libraryFragment: unitElement,
);
var resolver = ResolverVisitor(_inheritance, _libraryElement,
libraryResolutionContext, source, _typeProvider, errorListener,
analysisOptions: _library.file.analysisOptions,
featureSet: unit.featureSet,
flowAnalysisHelper: flowAnalysisHelper);
unit.accept(resolver);
_testingData?.recordTypeConstraintGenerationDataForTesting(
fileAnalysis.file.uri, resolver.inferenceHelper.dataForTesting!);
+24 -158
View File
@@ -109,78 +109,6 @@ class FormalParameterScope extends EnclosedScope {
}
}
/// Tracking information for all import in [CompilationUnitElementImpl].
class ImportsTracking {
/// Tracking information for each import prefix.
final Map<PrefixElementImpl?, ImportsTrackingOfPrefix> map;
ImportsTracking({
required this.map,
});
void notifyExtensionUsed(ExtensionElement element) {
for (var tracking in map.values) {
tracking.notifyExtensionUsed(element);
}
}
}
class ImportsTrackingOfPrefix {
final Map<Element, List<LibraryImportElementImpl>> elementImports;
final Set<LibraryImportElementImpl> usedImports = {};
/// This flag is set to `true` when there is a compile-time error reported
/// against the group of imports with this import prefix. Specifically,
/// currently there are two errors:
///
/// 1. Unresolved identifier.
/// 2. Using import prefix itself, without `.identifier` after it.
///
/// When this happens, we don't want to report unused imports.
bool hasErrorReported = false;
/// We set it temporarily to `false` while resolving combinators.
bool active = true;
ImportsTrackingOfPrefix({
required this.elementImports,
});
void lookupResult(Element? element) {
if (!active) {
return;
}
if (element == null) {
return;
}
if (element is MultiplyDefinedElement) {
notifyErrorReported();
return;
}
var imports = elementImports[element];
if (imports != null) {
usedImports.addAll(imports);
}
}
/// We cannot resolve something, mark this group of imports as affected.
void notifyErrorReported() {
if (active) {
hasErrorReported = true;
}
}
void notifyExtensionUsed(ExtensionElement element) {
var imports = elementImports[element];
if (imports != null) {
usedImports.addAll(imports);
}
}
}
/// The scope defined by an instance element.
class InstanceScope extends EnclosedScope {
InstanceScope(super.parent, InstanceElement element) {
@@ -249,14 +177,6 @@ class LibraryFragmentScope implements Scope {
/// The cached result for [accessibleExtensions].
List<ExtensionElement>? _extensions;
/// This field is set temporarily while resolving all files of a library.
/// So, we can track which elements were actually returned, and which imports
/// in which file (including enclosing files) provided these elements.
///
/// When we are done, we remove the tracker, so that it does not use memory
/// when we are not resolving files of this library.
ImportsTracking? _importsTracking;
factory LibraryFragmentScope(CompilationUnitElementImpl fragment) {
return LibraryFragmentScope._(
parent: fragment.enclosingElement3?.scope,
@@ -297,34 +217,6 @@ class LibraryFragmentScope implements Scope {
}.toFixedList();
}
// TODO(scheglov): this is kludge.
// We should not use the fragment scope for resolving combinators.
// We should use the export scope of the imported library.
void importsTrackingActive(bool value) {
if (_importsTracking case var importsTracking?) {
for (var tracking in importsTracking.map.values) {
tracking.active = value;
}
}
}
void importsTrackingDestroy() {
noPrefixScope.importsTrackingDestroy();
for (var prefixElement in _prefixElements.values) {
prefixElement.scope.importsTrackingDestroy();
}
}
ImportsTracking importsTrackingInit() {
return _importsTracking = ImportsTracking(
map: {
null: noPrefixScope.importsTrackingInit(),
for (var prefixElement in _prefixElements.values)
prefixElement: prefixElement.scope.importsTrackingInit(),
},
);
}
@override
ScopeLookupResult lookup(String id) {
// Try declarations of the whole library.
@@ -338,14 +230,10 @@ class LibraryFragmentScope implements Scope {
return importResult;
}
// No result.
// No parent, no result.
return ScopeLookupResultImpl(null, null);
}
void notifyExtensionUsed(ExtensionElement element) {
_importsTracking?.notifyExtensionUsed(element);
}
PrefixScope? _getParentPrefixScope(PrefixElementImpl prefix) {
var isDeferred = prefix.imports.any((import) {
return import.prefix is DeferredImportElementPrefix;
@@ -378,7 +266,12 @@ class LibraryFragmentScope implements Scope {
}
// Try the parent's combined import scope.
return parent?._lookupCombined(id);
var parentResult = parent?._lookupCombined(id);
if (parentResult != null) {
return parentResult;
}
return null;
}
ScopeLookupResult? _lookupLibrary(String id) {
@@ -417,9 +310,6 @@ class PrefixScope implements Scope {
final LibraryElementImpl libraryElement;
final PrefixScope? parent;
final List<LibraryImportElementImpl> _importElements = [];
final Map<Element, List<LibraryImportElementImpl>> _elementImports = {};
final Map<String, Element> _getters = {};
final Map<String, Element> _setters = {};
Set<String>? _settersFromDeprecatedExport;
@@ -427,53 +317,40 @@ class PrefixScope implements Scope {
final Set<ExtensionElement> _extensions = {};
LibraryElement? _deferredLibrary;
ImportsTrackingOfPrefix? _importsTracking;
PrefixScope({
required this.libraryElement,
required this.parent,
required List<LibraryImportElementImpl> libraryImports,
required List<LibraryImportElement> libraryImports,
required PrefixElement? prefix,
}) {
var elementFactory = libraryElement.session.elementFactory;
for (var import in libraryImports) {
var importedUri = import.uri;
if (importedUri is DirectiveUriWithLibraryImpl &&
if (importedUri is DirectiveUriWithLibrary &&
import.prefix?.element == prefix) {
_importElements.add(import);
var importedLibrary = importedUri.library;
var combinators = import.combinators.build();
for (var exportedReference in importedLibrary.exportedReferences) {
var reference = exportedReference.reference;
var id = reference.name;
if (combinators.allows(id)) {
var element = elementFactory.elementOfReference(reference)!;
if (_shouldAdd(importedLibrary, element)) {
(_elementImports[element] ??= []).add(import);
_add(
element,
importedLibrary.isFromDeprecatedExport(exportedReference),
);
if (importedLibrary is LibraryElementImpl) {
var combinators = import.combinators.build();
for (var exportedReference in importedLibrary.exportedReferences) {
var reference = exportedReference.reference;
if (combinators.allows(reference.name)) {
var element = elementFactory.elementOfReference(reference)!;
if (_shouldAdd(importedLibrary, element)) {
_add(
element,
importedLibrary.isFromDeprecatedExport(exportedReference),
);
}
}
}
}
if (import.prefix is DeferredImportElementPrefix) {
_deferredLibrary ??= importedLibrary;
if (import.prefix is DeferredImportElementPrefix) {
_deferredLibrary ??= importedLibrary;
}
}
}
}
}
void importsTrackingDestroy() {
_importsTracking = null;
}
ImportsTrackingOfPrefix importsTrackingInit() {
return _importsTracking = ImportsTrackingOfPrefix(
elementImports: _elementImports,
);
}
@override
ScopeLookupResult lookup(String id) {
var deferredLibrary = _deferredLibrary;
@@ -484,8 +361,6 @@ class PrefixScope implements Scope {
var getter = _getters[id];
var setter = _setters[id];
if (getter != null || setter != null) {
_importsTracking?.lookupResult(getter);
_importsTracking?.lookupResult(setter);
return PrefixScopeLookupResult(
getter,
setter,
@@ -498,18 +373,9 @@ class PrefixScope implements Scope {
return parent.lookup(id);
}
_importsTracking?.notifyErrorReported();
return ScopeLookupResultImpl(null, null);
}
/// This method is invoked when the import prefix is used by itself,
/// without the `.identifier` after it. This is a compile-time error that
/// we expect the user to fix first, and we don't want to report unused
/// imports until then.
void notifyErrorReported() {
_importsTracking?.notifyErrorReported();
}
void _add(Element element, bool isFromDeprecatedExport) {
if (element is PropertyAccessorElement && element.isSetter) {
_addTo(
@@ -5,7 +5,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
@@ -144,12 +143,6 @@ class CommentReferenceResolver {
var lookupResult = identifier.scopeLookupResult!;
var element = lookupResult.getter ?? lookupResult.setter;
// Usually referencing just an import prefix is an error.
// But we allow this in documentation comments.
if (element is PrefixElementImpl) {
element.scope.notifyErrorReported();
}
if (element == null) {
InterfaceType enclosingType;
var enclosingClass = _resolver.enclosingClass;
@@ -96,20 +96,12 @@ class ExtensionMemberResolver {
}
if (extensions.length == 1) {
var instantiated = extensions[0];
_resolver.libraryFragment.scope.notifyExtensionUsed(
instantiated.extension,
);
return instantiated.asResolutionResult;
return extensions[0].asResolutionResult;
}
var mostSpecific = _chooseMostSpecific(extensions);
if (mostSpecific.length == 1) {
var instantiated = mostSpecific.first;
_resolver.libraryFragment.scope.notifyExtensionUsed(
instantiated.extension,
);
return instantiated.asResolutionResult;
return mostSpecific.first.asResolutionResult;
}
// The most specific extension is ambiguous.
@@ -265,11 +265,7 @@ class MethodInvocationResolver with ScopeHelpers {
);
}
void _reportPrefixIdentifierNotFollowedByDot(
SimpleIdentifier target,
PrefixElementImpl prefixElement,
) {
prefixElement.scope.notifyErrorReported();
void _reportPrefixIdentifierNotFollowedByDot(SimpleIdentifier target) {
_resolver.errorReporter.atNode(
target,
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
@@ -590,10 +586,10 @@ class MethodInvocationResolver with ScopeHelpers {
return _rewriteAsFunctionExpressionInvocation(node, targetType);
}
// TODO(scheglov): This is a questionable distinction.
if (element is PrefixElementImpl) {
if (element is PrefixElement) {
_setInvalidTypeResolution(node,
whyNotPromotedList: whyNotPromotedList, contextType: contextType);
_reportPrefixIdentifierNotFollowedByDot(nameNode, element);
_reportPrefixIdentifierNotFollowedByDot(nameNode);
return null;
}
_reportInvocationOfNonFunction(node, whyNotPromotedList,
@@ -264,9 +264,6 @@ class NamedTypeResolver with ScopeHelpers {
);
return _verifyTypeAliasForContext(node, element, type);
} else if (_isInstanceCreation(node)) {
if (element is PrefixElementImpl) {
element.scope.notifyErrorReported();
}
_ErrorHelper(errorReporter).reportNewWithNonType(node);
return InvalidTypeImpl.instance;
} else if (element is DynamicElementImpl) {
@@ -617,9 +614,6 @@ class _ErrorHelper {
}
if (element != null) {
if (element is PrefixElementImpl) {
element.scope.notifyErrorReported();
}
var errorRange = _getErrorRange(node);
errorReporter.atOffset(
offset: errorRange.offset,
@@ -198,8 +198,7 @@ class SimpleIdentifierResolver with ScopeHelpers {
!identical(element, enclosingClass)) {
// This error is now reported by the parser.
element = null;
} else if (element is PrefixElementImpl && !_isValidAsPrefix(node)) {
element.scope.notifyErrorReported();
} else if (element is PrefixElement && !_isValidAsPrefix(node)) {
errorReporter.atNode(
node,
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
@@ -63,8 +63,7 @@ class AssignmentVerifier {
node,
CompileTimeErrorCode.ASSIGNMENT_TO_METHOD,
);
} else if (recovery is PrefixElementImpl) {
recovery.scope.notifyErrorReported();
} else if (recovery is PrefixElement) {
_errorReporter.atNode(
node,
CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
@@ -5,9 +5,7 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/analysis/file_analysis.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/summary2/combinator.dart';
@@ -243,8 +241,6 @@ class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor<void> {
/// this logic built up in this class could be used for such an action in the
/// future.
class ImportsVerifier {
final FileAnalysis fileAnalysis;
/// All [ImportDirective]s of the current library.
final List<ImportDirectiveImpl> _allImports = [];
@@ -300,10 +296,6 @@ class ImportsVerifier {
final Map<NamespaceDirective, List<SimpleIdentifier>>
_duplicateShownNamesMap = {};
ImportsVerifier({
required this.fileAnalysis,
});
void addImports(CompilationUnit node) {
var importsWithLibraries = <_NamespaceDirective>[];
var exportsWithLibraries = <_NamespaceDirective>[];
@@ -439,41 +431,37 @@ class ImportsVerifier {
verifier.reportImports(errorReporter);
}
/// Report [WarningCode.UNUSED_IMPORT] for each unused import.
/// Report an [HintCode.UNUSED_IMPORT] hint for each unused import.
///
/// 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_IMPORT] hints
void generateUnusedImportHints(ErrorReporter errorReporter) {
for (var importDirective in fileAnalysis.unit.directives) {
if (importDirective is ImportDirectiveImpl) {
var importElement = importDirective.element!;
var prefixElement = importElement.prefix?.element;
var tracking = fileAnalysis.importsTracking.map[prefixElement]!;
// If there are errors reported against this group (by import prefix)
// of imports, then it does not matter which imports are used.
if (tracking.hasErrorReported) {
int length = _unusedImports.length;
for (int i = 0; i < length; i++) {
ImportDirective unusedImport = _unusedImports[i];
// Check that the imported URI exists and isn't dart:core
var importElement = unusedImport.element;
if (importElement != null) {
var libraryElement = importElement.importedLibrary;
if (libraryElement == null ||
libraryElement.isDartCore ||
libraryElement.isSynthetic) {
continue;
}
if (importElement.uri case DirectiveUriWithLibraryImpl uri) {
// Ignore explicit dart:core import.
if (uri.library.isDartCore) {
continue;
}
// The URI target does not exist, reported this elsewhere.
if (uri.library.isSynthetic) {
continue;
}
var isUsed = tracking.usedImports.contains(importElement);
if (!isUsed) {
errorReporter.atNode(
importDirective.uri,
WarningCode.UNUSED_IMPORT,
arguments: [uri.relativeUriString],
);
}
}
}
StringLiteral uri = unusedImport.uri;
// We can safely assume that `uri.stringValue` is non-`null`, because the
// only way for it to be `null` is if the import contains a string
// interpolation, in which case the import wouldn't have resolved and
// would not have been included in [_unusedImports].
errorReporter.atNode(
uri,
WarningCode.UNUSED_IMPORT,
arguments: [uri.stringValue!],
);
}
}
+34 -67
View File
@@ -86,7 +86,6 @@ import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/generated/variable_type_provider.dart';
import 'package:analyzer/src/task/inference_error.dart';
import 'package:analyzer/src/util/ast_data_extractor.dart';
import 'package:analyzer/src/utilities/extensions/object.dart';
/// Function determining which source files should have inference logging
/// enabled.
@@ -135,9 +134,6 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
/// The element for the library containing the compilation unit being visited.
final LibraryElementImpl definingLibrary;
/// The library fragment being visited.
final CompilationUnitElementImpl libraryFragment;
/// The context shared between different units of the same library.
final LibraryResolutionContext libraryResolutionContext;
@@ -308,43 +304,39 @@ class ResolverVisitor extends ThrowingAstVisitor<void>
// TODO(paulberry): make [featureSet] a required parameter (this will be a
// breaking change).
ResolverVisitor(
InheritanceManager3 inheritanceManager,
LibraryElementImpl definingLibrary,
LibraryResolutionContext libraryResolutionContext,
Source source,
TypeProvider typeProvider,
AnalysisErrorListener errorListener, {
required CompilationUnitElementImpl libraryFragment,
required FeatureSet featureSet,
required AnalysisOptionsImpl analysisOptions,
required FlowAnalysisHelper flowAnalysisHelper,
}) : this._(
inheritanceManager,
definingLibrary,
libraryResolutionContext,
source,
definingLibrary.typeSystem,
typeProvider as TypeProviderImpl,
errorListener,
featureSet,
analysisOptions,
flowAnalysisHelper,
libraryFragment: libraryFragment,
);
InheritanceManager3 inheritanceManager,
LibraryElementImpl definingLibrary,
LibraryResolutionContext libraryResolutionContext,
Source source,
TypeProvider typeProvider,
AnalysisErrorListener errorListener,
{required FeatureSet featureSet,
required AnalysisOptionsImpl analysisOptions,
required FlowAnalysisHelper flowAnalysisHelper})
: this._(
inheritanceManager,
definingLibrary,
libraryResolutionContext,
source,
definingLibrary.typeSystem,
typeProvider as TypeProviderImpl,
errorListener,
featureSet,
analysisOptions,
flowAnalysisHelper);
ResolverVisitor._(
this.inheritance,
this.definingLibrary,
this.libraryResolutionContext,
this.source,
this.typeSystem,
this.typeProvider,
AnalysisErrorListener errorListener,
FeatureSet featureSet,
this.analysisOptions,
this.flowAnalysis, {
required this.libraryFragment,
}) : errorReporter = ErrorReporter(errorListener, source),
this.inheritance,
this.definingLibrary,
this.libraryResolutionContext,
this.source,
this.typeSystem,
this.typeProvider,
AnalysisErrorListener errorListener,
FeatureSet featureSet,
this.analysisOptions,
this.flowAnalysis)
: errorReporter = ErrorReporter(errorListener, source),
_featureSet = featureSet,
genericMetadataIsEnabled =
definingLibrary.featureSet.isEnabled(Feature.generic_metadata),
@@ -4991,17 +4983,6 @@ class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
}
}
@override
void visitHideCombinator(HideCombinator node) {
var scope = nameScope.ifTypeOrNull<LibraryFragmentScope>();
scope?.importsTrackingActive(false);
try {
super.visitHideCombinator(node);
} finally {
scope?.importsTrackingActive(true);
}
}
@override
void visitIfElement(covariant IfElementImpl node) {
_visitIf(node);
@@ -5028,9 +5009,6 @@ class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
_visitDocumentationComment(node.documentationComment);
}
@override
void visitLibraryIdentifier(LibraryIdentifier node) {}
@override
void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
node.body.localVariableInfo = _localVariableInfo;
@@ -5123,17 +5101,6 @@ class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
node.target?.accept(this);
}
@override
void visitShowCombinator(ShowCombinator node) {
var scope = nameScope.ifTypeOrNull<LibraryFragmentScope>();
scope?.importsTrackingActive(false);
try {
super.visitShowCombinator(node);
} finally {
scope?.importsTrackingActive(true);
}
}
@override
void visitSimpleIdentifier(covariant SimpleIdentifierImpl node) {
// Ignore if already resolved - declaration or type.
@@ -5142,9 +5109,6 @@ class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
}
// Ignore if qualified.
var parent = node.parent;
if (parent is ConstructorName && parent.name == node) {
return;
}
var scopeLookupResult = nameScope.lookup(node.name);
node.scopeLookupResult = scopeLookupResult;
// Ignore if it cannot be a reference to a local variable.
@@ -5156,6 +5120,9 @@ class ScopeResolverVisitor extends UnifyingAstVisitor<void> {
parent.fieldName == node) {
return;
}
if (parent is ConstructorName) {
return;
}
if (parent is Label) {
return;
}
@@ -58,7 +58,6 @@ class AstResolver {
featureSet: _featureSet,
analysisOptions: analysisOptions,
flowAnalysisHelper: _flowAnalysis,
libraryFragment: _unitElement,
);
AstResolver(
@@ -2237,6 +2237,7 @@ void f(A a) {}
flags: exists isLibrary
errors
25 +1 UNDEFINED_CLASS
7 +8 UNUSED_IMPORT
[stream]
ResolvedUnitResult #1
[status] idle
@@ -2112,6 +2112,7 @@ main() {
math?.loadLibrary();
}
''', [
error(WarningCode.UNUSED_IMPORT, 7, 11),
error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 49, 4),
]);
@@ -132,6 +132,7 @@ f() {
p?.loadLibrary();
}
''', [
error(WarningCode.UNUSED_IMPORT, 7, 10),
error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 41, 1),
]);
}
@@ -475,40 +475,6 @@ f() {
]);
}
test_noPrefix_constructorName_name() async {
await assertErrorsInCode(r'''
import 'dart:async';
class A {
A.foo();
}
void f() {
A.foo();
}
''', [
error(WarningCode.UNUSED_IMPORT, 7, 12),
]);
}
test_prefixed_commentReference_prefix() async {
await assertNoErrorsInCode(r'''
import 'dart:math' as math;
/// [math]
void f() {}
''');
}
test_prefixed_commentReference_prefixClass() async {
await assertNoErrorsInCode(r'''
import 'dart:math' as math;
/// [math.Random]
void f() {}
''');
}
test_show() async {
newFile('$testPackageLibPath/lib1.dart', r'''
class A {}
@@ -29,6 +29,7 @@ import ''
if (dart.library.async) 'dart:missing_2';
''',
[
error(WarningCode.UNUSED_IMPORT, 7, 2),
lint(35, 16, messageContains: 'dart:missing_1'),
lint(120, 16, messageContains: 'dart:missing_2'),
],
@@ -46,6 +47,7 @@ import ''
if (dart.library.async) 'missing_2.dart';
''',
[
error(WarningCode.UNUSED_IMPORT, 7, 2),
lint(35, 16, messageContains: 'missing_1.dart'),
lint(121, 16, messageContains: 'missing_2.dart'),
],
@@ -61,6 +63,7 @@ import ''
if (dart.library.io) 'package:foo/missing_2.dart';
''',
[
error(WarningCode.UNUSED_IMPORT, 7, 2),
lint(35, 29, messageContains: 'missing_1.dart'),
lint(142, 28, messageContains: 'missing_2.dart'),
],
@@ -22,8 +22,8 @@ class UseKeyInWidgetConstructorsTest extends LintRuleTest {
test_augmentedConstructor_noKey() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
import 'package:flutter/widgets.dart';
part 'test.dart';
class W extends StatelessWidget {
W();
@@ -34,7 +34,9 @@ class W extends StatelessWidget {
''');
await assertNoDiagnostics(r'''
part of 'a.dart';
augment library 'a.dart';
import 'package:flutter/widgets.dart';
augment class W {
augment const W();
@@ -82,8 +84,8 @@ augment class W {
test_constructorInAugmentedClass_noKeyParam() async {
newFile('$testPackageLibPath/a.dart', r'''
import augment 'test.dart';
import 'package:flutter/widgets.dart';
part 'test.dart';
class W extends StatelessWidget {
@override
@@ -92,13 +94,15 @@ class W extends StatelessWidget {
''');
await assertDiagnostics(r'''
part of 'a.dart';
augment library 'a.dart';
import 'package:flutter/widgets.dart';
augment class W {
const W();
}
''', [
lint(45, 1),
lint(93, 1),
]);
}