analyzer: rename Lint*Context classes For the analyzer plugin APIs, these classes should not have the word 'Lint' in them, as they are used for all analysis rules, whether they report lints or warnings. * LinterContext -> RuleContext * LinterContextWithParsedResults -> RuleContextWithParsedResults * LinterContextWithResolvedResults -> RuleContextWithResolvedResults * LintRuleUnitContext -> RuleUnitContext I'm open to better names for these. Some of these suffer from a chain-of-nouns name (a "RuleUnitContext" is a Context for a Unit for a Rule). So we could go with "UnitContextForRule" and "ContextForRule" or other ideas like that. Only RuleContext and RuleUnitContext will be public API. Change-Id: I5550736beaba7e39b36e7b5584ca6d023aa4d02b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431703 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart index 3e71263..0819700 100644 --- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart +++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -273,15 +273,15 @@ } if (parsedLibrary is ParsedLibraryResult) { var errorListener = RecordingErrorListener(); - var unitContexts = <LintRuleUnitContext>[]; + var contextUnits = <RuleContextUnit>[]; for (var parsedUnit in parsedLibrary.units) { var errorReporter = ErrorReporter( errorListener, StringSource(parsedUnit.content, null), ); - unitContexts.add( - LintRuleUnitContext( + contextUnits.add( + RuleContextUnit( file: parsedUnit.file, content: parsedUnit.content, errorReporter: errorReporter, @@ -289,8 +289,8 @@ ), ); } - for (var unitContext in unitContexts) { - _computeParsedResultLint(unitContext, unitContexts); + for (var unitContext in contextUnits) { + _computeParsedResultLint(unitContext, contextUnits); } await _fixErrorsInParsedLibrary( parsedLibrary, @@ -531,11 +531,13 @@ /// Computes lint for lint rules with names [_syntacticLintCodes] (rules that /// do not require [ResolvedUnitResult]s). void _computeParsedResultLint( - LintRuleUnitContext currentUnit, - List<LintRuleUnitContext> allUnits, + RuleContextUnit currentUnit, + List<RuleContextUnit> allUnits, ) { var nodeRegistry = RuleVisitorRegistry(enableTiming: false); - var context = LinterContextWithParsedResults(allUnits, currentUnit); + // TODO(srawlins): We are passing `currentUnit` in as `definingUnit`. Seems + // wrong. + var context = RuleContextWithParsedResults(allUnits, currentUnit); var lintRules = _syntacticLintCodes .map((name) => Registry.ruleRegistry.getRule(name))
diff --git a/pkg/analysis_server_plugin/lib/src/plugin_server.dart b/pkg/analysis_server_plugin/lib/src/plugin_server.dart index c8b876b..93f2f13 100644 --- a/pkg/analysis_server_plugin/lib/src/plugin_server.dart +++ b/pkg/analysis_server_plugin/lib/src/plugin_server.dart
@@ -321,7 +321,7 @@ var errorReporter = ErrorReporter( listener, unitResult.libraryElement2.firstFragment.source); - var currentUnit = LintRuleUnitContext( + var currentUnit = RuleContextUnit( file: unitResult.file, content: unitResult.content, errorReporter: errorReporter, @@ -329,7 +329,7 @@ ); var allUnits = [ for (var unitResult in libraryResult.units) - LintRuleUnitContext( + RuleContextUnit( file: unitResult.file, content: unitResult.content, errorReporter: errorReporter, @@ -341,7 +341,7 @@ // `benchhmark.dart` script does. var nodeRegistry = RuleVisitorRegistry(enableTiming: false); - var context = LinterContextWithResolvedResults( + var context = RuleContextWithResolvedResults( allUnits, currentUnit, libraryResult.element2.typeProvider,
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart index d13bb4a..51ae44a 100644 --- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart +++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -381,11 +381,11 @@ void _computeLints() { var definingUnit = _libraryElement.definingCompilationUnit; - var analysesToContextUnits = <FileAnalysis, LintRuleUnitContext>{}; - LintRuleUnitContext? definingContextUnit; + var analysesToContextUnits = <FileAnalysis, RuleContextUnit>{}; + RuleContextUnit? definingContextUnit; WorkspacePackageImpl? workspacePackage; for (var fileAnalysis in _libraryFiles.values) { - var linterContextUnit = LintRuleUnitContext( + var linterContextUnit = RuleContextUnit( file: fileAnalysis.file.resource, content: fileAnalysis.file.content, unit: fileAnalysis.unit, @@ -402,7 +402,7 @@ definingContextUnit ??= allUnits.first; var nodeRegistry = RuleVisitorRegistry(enableTiming: _enableLintRuleTiming); - var context = LinterContextWithResolvedResults( + var context = RuleContextWithResolvedResults( allUnits, definingContextUnit, _typeProvider,
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart index 743f3a1..df63b14 100644 --- a/pkg/analyzer/lib/src/lint/linter.dart +++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -23,6 +23,9 @@ show dart2_12, dart3, dart3_3, RuleState; export 'package:analyzer/src/lint/linter_visitor.dart' show NodeLintRegistry; +/// A soon-to-be deprecated alias for [RuleContext]. +typedef LinterContext = RuleContext; + /// Describes an [AbstractAnalysisRule] which reports diagnostics using exactly /// one [DiagnosticCode]. typedef LintRule = AnalysisRule; @@ -30,7 +33,7 @@ /// Describes a static analysis rule, either a lint rule (which must be enabled /// via analysis options) or a warning rule (which is enabled by default). sealed class AbstractAnalysisRule { - /// Used to report lint warnings. + /// Used to report lints and warnings. /// NOTE: this is set by the framework before any node processors start /// visiting nodes. late ErrorReporter _reporter; @@ -38,7 +41,7 @@ /// Short description suitable for display in console output. final String description; - /// Lint name. + /// The rule name. final String name; /// The state of this analysis rule, optionally indicating the "version" that @@ -61,9 +64,10 @@ /// A list of incompatible rule ids. List<String> get incompatibleRules => const []; - /// Returns a visitor that visits a [Pubspec] to perform analysis. + /// A visitor that visits a [Pubspec] to perform analysis. /// - /// Diagnostics are reported via this [LintRule]'s error [reporter]. + /// Diagnostics are reported via this [AbstractAnalysisRule]'s error + /// [reporter]. PubspecVisitor? get pubspecVisitor => null; /// Sets the [ErrorReporter] for the [CompilationUnit] currently being @@ -76,7 +80,7 @@ /// that is not available from the AST nodes or their associated elements. void registerNodeProcessors( RuleVisitorRegistry registry, - LinterContext context, + RuleContext context, ) {} void _reportAtNode( @@ -212,174 +216,6 @@ ); } -/// Provides access to information needed by analysis rules that is not -/// available from AST nodes or the element model. -abstract class LinterContext { - /// The list of all compilation units that make up the library under analysis, - /// including the defining compilation unit, all parts, and all augmentations. - List<LintRuleUnitContext> get allUnits; - - /// The compilation unit being linted. - /// - /// `null` when a unit is not currently being linted (for example when node - /// processors are being registered). - LintRuleUnitContext? get currentUnit; - - /// The defining compilation unit of the library under analysis. - LintRuleUnitContext get definingUnit; - - /// Whether the [definingUnit]'s location is in a package's top-level 'lib' - /// directory, including locations deeply nested, and locations in the - /// package-implementation directory, 'lib/src'. - bool get isInLibDir; - - /// Whether the [definingUnit] is in a [package]'s "test" directory. - bool get isInTestDirectory; - - /// The library element representing the library that contains the compilation - /// unit being linted. - @experimental - LibraryElement? get libraryElement2; - - /// The package in which the library being analyzed lives, or `null` if it - /// does not live in a package. - WorkspacePackage? get package; - - TypeProvider get typeProvider; - - TypeSystem get typeSystem; - - /// Whether the given [feature] is enabled in this linter context. - bool isFeatureEnabled(Feature feature); - - static bool _isInLibDir(String? filePath, WorkspacePackage? package) { - if (package == null) return false; - if (filePath == null) return false; - var libDir = package.root.getChildAssumingFolder('lib'); - return libDir.contains(filePath); - } -} - -/// A [LinterContext] for a library, resolved into [ParsedUnitResult]s. -final class LinterContextWithParsedResults implements LinterContext { - @override - final List<LintRuleUnitContext> allUnits; - - @override - final LintRuleUnitContext definingUnit; - - @override - LintRuleUnitContext? currentUnit; - - LinterContextWithParsedResults(this.allUnits, this.definingUnit); - - @override - bool get isInLibDir => LinterContext._isInLibDir( - definingUnit.unit.declaredFragment?.source.fullName, - package, - ); - - @override - bool get isInTestDirectory => false; - - @experimental - @override - LibraryElement get libraryElement2 => - throw UnsupportedError( - 'LinterContext with parsed results does not include a LibraryElement', - ); - - @override - WorkspacePackage? get package => null; - - @override - TypeProvider get typeProvider => - throw UnsupportedError( - 'LinterContext with parsed results does not include a TypeProvider', - ); - - @override - TypeSystem get typeSystem => - throw UnsupportedError( - 'LinterContext with parsed results does not include a TypeSystem', - ); - - @override - bool isFeatureEnabled(Feature feature) => - throw UnsupportedError( - 'LinterContext with parsed results does not include a LibraryElement', - ); -} - -/// A [LinterContext] for a library, resolved into [ResolvedUnitResult]s. -final class LinterContextWithResolvedResults implements LinterContext { - @override - final List<LintRuleUnitContext> allUnits; - - @override - final LintRuleUnitContext definingUnit; - - @override - LintRuleUnitContext? currentUnit; - - @override - final WorkspacePackage? package; - - @override - final TypeProvider typeProvider; - - @override - final TypeSystem typeSystem; - - LinterContextWithResolvedResults( - this.allUnits, - this.definingUnit, - this.typeProvider, - this.typeSystem, - this.package, - ); - - @override - bool get isInLibDir => LinterContext._isInLibDir( - definingUnit.unit.declaredFragment?.source.fullName, - package, - ); - - @override - bool get isInTestDirectory { - if (package case var package?) { - var file = definingUnit._file; - return package.isInTestDirectory(file); - } - return false; - } - - @experimental - @override - LibraryElement get libraryElement2 => - definingUnit.unit.declaredFragment!.element; - - @override - bool isFeatureEnabled(Feature feature) => - libraryElement2.featureSet.isEnabled(feature); -} - -/// Provides access to information needed by lint rules that is not available -/// from AST nodes or the element model. -class LintRuleUnitContext { - final File _file; - final String content; - final ErrorReporter errorReporter; - final CompilationUnit unit; - - LintRuleUnitContext({ - required File file, - required this.content, - required this.errorReporter, - required this.unit, - }) : _file = file; -} - /// Describes an [AbstractAnalysisRule] which reports diagnostics using multiple /// [DiagnosticCode]s). abstract class MultiAnalysisRule extends AbstractAnalysisRule { @@ -453,3 +289,174 @@ contextMessages: contextMessages, ); } + +/// Provides access to information needed by analysis rules that is not +/// available from AST nodes or the element model. +abstract class RuleContext { + /// The list of all compilation units that make up the library under analysis, + /// including the defining compilation unit, all parts, and all augmentations. + List<RuleContextUnit> get allUnits; + + /// The compilation unit being analyzed. + /// + /// `null` when a unit is not currently being analyzed (for example when node + /// processors are being registered). + RuleContextUnit? get currentUnit; + + /// The defining compilation unit of the library under analysis. + RuleContextUnit get definingUnit; + + /// Whether the [definingUnit]'s location is in a package's top-level 'lib' + /// directory, including locations deeply nested, and locations in the + /// package-implementation directory, 'lib/src'. + bool get isInLibDir; + + /// Whether the [definingUnit] is in a [package]'s "test" directory. + bool get isInTestDirectory; + + /// The library element representing the library that contains the compilation + /// unit being analyzed. + @experimental + LibraryElement? get libraryElement2; + + /// The package in which the library being analyzed lives, or `null` if it + /// does not live in a package. + WorkspacePackage? get package; + + TypeProvider get typeProvider; + + TypeSystem get typeSystem; + + /// Whether the given [feature] is enabled in this rule context. + bool isFeatureEnabled(Feature feature); + + static bool _isInLibDir(String? filePath, WorkspacePackage? package) { + if (package == null) return false; + if (filePath == null) return false; + var libDir = package.root.getChildAssumingFolder('lib'); + return libDir.contains(filePath); + } +} + +/// Provides access to information needed by analysis rules that is not +/// available from AST nodes or the element model. +class RuleContextUnit { + final File _file; + final String content; + final ErrorReporter errorReporter; + final CompilationUnit unit; + + RuleContextUnit({ + required File file, + required this.content, + required this.errorReporter, + required this.unit, + }) : _file = file; +} + +/// A [RuleContext] for a library, parsed into [ParsedUnitResult]s. +/// +/// This is available for analysis rules that can operate on parsed, +/// unresolved syntax trees. +final class RuleContextWithParsedResults implements RuleContext { + @override + final List<RuleContextUnit> allUnits; + + @override + final RuleContextUnit definingUnit; + + @override + RuleContextUnit? currentUnit; + + RuleContextWithParsedResults(this.allUnits, this.definingUnit); + + @override + bool get isInLibDir => RuleContext._isInLibDir( + definingUnit.unit.declaredFragment?.source.fullName, + package, + ); + + @override + bool get isInTestDirectory => false; + + @experimental + @override + LibraryElement get libraryElement2 => + throw UnsupportedError( + 'RuleContext with parsed results does not include a LibraryElement', + ); + + @override + WorkspacePackage? get package => null; + + @override + TypeProvider get typeProvider => + throw UnsupportedError( + 'RuleContext with parsed results does not include a TypeProvider', + ); + + @override + TypeSystem get typeSystem => + throw UnsupportedError( + 'RuleContext with parsed results does not include a TypeSystem', + ); + + @override + bool isFeatureEnabled(Feature feature) => + throw UnsupportedError( + 'RuleContext with parsed results does not include a LibraryElement', + ); +} + +/// A [RuleContext] for a library, resolved into [ResolvedUnitResult]s. +final class RuleContextWithResolvedResults implements RuleContext { + @override + final List<RuleContextUnit> allUnits; + + @override + final RuleContextUnit definingUnit; + + @override + RuleContextUnit? currentUnit; + + @override + final WorkspacePackage? package; + + @override + final TypeProvider typeProvider; + + @override + final TypeSystem typeSystem; + + RuleContextWithResolvedResults( + this.allUnits, + this.definingUnit, + this.typeProvider, + this.typeSystem, + this.package, + ); + + @override + bool get isInLibDir => RuleContext._isInLibDir( + definingUnit.unit.declaredFragment?.source.fullName, + package, + ); + + @override + bool get isInTestDirectory { + if (package case var package?) { + var file = definingUnit._file; + return package.isInTestDirectory(file); + } + return false; + } + + @experimental + @override + LibraryElement get libraryElement2 => + definingUnit.unit.declaredFragment!.element; + + @override + bool isFeatureEnabled(Feature feature) => + libraryElement2.featureSet.isEnabled(feature); +}
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart index 1173cd1..e11266e 100644 --- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart +++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -25,7 +25,7 @@ @reflectiveTest abstract class AbstractLinterContextTest extends PubPackageResolutionTest { - late final LinterContextWithResolvedResults context; + late final RuleContextWithResolvedResults context; Future<void> resolve(String content) async { await resolveTestCode(content); @@ -33,7 +33,7 @@ RecordingErrorListener(), StringSource(result.content, null), ); - var contextUnit = LintRuleUnitContext( + var contextUnit = RuleContextUnit( file: result.file, content: result.content, errorReporter: errorReporter, @@ -46,7 +46,7 @@ var workspace = analysisContext.contextRoot.workspace; var workspacePackage = workspace.findPackageFor(libraryPath); - context = LinterContextWithResolvedResults( + context = RuleContextWithResolvedResults( [contextUnit], contextUnit, result.typeProvider,
diff --git a/pkg/linter/lib/src/rules/use_string_in_part_of_directives.dart b/pkg/linter/lib/src/rules/use_string_in_part_of_directives.dart index f1185ab..6927b51 100644 --- a/pkg/linter/lib/src/rules/use_string_in_part_of_directives.dart +++ b/pkg/linter/lib/src/rules/use_string_in_part_of_directives.dart
@@ -50,6 +50,6 @@ extension on LinterContext { bool get hasEnancedPartsFeatureEnabled => - this is LinterContextWithResolvedResults && + this is RuleContextWithResolvedResults && isFeatureEnabled(Feature.enhanced_parts); }