analyzer: Move RuleContext and RuleContextUnit to public API
Change-Id: I9cca5ee27e623bfa5b878bb0277f5e12e84a745b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431982
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Samuel Rawlins <srawlins@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 0819700..e082c28 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
@@ -17,6 +17,7 @@
import 'package:analysis_server_plugin/edit/fix/fix.dart';
import 'package:analysis_server_plugin/src/correction/dart_change_workspace.dart';
import 'package:analysis_server_plugin/src/correction/fix_generators.dart';
+import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_options.dart';
import 'package:analyzer/dart/analysis/results.dart';
diff --git a/pkg/analysis_server_plugin/lib/src/plugin_server.dart b/pkg/analysis_server_plugin/lib/src/plugin_server.dart
index 93f2f13..0a0eee2 100644
--- a/pkg/analysis_server_plugin/lib/src/plugin_server.dart
+++ b/pkg/analysis_server_plugin/lib/src/plugin_server.dart
@@ -13,6 +13,7 @@
import 'package:analysis_server_plugin/src/correction/dart_change_workspace.dart';
import 'package:analysis_server_plugin/src/correction/fix_processor.dart';
import 'package:analysis_server_plugin/src/registry.dart';
+import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
diff --git a/pkg/analyzer/api.txt b/pkg/analyzer/api.txt
index 6269a79..511e20f 100644
--- a/pkg/analyzer/api.txt
+++ b/pkg/analyzer/api.txt
@@ -1,3 +1,22 @@
+package:analyzer/analysis_rule/rule_context.dart:
+ RuleContext (class extends Object):
+ new (constructor: RuleContext Function())
+ allUnits (getter: List<RuleContextUnit>)
+ currentUnit (getter: RuleContextUnit?)
+ definingUnit (getter: RuleContextUnit)
+ isInLibDir (getter: bool)
+ isInTestDirectory (getter: bool)
+ libraryElement (getter: LibraryElement?)
+ package (getter: WorkspacePackage?)
+ typeProvider (getter: TypeProvider)
+ typeSystem (getter: TypeSystem)
+ isFeatureEnabled (method: bool Function(Feature))
+ RuleContextUnit (class extends Object):
+ new (constructor: RuleContextUnit Function({required String content, required ErrorReporter errorReporter, required File file, required CompilationUnit unit}))
+ content (getter: String)
+ errorReporter (getter: ErrorReporter)
+ file (getter: File)
+ unit (getter: CompilationUnit)
package:analyzer/analysis_rule/rule_state.dart:
dart2_12 (static getter: Version)
dart3 (static getter: Version)
diff --git a/pkg/analyzer/lib/analysis_rule/rule_context.dart b/pkg/analyzer/lib/analysis_rule/rule_context.dart
new file mode 100644
index 0000000..edd940b
--- /dev/null
+++ b/pkg/analyzer/lib/analysis_rule/rule_context.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/dart/element/type_system.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/workspace/workspace.dart';
+
+/// 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.
+ LibraryElement? get libraryElement;
+
+ /// 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);
+}
+
+/// 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 this.file,
+ required this.content,
+ required this.errorReporter,
+ required this.unit,
+ });
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 51ae44a..23b0741 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index df63b14..0111c4a 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/analysis_rule/rule_state.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
@@ -13,16 +14,22 @@
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/lint/linter_visitor.dart' show RuleVisitorRegistry;
import 'package:analyzer/src/lint/pub.dart';
import 'package:analyzer/workspace/workspace.dart';
-import 'package:meta/meta.dart';
export 'package:analyzer/analysis_rule/rule_state.dart'
show dart2_12, dart3, dart3_3, RuleState;
export 'package:analyzer/src/lint/linter_visitor.dart' show NodeLintRegistry;
+/// Returns whether [filePath] is in the top-level `lib` directory in [package].
+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 soon-to-be deprecated alias for [RuleContext].
typedef LinterContext = RuleContext;
@@ -290,70 +297,6 @@
);
}
-/// 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,
@@ -371,17 +314,14 @@
RuleContextWithParsedResults(this.allUnits, this.definingUnit);
@override
- bool get isInLibDir => RuleContext._isInLibDir(
- definingUnit.unit.declaredFragment?.source.fullName,
- package,
- );
+ bool get isInLibDir =>
+ _isInLibDir(definingUnit.unit.declaredFragment?.source.fullName, package);
@override
bool get isInTestDirectory => false;
- @experimental
@override
- LibraryElement get libraryElement2 =>
+ LibraryElement get libraryElement =>
throw UnsupportedError(
'RuleContext with parsed results does not include a LibraryElement',
);
@@ -437,26 +377,23 @@
);
@override
- bool get isInLibDir => RuleContext._isInLibDir(
- definingUnit.unit.declaredFragment?.source.fullName,
- package,
- );
+ bool get isInLibDir =>
+ _isInLibDir(definingUnit.unit.declaredFragment?.source.fullName, package);
@override
bool get isInTestDirectory {
if (package case var package?) {
- var file = definingUnit._file;
+ var file = definingUnit.file;
return package.isInTestDirectory(file);
}
return false;
}
- @experimental
@override
- LibraryElement get libraryElement2 =>
+ LibraryElement get libraryElement =>
definingUnit.unit.declaredFragment!.element;
@override
bool isFeatureEnabled(Feature feature) =>
- libraryElement2.featureSet.isEnabled(feature);
+ libraryElement.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 e11266e..13878ec 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
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analyzer/analysis_rule/rule_context.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/lint/constants.dart';
diff --git a/pkg/linter/lib/src/rules/implementation_imports.dart b/pkg/linter/lib/src/rules/implementation_imports.dart
index 01ce403..d215a1f 100644
--- a/pkg/linter/lib/src/rules/implementation_imports.dart
+++ b/pkg/linter/lib/src/rules/implementation_imports.dart
@@ -24,7 +24,7 @@
NodeLintRegistry registry,
LinterContext context,
) {
- var libraryUri = context.libraryElement2?.uri;
+ var libraryUri = context.libraryElement?.uri;
if (libraryUri == null) return;
// If the source URI is not a `package` URI, bail out.
diff --git a/pkg/linter/lib/src/rules/no_wildcard_variable_uses.dart b/pkg/linter/lib/src/rules/no_wildcard_variable_uses.dart
index df6d65a..b5fb15c 100644
--- a/pkg/linter/lib/src/rules/no_wildcard_variable_uses.dart
+++ b/pkg/linter/lib/src/rules/no_wildcard_variable_uses.dart
@@ -25,7 +25,7 @@
NodeLintRegistry registry,
LinterContext context,
) {
- if (context.libraryElement2.hasWildcardVariablesFeatureEnabled) return;
+ if (context.libraryElement.hasWildcardVariablesFeatureEnabled) return;
var visitor = _Visitor(this);
registry.addSimpleIdentifier(this, visitor);
diff --git a/pkg/linter/lib/src/rules/prefer_relative_imports.dart b/pkg/linter/lib/src/rules/prefer_relative_imports.dart
index 8bbc788..f8aef87 100644
--- a/pkg/linter/lib/src/rules/prefer_relative_imports.dart
+++ b/pkg/linter/lib/src/rules/prefer_relative_imports.dart
@@ -32,7 +32,7 @@
) {
if (!context.isInLibDir) return;
- var sourceUri = context.libraryElement2?.uri;
+ var sourceUri = context.libraryElement?.uri;
if (sourceUri == null) return;
var visitor = _Visitor(this, sourceUri, context);
diff --git a/pkg/linter/lib/src/rules/require_trailing_commas.dart b/pkg/linter/lib/src/rules/require_trailing_commas.dart
index a0983bb..b81204b 100644
--- a/pkg/linter/lib/src/rules/require_trailing_commas.dart
+++ b/pkg/linter/lib/src/rules/require_trailing_commas.dart
@@ -29,7 +29,7 @@
LinterContext context,
) {
// Don't report if tall-style is enforced by the formatter.
- var languageVersion = context.libraryElement2?.languageVersion.effective;
+ var languageVersion = context.libraryElement?.languageVersion.effective;
if (languageVersion != null && languageVersion >= language37) return;
var visitor = _Visitor(this);