analyzer: Make various AnalysisRule classes and their dependencies public

This is a big CL; no code is really "changed." We basically move 3
components into the public API, which can all be reviewed concisely
in the `api.txt` file.

* The AnalysisRule classes: `AbstractAnalysisRule` (which is good to
  make public as a lot of the public API is specified and documented
  here), `AnalysisRule`, `MultiAnalysisRule`.
* The Pubspec classes, available for linting pubspec files:
  `PubspecDependency`, `PubspecDependencyList`, `PubspecEntry`,
  `PubspecEnvironment`, `PubspecGitRepo`, `PubspecHost`, `PubspecNode`,
  `PubspecNodeList`, `PubspecVisitor`.
* The `RuleVisitorRegistry` class. This class is needed by analysis
  rule authors, and is part of the public API of AnalysisRule.

Change-Id: Ib1803180de9469f4ff39cf1778f96787f5f74b14
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/432363
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Paul Berry <paulberry@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 e082c28..a3ebe12 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
@@ -535,7 +535,7 @@
     RuleContextUnit currentUnit,
     List<RuleContextUnit> allUnits,
   ) {
-    var nodeRegistry = RuleVisitorRegistry(enableTiming: false);
+    var nodeRegistry = RuleVisitorRegistryImpl(enableTiming: false);
     // TODO(srawlins): We are passing `currentUnit` in as `definingUnit`. Seems
     // wrong.
     var context = RuleContextWithParsedResults(allUnits, currentUnit);
diff --git a/pkg/analysis_server_plugin/api.txt b/pkg/analysis_server_plugin/api.txt
index 39dc392..9289d45 100644
--- a/pkg/analysis_server_plugin/api.txt
+++ b/pkg/analysis_server_plugin/api.txt
@@ -157,6 +157,8 @@
   int (referenced)
 package:_fe_analyzer_shared/src/scanner/token.dart:
   Token (referenced)
+package:analyzer/analysis_rule/analysis_rule.dart:
+  AnalysisRule (referenced)
 package:analyzer/dart/analysis/analysis_options.dart:
   AnalysisOptions (referenced)
 package:analyzer/dart/analysis/features.dart:
@@ -202,8 +204,6 @@
   Name (referenced)
 package:analyzer/src/dart/error/lint_codes.dart:
   LintCode (referenced)
-package:analyzer/src/lint/linter.dart:
-  AnalysisRule (referenced)
 package:analyzer_plugin/protocol/protocol_common.dart:
   SourceChange (referenced)
 package:analyzer_plugin/utilities/assist/assist.dart:
diff --git a/pkg/analysis_server_plugin/lib/src/plugin_server.dart b/pkg/analysis_server_plugin/lib/src/plugin_server.dart
index 0a0eee2..267f20a 100644
--- a/pkg/analysis_server_plugin/lib/src/plugin_server.dart
+++ b/pkg/analysis_server_plugin/lib/src/plugin_server.dart
@@ -340,7 +340,7 @@
 
     // TODO(srawlins): Enable timing similar to what the linter package's
     // `benchhmark.dart` script does.
-    var nodeRegistry = RuleVisitorRegistry(enableTiming: false);
+    var nodeRegistry = RuleVisitorRegistryImpl(enableTiming: false);
 
     var context = RuleContextWithResolvedResults(
       allUnits,
diff --git a/pkg/analysis_server_plugin/test/src/lint_rules.dart b/pkg/analysis_server_plugin/test/src/lint_rules.dart
index 97440d2..cd1160c 100644
--- a/pkg/analysis_server_plugin/test/src/lint_rules.dart
+++ b/pkg/analysis_server_plugin/test/src/lint_rules.dart
@@ -2,11 +2,11 @@
 // 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_visitor_registry.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/lint/linter.dart';
-import 'package:analyzer/src/lint/linter_visitor.dart';
 
 class NoBoolsRule extends AnalysisRule {
   static const LintCode code = LintCode('no_bools', 'No bools message');
diff --git a/pkg/analysis_server_plugin/test/src/plugin_server_error_test.dart b/pkg/analysis_server_plugin/test/src/plugin_server_error_test.dart
index be12a3b..7c44a7a 100644
--- a/pkg/analysis_server_plugin/test/src/plugin_server_error_test.dart
+++ b/pkg/analysis_server_plugin/test/src/plugin_server_error_test.dart
@@ -8,11 +8,11 @@
 import 'package:analysis_server_plugin/plugin.dart';
 import 'package:analysis_server_plugin/registry.dart';
 import 'package:analysis_server_plugin/src/plugin_server.dart';
+import 'package:analyzer/analysis_rule/rule_visitor_registry.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/lint/linter.dart';
-import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer_plugin/protocol/protocol_constants.dart' as protocol;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as protocol;
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
diff --git a/pkg/analyzer/api.txt b/pkg/analyzer/api.txt
index 536876e..4f3d512 100644
--- a/pkg/analyzer/api.txt
+++ b/pkg/analyzer/api.txt
@@ -1,3 +1,84 @@
+package:analyzer/analysis_rule/analysis_rule.dart:
+  AbstractAnalysisRule (class extends Object, sealed (immediate subtypes: AnalysisRule, MultiAnalysisRule)):
+    canUseParsedResult (getter: bool)
+    description (getter: String)
+    diagnosticCodes (getter: List<DiagnosticCode>)
+    incompatibleRules (getter: List<String>)
+    name (getter: String)
+    pubspecVisitor (getter: PubspecVisitor<dynamic>?)
+    reporter= (setter: ErrorReporter)
+    state (getter: RuleState)
+    registerNodeProcessors (method: void Function(RuleVisitorRegistry, RuleContext))
+  AnalysisRule (class extends AbstractAnalysisRule):
+    new (constructor: AnalysisRule Function({required String description, required String name, RuleState state}))
+    diagnosticCode (getter: DiagnosticCode)
+    diagnosticCodes (getter: List<DiagnosticCode>)
+    reportAtNode (method: void Function(AstNode?, {List<Object> arguments, List<DiagnosticMessage>? contextMessages}))
+    reportAtOffset (method: void Function(int, int, {List<Object> arguments, List<DiagnosticMessage>? contextMessages}))
+    reportAtPubNode (method: void Function(PubspecNode, {List<Object> arguments, List<DiagnosticMessage> contextMessages}))
+    reportAtToken (method: void Function(Token, {List<Object> arguments, List<DiagnosticMessage>? contextMessages}))
+  MultiAnalysisRule (class extends AbstractAnalysisRule):
+    new (constructor: MultiAnalysisRule Function({required String description, required String name, RuleState state}))
+    reportAtNode (method: void Function(AstNode?, {List<Object> arguments, List<DiagnosticMessage>? contextMessages, required DiagnosticCode diagnosticCode}))
+    reportAtOffset (method: void Function(int, int, {List<Object> arguments, List<DiagnosticMessage>? contextMessages, required DiagnosticCode diagnosticCode}))
+    reportAtPubNode (method: void Function(PubspecNode, {List<Object> arguments, List<DiagnosticMessage> contextMessages, required DiagnosticCode diagnosticCode}))
+    reportAtToken (method: void Function(Token, {List<Object> arguments, List<DiagnosticMessage>? contextMessages, required DiagnosticCode diagnosticCode}))
+package:analyzer/analysis_rule/pubspec.dart:
+  PubspecDependency (class extends Object):
+    new (constructor: PubspecDependency Function())
+    git (getter: PubspecGitRepo?)
+    host (getter: PubspecHost?)
+    name (getter: PubspecNode?)
+    path (getter: PubspecEntry?)
+    version (getter: PubspecEntry?)
+  PubspecDependencyList (class extends Object):
+    new (constructor: PubspecDependencyList Function())
+  PubspecEntry (class extends Object):
+    new (constructor: PubspecEntry Function(PubspecNode?, PubspecNode))
+    key (getter: PubspecNode?)
+    value (getter: PubspecNode)
+    toString (method: String Function())
+  PubspecEnvironment (class extends Object implements PubspecSection):
+    new (constructor: PubspecEnvironment Function())
+    flutter (getter: PubspecEntry?)
+    sdk (getter: PubspecEntry?)
+  PubspecGitRepo (class extends Object implements PubspecSection):
+    new (constructor: PubspecGitRepo Function())
+    ref (getter: PubspecEntry?)
+    url (getter: PubspecEntry?)
+  PubspecHost (class extends Object implements PubspecSection):
+    new (constructor: PubspecHost Function())
+    isShortForm (getter: bool)
+    name (getter: PubspecEntry?)
+    url (getter: PubspecEntry?)
+  PubspecNode (class extends Object):
+    new (constructor: PubspecNode Function())
+    span (getter: SourceSpan)
+    text (getter: String?)
+  PubspecNodeList (class extends Object implements PubspecSection):
+    new (constructor: PubspecNodeList Function())
+    iterator (getter: Iterator<PubspecNode>)
+  PubspecSection (class extends Object):
+    new (constructor: PubspecSection Function())
+    token (getter: PubspecNode)
+  PubspecVisitor (class<T> extends Object):
+    new (constructor: PubspecVisitor<T> Function())
+    visitPackageAuthor (method: T? Function(PubspecEntry))
+    visitPackageAuthors (method: T? Function(PubspecNodeList))
+    visitPackageDependencies (method: T? Function(PubspecDependencyList))
+    visitPackageDependency (method: T? Function(PubspecDependency))
+    visitPackageDependencyOverride (method: T? Function(PubspecDependency))
+    visitPackageDependencyOverrides (method: T? Function(PubspecDependencyList))
+    visitPackageDescription (method: T? Function(PubspecEntry))
+    visitPackageDevDependencies (method: T? Function(PubspecDependencyList))
+    visitPackageDevDependency (method: T? Function(PubspecDependency))
+    visitPackageDocumentation (method: T? Function(PubspecEntry))
+    visitPackageEnvironment (method: T? Function(PubspecEnvironment))
+    visitPackageHomepage (method: T? Function(PubspecEntry))
+    visitPackageIssueTracker (method: T? Function(PubspecEntry))
+    visitPackageName (method: T? Function(PubspecEntry))
+    visitPackageRepository (method: T? Function(PubspecEntry))
+    visitPackageVersion (method: T? Function(PubspecEntry))
 package:analyzer/analysis_rule/rule_context.dart:
   RuleContext (class extends Object):
     new (constructor: RuleContext Function())
@@ -34,6 +115,181 @@
     label (getter: String)
     replacedBy (getter: String?)
     since (getter: Version?)
+package:analyzer/analysis_rule/rule_visitor_registry.dart:
+  RuleVisitorRegistry (class extends Object):
+    new (constructor: RuleVisitorRegistry Function())
+    addAdjacentStrings (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAnnotation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addArgumentList (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAsExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAssertInitializer (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAssertStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAssignedVariablePattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAssignmentExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAugmentedExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAugmentedInvocation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addAwaitExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addBinaryExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addBlock (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addBlockFunctionBody (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addBooleanLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addBreakStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addCascadeExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addCaseClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addCastPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addCatchClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addCatchClauseParameter (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addClassDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addClassTypeAlias (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addComment (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addCommentReference (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addCompilationUnit (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConditionalExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConfiguration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConstantPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConstructorDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConstructorFieldInitializer (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConstructorName (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConstructorReference (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addConstructorSelector (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addContinueStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDeclaredIdentifier (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDeclaredVariablePattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDefaultFormalParameter (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDoStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDotShorthandConstructorInvocation (method: void Function(AnalysisRule, AstVisitor<dynamic>))
+    addDotShorthandInvocation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDotShorthandPropertyAccess (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDottedName (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addDoubleLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addEmptyFunctionBody (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addEmptyStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addEnumConstantArguments (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addEnumConstantDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addEnumDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExportDirective (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExpressionFunctionBody (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExpressionStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExtendsClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExtensionDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExtensionOnClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExtensionOverride (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addExtensionTypeDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFieldDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFieldFormalParameter (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForEachPartsWithDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForEachPartsWithIdentifier (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForEachPartsWithPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForElement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForPartsWithDeclarations (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForPartsWithExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForPartsWithPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addForStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFormalParameterList (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFunctionDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFunctionDeclarationStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFunctionExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFunctionExpressionInvocation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFunctionReference (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFunctionTypeAlias (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addFunctionTypedFormalParameter (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addGenericFunctionType (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addGenericTypeAlias (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addGuardedPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addHideCombinator (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addIfElement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addIfStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addImplementsClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addImplicitCallReference (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addImportDirective (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addImportPrefixReference (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addIndexExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addInstanceCreationExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addIntegerLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addInterpolationExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addInterpolationString (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addIsExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addLabel (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addLabeledStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addLibraryDirective (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addLibraryIdentifier (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addListLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addListPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addLogicalAndPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addLogicalOrPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addMapLiteralEntry (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addMapPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addMapPatternEntry (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addMethodDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addMethodInvocation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addMixinDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addMixinOnClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addNamedExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addNamedType (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addNativeClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addNativeFunctionBody (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addNullAssertPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addNullCheckPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addNullLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addObjectPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addParenthesizedExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addParenthesizedPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPartDirective (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPartOfDirective (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPatternAssignment (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPatternField (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPatternFieldName (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPatternVariableDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPatternVariableDeclarationStatement (method: void Function(AnalysisRule, AstVisitor<dynamic>))
+    addPostfixExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPrefixExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPrefixedIdentifier (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addPropertyAccess (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRecordLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRecordPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRecordTypeAnnotation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRedirectingConstructorInvocation (method: void Function(AnalysisRule, AstVisitor<dynamic>))
+    addRelationalPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRepresentationConstructorName (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRepresentationDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRestPatternElement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addRethrowExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addReturnStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addScriptTag (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSetOrMapLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addShowCombinator (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSimpleFormalParameter (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSimpleIdentifier (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSimpleStringLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSpreadElement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addStringInterpolation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSuperConstructorInvocation (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSuperExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSuperFormalParameter (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSwitchCase (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSwitchDefault (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSwitchExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSwitchExpressionCase (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSwitchPatternCase (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSwitchStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addSymbolLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addThisExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addThrowExpression (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addTopLevelVariableDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addTryStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addTypeArgumentList (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addTypeLiteral (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addTypeParameter (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addTypeParameterList (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addVariableDeclaration (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addVariableDeclarationList (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addVariableDeclarationStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addWhenClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addWhileStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addWildcardPattern (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addWithClause (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    addYieldStatement (method: void Function(AbstractAnalysisRule, AstVisitor<dynamic>))
+    afterLibrary (method: void Function(AbstractAnalysisRule, void Function()))
 package:analyzer/dart/analysis/analysis_context.dart:
   AnalysisContext@1 (class extends Object):
     new (constructor: AnalysisContext@1 Function())
@@ -4881,8 +5137,6 @@
     modificationTime (getter: int)
 package:analyzer/src/lint/config.dart:
   RuleConfig (non-public)
-package:analyzer/src/lint/linter.dart:
-  AbstractAnalysisRule (non-public)
 package:analyzer/src/workspace/workspace.dart:
   Workspace (non-public)
 package:analyzer/utilities/extensions/ast.dart:
@@ -4917,6 +5171,7 @@
   Duration (referenced)
   Exception (referenced)
   Iterable (referenced)
+  Iterator (referenced)
   List (referenced)
   Map (referenced)
   Null (referenced)
diff --git a/pkg/analyzer/lib/analysis_rule/analysis_rule.dart b/pkg/analyzer/lib/analysis_rule/analysis_rule.dart
new file mode 100644
index 0000000..e7e6e83
--- /dev/null
+++ b/pkg/analyzer/lib/analysis_rule/analysis_rule.dart
@@ -0,0 +1,284 @@
+// Copyright (c) 2015, 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/analysis_rule/pubspec.dart';
+import 'package:analyzer/analysis_rule/rule_context.dart';
+import 'package:analyzer/analysis_rule/rule_state.dart';
+import 'package:analyzer/analysis_rule/rule_visitor_registry.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/lint/pub.dart';
+
+/// 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 lints and warnings.
+  ///
+  /// NOTE: this is set by the framework before any node processors start
+  /// visiting nodes.
+  late ErrorReporter _reporter;
+
+  /// Short description suitable for display in console output and IDEs.
+  ///
+  /// This text may be used when providing information about a rule listed in
+  /// analysis options file, or to suggest enabling a rule.
+  final String description;
+
+  /// The rule name.
+  final String name;
+
+  /// The state of this analysis rule.
+  ///
+  /// See [RuleState] for a list of the possible states and when they should be
+  /// applied to a given rule.
+  final RuleState state;
+
+  AbstractAnalysisRule({
+    required this.name,
+    required this.description,
+    this.state = const RuleState.stable(),
+  });
+
+  /// Indicates whether this analysis rule can work with just the parsed
+  /// information or if it requires a resolved unit.
+  bool get canUseParsedResult => false;
+
+  /// The diagnostic codes associated with this analysis rule.
+  List<DiagnosticCode> get diagnosticCodes;
+
+  /// A list of incompatible rule names.
+  ///
+  /// Two rules are incompatible if there are situations where it is difficult
+  /// or impossible to comply with both. The analyzer will warn if two
+  /// incompatible rules are both enabled in analysis options.
+  List<String> get incompatibleRules => const [];
+
+  /// A visitor that visits a [Pubspec] to perform analysis.
+  ///
+  /// Diagnostics are reported via this [AbstractAnalysisRule]'s error
+  /// [reporter].
+  PubspecVisitor? get pubspecVisitor => null;
+
+  /// Sets the [ErrorReporter] for the [CompilationUnit] currently being
+  /// visited.
+  set reporter(ErrorReporter value) => _reporter = value;
+
+  /// Registers node processors in the given [registry].
+  ///
+  /// The node processors may use the provided [context] to access information
+  /// that is not available from the AST nodes or their associated elements.
+  void registerNodeProcessors(
+    RuleVisitorRegistry registry,
+    RuleContext context,
+  ) {}
+
+  void _reportAtNode(
+    AstNode? node, {
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+    required DiagnosticCode diagnosticCode,
+  }) {
+    if (node != null && !node.isSynthetic) {
+      _reporter.atNode(
+        node,
+        diagnosticCode,
+        arguments: arguments,
+        contextMessages: contextMessages,
+      );
+    }
+  }
+
+  void _reportAtOffset(
+    int offset,
+    int length, {
+    required DiagnosticCode diagnosticCode,
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+  }) {
+    _reporter.atOffset(
+      offset: offset,
+      length: length,
+      diagnosticCode: diagnosticCode,
+      arguments: arguments,
+      contextMessages: contextMessages,
+    );
+  }
+
+  void _reportAtPubNode(
+    PubspecNodeImpl node, {
+    List<Object> arguments = const [],
+    List<DiagnosticMessage> contextMessages = const [],
+    required DiagnosticCode diagnosticCode,
+  }) {
+    // Cache diagnostic and location info for creating `AnalysisErrorInfo`s.
+    var diagnostic = Diagnostic.tmp(
+      source: node.source,
+      offset: node.span.start.offset,
+      length: node.span.length,
+      errorCode: diagnosticCode,
+      arguments: arguments,
+      contextMessages: contextMessages,
+    );
+    _reporter.reportError(diagnostic);
+  }
+
+  void _reportAtToken(
+    Token token, {
+    required DiagnosticCode diagnosticCode,
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+  }) {
+    if (!token.isSynthetic) {
+      _reporter.atToken(
+        token,
+        diagnosticCode,
+        arguments: arguments,
+        contextMessages: contextMessages,
+      );
+    }
+  }
+}
+
+/// Describes an [AbstractAnalysisRule] which reports exactly one type of
+/// diagnostic (one [DiagnosticCode]).
+abstract class AnalysisRule extends AbstractAnalysisRule {
+  AnalysisRule({required super.name, required super.description, super.state});
+
+  /// The code to report for a violation.
+  DiagnosticCode get diagnosticCode;
+
+  @override
+  List<DiagnosticCode> get diagnosticCodes => [diagnosticCode];
+
+  /// Reports a diagnostic at [node] with message [arguments] and
+  /// [contextMessages].
+  void reportAtNode(
+    AstNode? node, {
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+  }) => _reportAtNode(
+    node,
+    diagnosticCode: diagnosticCode,
+    arguments: arguments,
+    contextMessages: contextMessages,
+  );
+
+  /// Reports a diagnostic at [offset], with [length], with message [arguments]
+  /// and [contextMessages].
+  void reportAtOffset(
+    int offset,
+    int length, {
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+  }) => _reportAtOffset(
+    offset,
+    length,
+    diagnosticCode: diagnosticCode,
+    arguments: arguments,
+    contextMessages: contextMessages,
+  );
+
+  /// Reports a diagnostic at Pubspec [node], with message [arguments] and
+  /// [contextMessages].
+  void reportAtPubNode(
+    PubspecNode node, {
+    List<Object> arguments = const [],
+    List<DiagnosticMessage> contextMessages = const [],
+  }) => _reportAtPubNode(
+    node as PubspecNodeImpl,
+    diagnosticCode: diagnosticCode,
+    arguments: arguments,
+    contextMessages: contextMessages,
+  );
+
+  /// Reports a diagnostic at [token], with message [arguments] and
+  /// [contextMessages].
+  void reportAtToken(
+    Token token, {
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+  }) => _reportAtToken(
+    token,
+    diagnosticCode: diagnosticCode,
+    arguments: arguments,
+    contextMessages: contextMessages,
+  );
+}
+
+/// Describes an [AbstractAnalysisRule] which reports diagnostics using multiple
+/// [DiagnosticCode]s).
+abstract class MultiAnalysisRule extends AbstractAnalysisRule {
+  MultiAnalysisRule({
+    required super.name,
+    required super.description,
+    super.state,
+  });
+
+  /// Reports [diagnosticCode] at [node] with message [arguments] and
+  /// [contextMessages].
+  void reportAtNode(
+    AstNode? node, {
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+    required DiagnosticCode diagnosticCode,
+  }) => _reportAtNode(
+    node,
+    diagnosticCode: diagnosticCode,
+    arguments: arguments,
+    contextMessages: contextMessages,
+  );
+
+  /// Reports [diagnosticCode] at [offset], with [length], with message [arguments]
+  /// and [contextMessages].
+  void reportAtOffset(
+    int offset,
+    int length, {
+    required DiagnosticCode diagnosticCode,
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+  }) => _reportAtOffset(
+    offset,
+    length,
+    diagnosticCode: diagnosticCode,
+    arguments: arguments,
+    contextMessages: contextMessages,
+  );
+
+  /// Reports [diagnosticCode] at Pubspec [node], with message [arguments] and
+  /// [contextMessages].
+  void reportAtPubNode(
+    PubspecNode node, {
+    required DiagnosticCode diagnosticCode,
+    List<Object> arguments = const [],
+    List<DiagnosticMessage> contextMessages = const [],
+  }) {
+    // Cache error and location info for creating `AnalysisErrorInfo`s.
+    var error = Diagnostic.tmp(
+      source: (node as PubspecNodeImpl).source,
+      offset: node.span.start.offset,
+      length: node.span.length,
+      errorCode: diagnosticCode,
+      arguments: arguments,
+      contextMessages: contextMessages,
+    );
+    _reporter.reportError(error);
+  }
+
+  /// Reports [diagnosticCode] at [token], with message [arguments] and
+  /// [contextMessages].
+  void reportAtToken(
+    Token token, {
+    required DiagnosticCode diagnosticCode,
+    List<Object> arguments = const [],
+    List<DiagnosticMessage>? contextMessages,
+  }) => _reportAtToken(
+    token,
+    diagnosticCode: diagnosticCode,
+    arguments: arguments,
+    contextMessages: contextMessages,
+  );
+}
diff --git a/pkg/analyzer/lib/analysis_rule/pubspec.dart b/pkg/analyzer/lib/analysis_rule/pubspec.dart
new file mode 100644
index 0000000..fdf253f
--- /dev/null
+++ b/pkg/analyzer/lib/analysis_rule/pubspec.dart
@@ -0,0 +1,209 @@
+// Copyright (c) 2015, 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 'dart:collection';
+
+import 'package:source_span/source_span.dart';
+
+/// Representation of a key/value pair which maps a package name to a
+/// _package description_.
+///
+/// **Example** of a path-dependency:
+/// ```yaml
+/// dependencies:
+///   <name>:
+///     version: <version>
+///     path: <path>
+/// ```
+abstract class PubspecDependency {
+  /// The git dependency section, if specified.
+  PubspecGitRepo? get git;
+
+  /// The host section, if specified.
+  PubspecHost? get host;
+
+  /// The dependency name, if specified.
+  PubspecNode? get name;
+
+  /// The path section, if specified.
+  PubspecEntry? get path;
+
+  /// The dependency version, if specified.
+  PubspecEntry? get version;
+}
+
+/// Representation of the map from package name to _package description_ used
+/// under `dependencies`, `dev_dependencies` and `dependency_overrides`.
+abstract class PubspecDependencyList with IterableMixin<PubspecDependency> {}
+
+/// Representation of a YAML section in a pubspec file.
+class PubspecEntry {
+  final PubspecNode? key;
+  final PubspecNode value;
+
+  PubspecEntry(this.key, this.value);
+
+  @override
+  String toString() => '${key != null ? '$key: ' : ''}$value';
+}
+
+/// Representation of an `environment` section in a pubspec file.
+///
+/// **Example** of an environment:
+/// ```yaml
+/// environment:
+///   sdk: '>=2.12.0 <4.0.0'
+///   flutter: ^3.3.10
+/// ```
+abstract class PubspecEnvironment implements PubspecSection {
+  /// The `flutter` section, if specified.
+  PubspecEntry? get flutter;
+
+  /// The (Dart) `sdk` section, if specified.
+  PubspecEntry? get sdk;
+}
+
+/// Representation of git-dependency section in a pubspec file.
+///
+/// **Example** of a git-dependency:
+/// ```yaml
+/// dependencies:
+///   foo:
+///     git: # <-- this is the [token] property
+///       url: https://github.com/example/example
+///       ref: main # ref is optional
+/// ```
+///
+/// This may also be written in the form:
+/// ```yaml
+/// dependencies:
+///   foo:
+///     git:       https://github.com/example/example
+///     # ^-token  ^--url
+///     # In this case [ref] is `null`.
+/// ```
+abstract class PubspecGitRepo implements PubspecSection {
+  /// [PubspecEntry] for `ref: main` where [PubspecEntry.key] is `ref` and
+  /// [PubspecEntry.value] is `main`.
+  PubspecEntry? get ref;
+
+  /// [PubspecEntry] for `url: https://...` or `git: https://`, where [PubspecEntry.key]
+  /// is either `url` or `git`, and [PubspecEntry.key] is the URL.
+  ///
+  /// If the git-dependency is given in the form:
+  /// ```yaml
+  /// dependencies:
+  ///   foo:
+  ///     git:       https://github.com/example/example
+  /// ```
+  /// Then [token] and `url.key` will be the same object.
+  PubspecEntry? get url;
+}
+
+/// A section describing where a package is hosted in a custom package
+/// repository.
+abstract class PubspecHost implements PubspecSection {
+  /// True, if _short-form_ for writing hosted-dependencies was used.
+  ///
+  /// **Example** of a hosted-dependency written in short-form:
+  /// ```yaml
+  /// dependencies:
+  ///   foo:
+  ///     hosted: https://some-pub-server.com
+  ///     version: ^1.2.3
+  /// ```
+  ///
+  /// The _long-form_ for writing the dependency given above is:
+  /// ```yaml
+  /// dependencies:
+  ///   foo:
+  ///     hosted:
+  ///       url: https://some-pub-server.com
+  ///       name: foo
+  ///     version: ^1.2.3
+  /// ```
+  ///
+  /// The short-form was added in Dart 2.15.0 because:
+  ///  * The `name` property just specifies the package name, which can be
+  ///    inferred from the context. So it is unnecessary to write it.
+  ///  * The nested object and `url` key becomes unnecessary when the `name`
+  ///    property is removed.
+  bool get isShortForm;
+
+  /// The name of the package at the package repository.
+  PubspecEntry? get name;
+
+  /// The URL of the package repository.
+  PubspecEntry? get url;
+}
+
+/// Representation of a leaf-node in a pubspec file.
+abstract class PubspecNode {
+  /// Information about this node's location in the pubspec file.
+  SourceSpan get span;
+
+  /// String value of the node, or `null` if value in the pubspec file is `null`
+  /// or omitted.
+  ///
+  /// **Example**
+  /// ```
+  /// name: foo
+  /// version:
+  /// ```
+  /// In the example above the [PubspecNode] for `foo` will have [text] "foo", and
+  /// the [PubspecNode] for `version` will have not have [text] as `null`, as empty
+  /// value or `"null"` is the same in YAML.
+  String? get text;
+}
+
+/// A list of [PubspecNode]s in a section.
+abstract class PubspecNodeList
+    with IterableMixin<PubspecNode>
+    implements PubspecSection {
+  @override
+  Iterator<PubspecNode> get iterator;
+}
+
+abstract class PubspecSection {
+  /// The node for this section's key.
+  ///
+  /// This is primarily used in the string representation of node classes.
+  PubspecNode get token;
+}
+
+/// A visitor that visits various semantic sections of a pubspec file.
+abstract class PubspecVisitor<T> {
+  T? visitPackageAuthor(PubspecEntry author) => null;
+
+  T? visitPackageAuthors(PubspecNodeList authors) => null;
+
+  T? visitPackageDependencies(PubspecDependencyList dependencies) => null;
+
+  T? visitPackageDependency(PubspecDependency dependency) => null;
+
+  T? visitPackageDependencyOverride(PubspecDependency dependency) => null;
+
+  T? visitPackageDependencyOverrides(PubspecDependencyList dependencies) =>
+      null;
+
+  T? visitPackageDescription(PubspecEntry description) => null;
+
+  T? visitPackageDevDependencies(PubspecDependencyList dependencies) => null;
+
+  T? visitPackageDevDependency(PubspecDependency dependency) => null;
+
+  T? visitPackageDocumentation(PubspecEntry documentation) => null;
+
+  T? visitPackageEnvironment(PubspecEnvironment environment) => null;
+
+  T? visitPackageHomepage(PubspecEntry homepage) => null;
+
+  T? visitPackageIssueTracker(PubspecEntry issueTracker) => null;
+
+  T? visitPackageName(PubspecEntry name) => null;
+
+  T? visitPackageRepository(PubspecEntry repository) => null;
+
+  T? visitPackageVersion(PubspecEntry version) => null;
+}
diff --git a/pkg/analyzer/lib/analysis_rule/rule_visitor_registry.dart b/pkg/analyzer/lib/analysis_rule/rule_visitor_registry.dart
new file mode 100644
index 0000000..0ab48ca
--- /dev/null
+++ b/pkg/analyzer/lib/analysis_rule/rule_visitor_registry.dart
@@ -0,0 +1,438 @@
+// Copyright (c) 2018, 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/ast/ast.dart';
+import 'package:analyzer/src/lint/linter.dart';
+
+/// The container to register visitors for separate AST node types.
+///
+/// Source files are visited by the Dart analysis server recursively. Only the
+/// visitors that are registered to visit a given node type will visit such
+/// nodes. Each analysis rule overrides
+/// [AbstractAnalysisRule.registerNodeProcessors] and calls `add*` for each of
+/// the node types it needs to visit with an [AstVisitor], which registers that
+/// visitor.
+abstract class RuleVisitorRegistry {
+  void addAdjacentStrings(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAnnotation(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addArgumentList(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAsExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAssertInitializer(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAssertStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAssignedVariablePattern(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addAssignmentExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAugmentedExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAugmentedInvocation(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addAwaitExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addBinaryExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addBlock(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addBlockFunctionBody(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addBooleanLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addBreakStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addCascadeExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addCaseClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addCastPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addCatchClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addCatchClauseParameter(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addClassDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addClassTypeAlias(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addComment(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addCommentReference(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addCompilationUnit(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addConditionalExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addConfiguration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addConstantPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addConstructorDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addConstructorFieldInitializer(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addConstructorName(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addConstructorReference(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addConstructorSelector(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addContinueStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addDeclaredIdentifier(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addDeclaredVariablePattern(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addDefaultFormalParameter(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addDoStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addDotShorthandConstructorInvocation(
+    AnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addDotShorthandInvocation(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addDotShorthandPropertyAccess(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addDottedName(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addDoubleLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addEmptyFunctionBody(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addEmptyStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addEnumConstantArguments(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addEnumConstantDeclaration(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addEnumDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExportDirective(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExpressionFunctionBody(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExpressionStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExtendsClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExtensionDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExtensionOnClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExtensionOverride(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addExtensionTypeDeclaration(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addFieldDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addFieldFormalParameter(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addForEachPartsWithDeclaration(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addForEachPartsWithIdentifier(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addForEachPartsWithPattern(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addForElement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addFormalParameterList(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addForPartsWithDeclarations(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addForPartsWithExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addForPartsWithPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addForStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addFunctionDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addFunctionDeclarationStatement(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addFunctionExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addFunctionExpressionInvocation(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addFunctionReference(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addFunctionTypeAlias(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addFunctionTypedFormalParameter(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addGenericFunctionType(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addGenericTypeAlias(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addGuardedPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addHideCombinator(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addIfElement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addIfStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addImplementsClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addImplicitCallReference(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addImportDirective(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addImportPrefixReference(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addIndexExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addInstanceCreationExpression(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addIntegerLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addInterpolationExpression(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addInterpolationString(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addIsExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addLabel(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addLabeledStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addLibraryDirective(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addLibraryIdentifier(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addListLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addListPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addLogicalAndPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addLogicalOrPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addMapLiteralEntry(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addMapPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addMapPatternEntry(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addMethodDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addMethodInvocation(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addMixinDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addMixinOnClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addNamedExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addNamedType(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addNativeClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addNativeFunctionBody(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addNullAssertPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addNullCheckPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addNullLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addObjectPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addParenthesizedExpression(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addParenthesizedPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPartDirective(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPartOfDirective(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPatternAssignment(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPatternField(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPatternFieldName(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPatternVariableDeclaration(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addPatternVariableDeclarationStatement(
+    AnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addPostfixExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPrefixedIdentifier(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPrefixExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addPropertyAccess(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addRecordLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addRecordPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addRecordTypeAnnotation(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addRedirectingConstructorInvocation(
+    AnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addRelationalPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addRepresentationConstructorName(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addRepresentationDeclaration(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addRestPatternElement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addRethrowExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addReturnStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addScriptTag(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSetOrMapLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addShowCombinator(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSimpleFormalParameter(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSimpleIdentifier(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSimpleStringLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSpreadElement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addStringInterpolation(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSuperConstructorInvocation(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addSuperExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSuperFormalParameter(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSwitchCase(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSwitchDefault(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSwitchExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSwitchExpressionCase(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSwitchPatternCase(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSwitchStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addSymbolLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addThisExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addThrowExpression(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addTopLevelVariableDeclaration(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addTryStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addTypeArgumentList(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addTypeLiteral(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addTypeParameter(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addTypeParameterList(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addVariableDeclaration(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addVariableDeclarationList(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addVariableDeclarationStatement(
+    AbstractAnalysisRule rule,
+    AstVisitor visitor,
+  );
+
+  void addWhenClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addWhileStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addWildcardPattern(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addWithClause(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void addYieldStatement(AbstractAnalysisRule rule, AstVisitor visitor);
+
+  void afterLibrary(AbstractAnalysisRule rule, void Function() callback);
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart b/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart
index eeaa6d5..f412c43 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state_filter.dart
@@ -2,8 +2,8 @@
 // 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/pubspec.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/src/workspace/pub.dart';
 
 abstract class FileStateFilter {
@@ -141,7 +141,7 @@
   }
 }
 
-extension on PSDependencyList? {
+extension on PubspecDependencyList? {
   List<String> get names {
     var self = this;
     if (self == null) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 23b0741..9b9fa86 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -402,7 +402,9 @@
     var allUnits = analysesToContextUnits.values.toList();
     definingContextUnit ??= allUnits.first;
 
-    var nodeRegistry = RuleVisitorRegistry(enableTiming: _enableLintRuleTiming);
+    var nodeRegistry = RuleVisitorRegistryImpl(
+      enableTiming: _enableLintRuleTiming,
+    );
     var context = RuleContextWithResolvedResults(
       allUnits,
       definingContextUnit,
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 0111c4a..f9c24ca 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -2,22 +2,17 @@
 // 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/analysis_rule.dart';
 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';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.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/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/lint/linter_visitor.dart' show RuleVisitorRegistry;
-import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/workspace/workspace.dart';
 
+export 'package:analyzer/analysis_rule/analysis_rule.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;
@@ -37,266 +32,6 @@
 /// one [DiagnosticCode].
 typedef LintRule = AnalysisRule;
 
-/// 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 lints and warnings.
-  /// NOTE: this is set by the framework before any node processors start
-  /// visiting nodes.
-  late ErrorReporter _reporter;
-
-  /// Short description suitable for display in console output.
-  final String description;
-
-  /// The rule name.
-  final String name;
-
-  /// The state of this analysis rule, optionally indicating the "version" that
-  /// this state started applying to this rule.
-  final RuleState state;
-
-  AbstractAnalysisRule({
-    required this.name,
-    required this.description,
-    this.state = const RuleState.stable(),
-  });
-
-  /// Indicates whether this analysis rule can work with just the parsed
-  /// information or if it requires a resolved unit.
-  bool get canUseParsedResult => false;
-
-  /// The diagnostic codes associated with this analysis rule.
-  List<DiagnosticCode> get diagnosticCodes;
-
-  /// A list of incompatible rule ids.
-  List<String> get incompatibleRules => const [];
-
-  /// A visitor that visits a [Pubspec] to perform analysis.
-  ///
-  /// Diagnostics are reported via this [AbstractAnalysisRule]'s error
-  /// [reporter].
-  PubspecVisitor? get pubspecVisitor => null;
-
-  /// Sets the [ErrorReporter] for the [CompilationUnit] currently being
-  /// visited.
-  set reporter(ErrorReporter value) => _reporter = value;
-
-  /// Registers node processors in the given [registry].
-  ///
-  /// The node processors may use the provided [context] to access information
-  /// that is not available from the AST nodes or their associated elements.
-  void registerNodeProcessors(
-    RuleVisitorRegistry registry,
-    RuleContext context,
-  ) {}
-
-  void _reportAtNode(
-    AstNode? node, {
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-    required DiagnosticCode diagnosticCode,
-  }) {
-    if (node != null && !node.isSynthetic) {
-      _reporter.atNode(
-        node,
-        diagnosticCode,
-        arguments: arguments,
-        contextMessages: contextMessages,
-      );
-    }
-  }
-
-  void _reportAtOffset(
-    int offset,
-    int length, {
-    required DiagnosticCode diagnosticCode,
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-  }) {
-    _reporter.atOffset(
-      offset: offset,
-      length: length,
-      diagnosticCode: diagnosticCode,
-      arguments: arguments,
-      contextMessages: contextMessages,
-    );
-  }
-
-  void _reportAtPubNode(
-    PSNode node, {
-    List<Object> arguments = const [],
-    List<DiagnosticMessage> contextMessages = const [],
-    required DiagnosticCode diagnosticCode,
-  }) {
-    // Cache diagnostic and location info for creating `AnalysisErrorInfo`s.
-    var diagnostic = Diagnostic.tmp(
-      source: node.source,
-      offset: node.span.start.offset,
-      length: node.span.length,
-      errorCode: diagnosticCode,
-      arguments: arguments,
-      contextMessages: contextMessages,
-    );
-    _reporter.reportError(diagnostic);
-  }
-
-  void _reportAtToken(
-    Token token, {
-    required DiagnosticCode diagnosticCode,
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-  }) {
-    if (!token.isSynthetic) {
-      _reporter.atToken(
-        token,
-        diagnosticCode,
-        arguments: arguments,
-        contextMessages: contextMessages,
-      );
-    }
-  }
-}
-
-/// Describes an [AbstractAnalysisRule] which reports exactly one type of
-/// diagnostic (one [DiagnosticCode]).
-abstract class AnalysisRule extends AbstractAnalysisRule {
-  AnalysisRule({required super.name, required super.description, super.state});
-
-  /// The code to report for a violation.
-  DiagnosticCode get diagnosticCode;
-
-  @override
-  List<DiagnosticCode> get diagnosticCodes => [diagnosticCode];
-
-  /// Reports a diagnostic at [node] with message [arguments] and
-  /// [contextMessages].
-  void reportAtNode(
-    AstNode? node, {
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-  }) => _reportAtNode(
-    node,
-    diagnosticCode: diagnosticCode,
-    arguments: arguments,
-    contextMessages: contextMessages,
-  );
-
-  /// Reports a diagnostic at [offset], with [length], with message [arguments]
-  /// and [contextMessages].
-  void reportAtOffset(
-    int offset,
-    int length, {
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-  }) => _reportAtOffset(
-    offset,
-    length,
-    diagnosticCode: diagnosticCode,
-    arguments: arguments,
-    contextMessages: contextMessages,
-  );
-
-  /// Reports a diagnostic at Pubspec [node], with message [arguments] and
-  /// [contextMessages].
-  void reportAtPubNode(
-    PSNode node, {
-    List<Object> arguments = const [],
-    List<DiagnosticMessage> contextMessages = const [],
-  }) => _reportAtPubNode(
-    node,
-    diagnosticCode: diagnosticCode,
-    arguments: arguments,
-    contextMessages: contextMessages,
-  );
-
-  /// Reports a diagnostic at [token], with message [arguments] and
-  /// [contextMessages].
-  void reportAtToken(
-    Token token, {
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-  }) => _reportAtToken(
-    token,
-    diagnosticCode: diagnosticCode,
-    arguments: arguments,
-    contextMessages: contextMessages,
-  );
-}
-
-/// Describes an [AbstractAnalysisRule] which reports diagnostics using multiple
-/// [DiagnosticCode]s).
-abstract class MultiAnalysisRule extends AbstractAnalysisRule {
-  MultiAnalysisRule({
-    required super.name,
-    required super.description,
-    super.state,
-  });
-
-  /// Reports [diagnosticCode] at [node] with message [arguments] and
-  /// [contextMessages].
-  void reportAtNode(
-    AstNode? node, {
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-    required DiagnosticCode diagnosticCode,
-  }) => _reportAtNode(
-    node,
-    diagnosticCode: diagnosticCode,
-    arguments: arguments,
-    contextMessages: contextMessages,
-  );
-
-  /// Reports [diagnosticCode] at [offset], with [length], with message [arguments]
-  /// and [contextMessages].
-  void reportAtOffset(
-    int offset,
-    int length, {
-    required DiagnosticCode diagnosticCode,
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-  }) => _reportAtOffset(
-    offset,
-    length,
-    diagnosticCode: diagnosticCode,
-    arguments: arguments,
-    contextMessages: contextMessages,
-  );
-
-  /// Reports [diagnosticCode] at Pubspec [node], with message [arguments] and
-  /// [contextMessages].
-  void reportAtPubNode(
-    PSNode node, {
-    required DiagnosticCode diagnosticCode,
-    List<Object> arguments = const [],
-    List<DiagnosticMessage> contextMessages = const [],
-  }) {
-    // Cache error and location info for creating `AnalysisErrorInfo`s.
-    var error = Diagnostic.tmp(
-      source: node.source,
-      offset: node.span.start.offset,
-      length: node.span.length,
-      errorCode: diagnosticCode,
-      arguments: arguments,
-      contextMessages: contextMessages,
-    );
-    _reporter.reportError(error);
-  }
-
-  /// Reports [diagnosticCode] at [token], with message [arguments] and
-  /// [contextMessages].
-  void reportAtToken(
-    Token token, {
-    required DiagnosticCode diagnosticCode,
-    List<Object> arguments = const [],
-    List<DiagnosticMessage>? contextMessages,
-  }) => _reportAtToken(
-    token,
-    diagnosticCode: diagnosticCode,
-    arguments: arguments,
-    contextMessages: contextMessages,
-  );
-}
-
 /// A [RuleContext] for a library, parsed into [ParsedUnitResult]s.
 ///
 /// This is available for analysis rules that can operate on parsed,
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
index fb94c8f..4d55088 100644
--- a/pkg/analyzer/lib/src/lint/linter_visitor.dart
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.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_visitor_registry.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -13,7 +14,7 @@
 
 /// The AST visitor that runs handlers for nodes from the [_registry].
 class AnalysisRuleVisitor implements AstVisitor<void> {
-  final RuleVisitorRegistry _registry;
+  final RuleVisitorRegistryImpl _registry;
 
   /// Whether exceptions should be propagated (by rethrowing them).
   final bool _shouldPropagateExceptions;
@@ -1144,8 +1145,7 @@
   }
 }
 
-/// The container to register visitors for separate AST node types.
-class RuleVisitorRegistry {
+class RuleVisitorRegistryImpl implements RuleVisitorRegistry {
   final bool _enableTiming;
   final List<_AfterLibrarySubscription> _afterLibrary = [];
   final List<_Subscription<AdjacentStrings>> _forAdjacentStrings = [];
@@ -1363,33 +1363,40 @@
   final List<_Subscription<WithClause>> _forWithClause = [];
   final List<_Subscription<YieldStatement>> _forYieldStatement = [];
 
-  RuleVisitorRegistry({required bool enableTiming})
+  RuleVisitorRegistryImpl({required bool enableTiming})
     : _enableTiming = enableTiming;
 
+  @override
   void addAdjacentStrings(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAdjacentStrings.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAnnotation(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAnnotation.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addArgumentList(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forArgumentList.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAsExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAsExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAssertInitializer(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAssertInitializer.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAssertStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAssertStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAssignedVariablePattern(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1399,96 +1406,119 @@
     );
   }
 
+  @override
   void addAssignmentExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAssignmentExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAugmentedExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAugmentedExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAugmentedInvocation(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAugmentedInvocation.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addAwaitExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forAwaitExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addBinaryExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forBinaryExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addBlock(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forBlock.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addBlockFunctionBody(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forBlockFunctionBody.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addBooleanLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forBooleanLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addBreakStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forBreakStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addCascadeExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forCascadeExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addCaseClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forCaseClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addCastPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forCastPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addCatchClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forCatchClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addCatchClauseParameter(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forCatchClauseParameter.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addClassDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forClassDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addClassTypeAlias(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forClassTypeAlias.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addComment(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forComment.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addCommentReference(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forCommentReference.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addCompilationUnit(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forCompilationUnit.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addConditionalExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forConditionalExpression.add(
       _Subscription(rule, visitor, _getTimer(rule)),
     );
   }
 
+  @override
   void addConfiguration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forConfiguration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addConstantPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forConstantPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addConstructorDeclaration(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1498,6 +1528,7 @@
     );
   }
 
+  @override
   void addConstructorFieldInitializer(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1507,26 +1538,32 @@
     );
   }
 
+  @override
   void addConstructorName(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forConstructorName.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addConstructorReference(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forConstructorReference.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addConstructorSelector(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forConstructorSelector.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addContinueStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forContinueStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addDeclaredIdentifier(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forDeclaredIdentifier.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addDeclaredVariablePattern(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1536,6 +1573,7 @@
     );
   }
 
+  @override
   void addDefaultFormalParameter(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1545,10 +1583,12 @@
     );
   }
 
+  @override
   void addDoStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forDoStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addDotShorthandConstructorInvocation(
     AnalysisRule rule,
     AstVisitor visitor,
@@ -1558,6 +1598,7 @@
     );
   }
 
+  @override
   void addDotShorthandInvocation(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1567,6 +1608,7 @@
     );
   }
 
+  @override
   void addDotShorthandPropertyAccess(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1576,28 +1618,34 @@
     );
   }
 
+  @override
   void addDottedName(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forDottedName.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addDoubleLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forDoubleLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addEmptyFunctionBody(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forEmptyFunctionBody.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addEmptyStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forEmptyStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addEnumConstantArguments(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forEnumConstantArguments.add(
       _Subscription(rule, visitor, _getTimer(rule)),
     );
   }
 
+  @override
   void addEnumConstantDeclaration(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1607,14 +1655,17 @@
     );
   }
 
+  @override
   void addEnumDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forEnumDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addExportDirective(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forExportDirective.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addExpressionFunctionBody(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1624,26 +1675,32 @@
     );
   }
 
+  @override
   void addExpressionStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forExpressionStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addExtendsClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forExtendsClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addExtensionDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forExtensionDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addExtensionOnClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forExtensionOnClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addExtensionOverride(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forExtensionOverride.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addExtensionTypeDeclaration(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1653,14 +1710,17 @@
     );
   }
 
+  @override
   void addFieldDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forFieldDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addFieldFormalParameter(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forFieldFormalParameter.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addForEachPartsWithDeclaration(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1670,6 +1730,7 @@
     );
   }
 
+  @override
   void addForEachPartsWithIdentifier(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1679,6 +1740,7 @@
     );
   }
 
+  @override
   void addForEachPartsWithPattern(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1688,14 +1750,17 @@
     );
   }
 
+  @override
   void addForElement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forForElement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addFormalParameterList(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forFormalParameterList.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addForPartsWithDeclarations(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1705,6 +1770,7 @@
     );
   }
 
+  @override
   void addForPartsWithExpression(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1714,18 +1780,22 @@
     );
   }
 
+  @override
   void addForPartsWithPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forForPartsWithPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addForStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forForStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addFunctionDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forFunctionDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addFunctionDeclarationStatement(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1735,10 +1805,12 @@
     );
   }
 
+  @override
   void addFunctionExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forFunctionExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addFunctionExpressionInvocation(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1748,14 +1820,17 @@
     );
   }
 
+  @override
   void addFunctionReference(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forFunctionReference.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addFunctionTypeAlias(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forFunctionTypeAlias.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addFunctionTypedFormalParameter(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1765,54 +1840,66 @@
     );
   }
 
+  @override
   void addGenericFunctionType(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forGenericFunctionType.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addGenericTypeAlias(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forGenericTypeAlias.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addGuardedPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forGuardedPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addHideCombinator(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forHideCombinator.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addIfElement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forIfElement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addIfStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forIfStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addImplementsClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forImplementsClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addImplicitCallReference(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forImplicitCallReference.add(
       _Subscription(rule, visitor, _getTimer(rule)),
     );
   }
 
+  @override
   void addImportDirective(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forImportDirective.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addImportPrefixReference(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forImportPrefixReference.add(
       _Subscription(rule, visitor, _getTimer(rule)),
     );
   }
 
+  @override
   void addIndexExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forIndexExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addInstanceCreationExpression(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1822,10 +1909,12 @@
     );
   }
 
+  @override
   void addIntegerLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forIntegerLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addInterpolationExpression(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1835,106 +1924,132 @@
     );
   }
 
+  @override
   void addInterpolationString(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forInterpolationString.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addIsExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forIsExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addLabel(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forLabel.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addLabeledStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forLabeledStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addLibraryDirective(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forLibraryDirective.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addLibraryIdentifier(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forLibraryIdentifier.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addListLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forListLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addListPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forListPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addLogicalAndPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forLogicalAndPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addLogicalOrPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forLogicalOrPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addMapLiteralEntry(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forMapLiteralEntry.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addMapPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forMapPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addMapPatternEntry(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forMapPatternEntry.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addMethodDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forMethodDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addMethodInvocation(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forMethodInvocation.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addMixinDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forMixinDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addMixinOnClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forMixinOnClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addNamedExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forNamedExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addNamedType(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forNamedType.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addNativeClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forNativeClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addNativeFunctionBody(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forNativeFunctionBody.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addNullAssertPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forNullAssertPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addNullCheckPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forNullCheckPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addNullLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forNullLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addObjectPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forObjectPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addParenthesizedExpression(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1944,30 +2059,37 @@
     );
   }
 
+  @override
   void addParenthesizedPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forParenthesizedPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPartDirective(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPartDirective.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPartOfDirective(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPartOfDirective.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPatternAssignment(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPatternAssignment.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPatternField(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPatternField.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPatternFieldName(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPatternFieldName.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPatternVariableDeclaration(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -1977,6 +2099,7 @@
     );
   }
 
+  @override
   void addPatternVariableDeclarationStatement(
     AnalysisRule rule,
     AstVisitor visitor,
@@ -1986,34 +2109,42 @@
     );
   }
 
+  @override
   void addPostfixExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPostfixExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPrefixedIdentifier(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPrefixedIdentifier.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPrefixExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPrefixExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addPropertyAccess(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forPropertyAccess.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addRecordLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forRecordLiterals.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addRecordPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forRecordPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addRecordTypeAnnotation(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forRecordTypeAnnotation.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addRedirectingConstructorInvocation(
     AnalysisRule rule,
     AstVisitor visitor,
@@ -2023,10 +2154,12 @@
     );
   }
 
+  @override
   void addRelationalPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forRelationalPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addRepresentationConstructorName(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -2036,6 +2169,7 @@
     );
   }
 
+  @override
   void addRepresentationDeclaration(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -2045,52 +2179,64 @@
     );
   }
 
+  @override
   void addRestPatternElement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forRestPatternElement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addRethrowExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forRethrowExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addReturnStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forReturnStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addScriptTag(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forScriptTag.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSetOrMapLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSetOrMapLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addShowCombinator(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forShowCombinator.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSimpleFormalParameter(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSimpleFormalParameter.add(
       _Subscription(rule, visitor, _getTimer(rule)),
     );
   }
 
+  @override
   void addSimpleIdentifier(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSimpleIdentifier.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSimpleStringLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSimpleStringLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSpreadElement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSpreadElement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addStringInterpolation(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forStringInterpolation.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSuperConstructorInvocation(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -2100,50 +2246,62 @@
     );
   }
 
+  @override
   void addSuperExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSuperExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSuperFormalParameter(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSuperFormalParameter.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSwitchCase(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSwitchCase.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSwitchDefault(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSwitchDefault.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSwitchExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSwitchExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSwitchExpressionCase(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSwitchExpressionCase.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSwitchPatternCase(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSwitchPatternCase.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSwitchStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSwitchStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addSymbolLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forSymbolLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addThisExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forThisExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addThrowExpression(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forThrowExpression.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addTopLevelVariableDeclaration(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -2153,30 +2311,37 @@
     );
   }
 
+  @override
   void addTryStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forTryStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addTypeArgumentList(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forTypeArgumentList.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addTypeLiteral(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forTypeLiteral.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addTypeParameter(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forTypeParameter.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addTypeParameterList(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forTypeParameterList.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addVariableDeclaration(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forVariableDeclaration.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addVariableDeclarationList(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -2186,6 +2351,7 @@
     );
   }
 
+  @override
   void addVariableDeclarationStatement(
     AbstractAnalysisRule rule,
     AstVisitor visitor,
@@ -2195,26 +2361,32 @@
     );
   }
 
+  @override
   void addWhenClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forWhenClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addWhileStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forWhileStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addWildcardPattern(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forWildcardPattern.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addWithClause(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forWithClause.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void addYieldStatement(AbstractAnalysisRule rule, AstVisitor visitor) {
     _forYieldStatement.add(_Subscription(rule, visitor, _getTimer(rule)));
   }
 
+  @override
   void afterLibrary(AbstractAnalysisRule rule, void Function() callback) {
     _afterLibrary.add(
       _AfterLibrarySubscription(rule, callback, _getTimer(rule)),
diff --git a/pkg/analyzer/lib/src/lint/pub.dart b/pkg/analyzer/lib/src/lint/pub.dart
index a4f2905..e613cc1 100644
--- a/pkg/analyzer/lib/src/lint/pub.dart
+++ b/pkg/analyzer/lib/src/lint/pub.dart
@@ -2,8 +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 'dart:collection';
-
+import 'package:analyzer/analysis_rule/pubspec.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/source/file_source.dart';
@@ -11,12 +10,12 @@
 import 'package:source_span/source_span.dart';
 import 'package:yaml/yaml.dart';
 
-PSEntry? _findEntry(
+PubspecEntry? _findEntry(
   YamlMap map,
   String key,
   ResourceProvider? resourceProvider,
 ) {
-  PSEntry? entry;
+  PubspecEntry? entry;
   map.nodes.forEach((k, v) {
     if (k is YamlScalar && key == k.toString()) {
       entry = _processScalar(k, v, resourceProvider);
@@ -25,7 +24,7 @@
   return entry;
 }
 
-PSDependencyList? _processDependencies(
+PubspecDependencyList? _processDependencies(
   YamlScalar key,
   YamlNode value,
   ResourceProvider? resourceProvider,
@@ -34,14 +33,16 @@
     return null;
   }
 
-  _PSDependencyList deps = _PSDependencyList(_PSNode(key, resourceProvider));
+  _PubspecDependencyList deps = _PubspecDependencyList(
+    PubspecNodeImpl(key, resourceProvider),
+  );
   value.nodes.forEach((k, v) {
-    if (k is YamlScalar) deps.add(_PSDependency(k, v, resourceProvider));
+    if (k is YamlScalar) deps.add(_PubspecDependency(k, v, resourceProvider));
   });
   return deps;
 }
 
-PSEnvironment? _processEnvironment(
+PubspecEnvironment? _processEnvironment(
   YamlScalar key,
   YamlNode value,
   ResourceProvider? resourceProvider,
@@ -50,23 +51,23 @@
     return null;
   }
 
-  return _PSEnvironment(
-    _PSNode(key, resourceProvider),
+  return _PubspecEnvironment(
+    PubspecNodeImpl(key, resourceProvider),
     flutter: _findEntry(value, 'flutter', resourceProvider),
     sdk: _findEntry(value, 'sdk', resourceProvider),
   );
 }
 
-PSGitRepo? _processGitRepo(
+PubspecGitRepo? _processGitRepo(
   YamlScalar key,
   YamlNode value,
   ResourceProvider? resourceProvider,
 ) {
   if (value is YamlScalar) {
-    var token = _PSNode(key, resourceProvider);
-    return _PSGitRepo(
+    var token = PubspecNodeImpl(key, resourceProvider);
+    return _PubspecGitRepo(
       token,
-      url: PSEntry(token, _PSNode(value, resourceProvider)),
+      url: PubspecEntry(token, PubspecNodeImpl(value, resourceProvider)),
     );
   }
   if (value is! YamlMap) {
@@ -75,14 +76,14 @@
 
   // url: git://github.com/munificent/kittens.git
   // ref: some-branch
-  return _PSGitRepo(
-    _PSNode(key, resourceProvider),
+  return _PubspecGitRepo(
+    PubspecNodeImpl(key, resourceProvider),
     ref: _findEntry(value, 'ref', resourceProvider),
     url: _findEntry(value, 'url', resourceProvider),
   );
 }
 
-PSHost? _processHost(
+PubspecHost? _processHost(
   YamlScalar key,
   YamlNode value,
   ResourceProvider? resourceProvider,
@@ -92,8 +93,8 @@
     //   mypkg:
     //     hosted:  https://some-pub-server.com
     //     version: ^1.2.3
-    return _PSHost(
-      _PSNode(key, resourceProvider),
+    return _PubspecHost(
+      PubspecNodeImpl(key, resourceProvider),
       isShortForm: true,
       url: _processScalar(key, value, resourceProvider),
     );
@@ -101,8 +102,8 @@
   if (value is YamlMap) {
     // name: transmogrify
     // url: http://your-package-server.com
-    return _PSHost(
-      _PSNode(key, resourceProvider),
+    return _PubspecHost(
+      PubspecNodeImpl(key, resourceProvider),
       isShortForm: false,
       name: _findEntry(value, 'name', resourceProvider),
       url: _findEntry(value, 'url', resourceProvider),
@@ -111,7 +112,7 @@
   return null;
 }
 
-PSEntry? _processScalar(
+PubspecEntry? _processScalar(
   YamlScalar key,
   YamlNode value,
   ResourceProvider? resourceProvider,
@@ -120,13 +121,13 @@
     return null;
     //WARN?
   }
-  return PSEntry(
-    _PSNode(key, resourceProvider),
-    _PSNode(value, resourceProvider),
+  return PubspecEntry(
+    PubspecNodeImpl(key, resourceProvider),
+    PubspecNodeImpl(value, resourceProvider),
   );
 }
 
-PSNodeList? _processScalarList(
+PubspecNodeList? _processScalarList(
   YamlScalar key,
   YamlNode value,
   ResourceProvider? resourceProvider,
@@ -134,169 +135,14 @@
   if (value is! YamlList) {
     return null;
   }
-  return _PSNodeList(
-    _PSNode(key, resourceProvider),
+  return _PubspecNodeList(
+    PubspecNodeImpl(key, resourceProvider),
     value.nodes.whereType<YamlScalar>().map(
-      (n) => _PSNode(n, resourceProvider),
+      (n) => PubspecNodeImpl(n, resourceProvider),
     ),
   );
 }
 
-/// Representation of a key/value pair which maps a package name to a
-/// _package description_.
-///
-/// **Example** of a path-dependency:
-/// ```yaml
-/// dependencies:
-///   <name>:
-///     version: <version>
-///     path: <path>
-/// ```
-abstract class PSDependency {
-  PSGitRepo? get git;
-
-  PSHost? get host;
-
-  PSNode? get name;
-
-  PSEntry? get path;
-
-  PSEntry? get version;
-}
-
-/// Representation of the map from package name to _package description_ used
-/// under `dependencies`, `dev_dependencies` and `dependency_overrides`.
-abstract class PSDependencyList with IterableMixin<PSDependency> {}
-
-class PSEntry {
-  final PSNode? key;
-  final PSNode value;
-
-  PSEntry(this.key, this.value);
-
-  @override
-  String toString() => '${key != null ? '$key: ' : ''}$value';
-}
-
-/// Representation of an `environment` section in a pubspec file.
-///
-/// **Example** of an environment:
-/// ```yaml
-/// environment:
-///   sdk: '>=2.12.0 <4.0.0'
-///   flutter: ^3.3.10
-/// ```
-abstract class PSEnvironment {
-  PSEntry? get flutter;
-
-  PSEntry? get sdk;
-
-  PSNode get token;
-}
-
-/// Representation of git-dependency section in a pubspec file.
-///
-/// **Example** of a git-dependency:
-/// ```yaml
-/// dependencies:
-///   foo:
-///     git: # <-- this is the [token] property
-///       url: https://github.com/example/example
-///       ref: main # ref is optional
-/// ```
-///
-/// This may also be written in the form:
-/// ```yaml
-/// dependencies:
-///   foo:
-///     git:       https://github.com/example/example
-///     # ^-token  ^--url
-///     # In this case [ref] is `null`.
-/// ```
-abstract class PSGitRepo {
-  /// [PSEntry] for `ref: main` where [PSEntry.key] is `ref` and [PSEntry.value]
-  /// is `main`.
-  PSEntry? get ref;
-
-  /// The `'git'` from the `pubspec.yaml`, this is the key that indicates this
-  /// is a git-dependency.
-  PSNode get token;
-
-  /// [PSEntry] for `url: https://...` or `git: https://`, where [PSEntry.key]
-  /// is either `url` or `git`, and [PSEntry.key] is the URL.
-  ///
-  /// If the git-dependency is given in the form:
-  /// ```yaml
-  /// dependencies:
-  ///   foo:
-  ///     git:       https://github.com/example/example
-  /// ```
-  /// Then [token] and `url.key` will be the same object.
-  PSEntry? get url;
-}
-
-abstract class PSHost {
-  /// True, if _short-form_ for writing hosted-dependencies was used.
-  ///
-  /// **Example** of a hosted-dependency written in short-form:
-  /// ```yaml
-  /// dependencies:
-  ///   foo:
-  ///     hosted: https://some-pub-server.com
-  ///     version: ^1.2.3
-  /// ```
-  ///
-  /// The _long-form_ for writing the dependency given above is:
-  /// ```yaml
-  /// dependencies:
-  ///   foo:
-  ///     hosted:
-  ///       url: https://some-pub-server.com
-  ///       name: foo
-  ///     version: ^1.2.3
-  /// ```
-  ///
-  /// The short-form was added in Dart 2.15.0 because:
-  ///  * The `name` property just specifies the package name, which can be
-  ///    inferred from the context. So it is unnecessary to write it.
-  ///  * The nested object and `url` key becomes unnecessary when the `name`
-  ///    property is removed.
-  bool get isShortForm;
-
-  PSEntry? get name;
-
-  PSNode get token;
-
-  PSEntry? get url;
-}
-
-/// Representation of a leaf-node in a pubspec file.
-abstract class PSNode {
-  Source get source;
-
-  SourceSpan get span;
-
-  /// String value of the node, or `null` if value in the pubspec file is `null`
-  /// or omitted.
-  ///
-  /// **Example**
-  /// ```
-  /// name: foo
-  /// version:
-  /// ```
-  /// In the example above the [PSNode] for `foo` will have [text] "foo", and
-  /// the [PSNode] for `version` will have not have [text] as `null`, as empty
-  /// value or `"null"` is the same in YAML.
-  String? get text;
-}
-
-abstract class PSNodeList with IterableMixin<PSNode> {
-  @override
-  Iterator<PSNode> get iterator;
-
-  PSNode get token;
-}
-
 abstract class Pubspec {
   factory Pubspec.parse(
     String pubspec, {
@@ -318,240 +164,36 @@
     return _Pubspec.parse(yaml, resourceProvider: resourceProvider);
   }
 
-  PSEntry? get author;
+  PubspecEntry? get author;
 
-  PSNodeList? get authors;
+  PubspecNodeList? get authors;
 
-  PSDependencyList? get dependencies;
+  PubspecDependencyList? get dependencies;
 
-  PSDependencyList? get dependencyOverrides;
+  PubspecDependencyList? get dependencyOverrides;
 
-  PSEntry? get description;
+  PubspecEntry? get description;
 
-  PSDependencyList? get devDependencies;
+  PubspecDependencyList? get devDependencies;
 
-  PSEntry? get documentation;
+  PubspecEntry? get documentation;
 
-  PSEnvironment? get environment;
+  PubspecEnvironment? get environment;
 
-  PSEntry? get homepage;
+  PubspecEntry? get homepage;
 
-  PSEntry? get issueTracker;
+  PubspecEntry? get issueTracker;
 
-  PSEntry? get name;
+  PubspecEntry? get name;
 
-  PSEntry? get repository;
+  PubspecEntry? get repository;
 
-  PSEntry? get version;
+  PubspecEntry? get version;
 
   void accept(PubspecVisitor visitor);
 }
 
-abstract class PubspecVisitor<T> {
-  T? visitPackageAuthor(PSEntry author) => null;
-
-  T? visitPackageAuthors(PSNodeList authors) => null;
-
-  T? visitPackageDependencies(PSDependencyList dependencies) => null;
-
-  T? visitPackageDependency(PSDependency dependency) => null;
-
-  T? visitPackageDependencyOverride(PSDependency dependency) => null;
-
-  T? visitPackageDependencyOverrides(PSDependencyList dependencies) => null;
-
-  T? visitPackageDescription(PSEntry description) => null;
-
-  T? visitPackageDevDependencies(PSDependencyList dependencies) => null;
-
-  T? visitPackageDevDependency(PSDependency dependency) => null;
-
-  T? visitPackageDocumentation(PSEntry documentation) => null;
-
-  T? visitPackageEnvironment(PSEnvironment environment) => null;
-
-  T? visitPackageHomepage(PSEntry homepage) => null;
-
-  T? visitPackageIssueTracker(PSEntry issueTracker) => null;
-
-  T? visitPackageName(PSEntry name) => null;
-
-  T? visitPackageRepository(PSEntry repository) => null;
-
-  T? visitPackageVersion(PSEntry version) => null;
-}
-
-class _PSDependency extends PSDependency {
-  @override
-  final PSNode? name;
-
-  @override
-  final PSEntry? path;
-
-  @override
-  final PSEntry? version;
-
-  @override
-  final PSHost? host;
-
-  @override
-  final PSGitRepo? git;
-
-  factory _PSDependency(
-    YamlScalar key,
-    YamlNode value,
-    ResourceProvider? resourceProvider,
-  ) {
-    var name = _PSNode(key, resourceProvider);
-    PSEntry? path;
-    PSEntry? version;
-    PSHost? host;
-    PSGitRepo? git;
-
-    if (value is YamlScalar) {
-      // Simple version constraint.
-      version = PSEntry(null, _PSNode(value, resourceProvider));
-    } else if (value is YamlMap) {
-      value.nodes.forEach((k, v) {
-        if (k is! YamlScalar) {
-          return;
-        }
-        YamlScalar key = k;
-        switch (key.toString()) {
-          case 'path':
-            path = _processScalar(key, v, resourceProvider);
-          case 'version':
-            version = _processScalar(key, v, resourceProvider);
-          case 'hosted':
-            host = _processHost(key, v, resourceProvider);
-          case 'git':
-            git = _processGitRepo(key, v, resourceProvider);
-        }
-      });
-    }
-
-    return _PSDependency._(
-      name: name,
-      path: path,
-      version: version,
-      host: host,
-      git: git,
-    );
-  }
-
-  _PSDependency._({
-    required this.name,
-    required this.path,
-    required this.version,
-    required this.host,
-    required this.git,
-  });
-
-  @override
-  String toString() {
-    var sb = StringBuffer();
-    if (name != null) {
-      sb.write('$name:');
-    }
-    var versionInfo = '';
-    if (version != null) {
-      if (version!.key == null) {
-        versionInfo = ' $version';
-      } else {
-        versionInfo = '\n    $version';
-      }
-    }
-    sb.writeln(versionInfo);
-    if (host != null) {
-      sb.writeln(host);
-    }
-    if (git != null) {
-      sb.writeln(git);
-    }
-    return sb.toString();
-  }
-}
-
-class _PSDependencyList extends PSDependencyList {
-  final dependencies = <PSDependency>[];
-  final PSNode token;
-
-  _PSDependencyList(this.token);
-
-  @override
-  Iterator<PSDependency> get iterator => dependencies.iterator;
-
-  void add(PSDependency? dependency) {
-    if (dependency != null) {
-      dependencies.add(dependency);
-    }
-  }
-
-  @override
-  String toString() => '$token\n${dependencies.join('  ')}';
-}
-
-class _PSEnvironment implements PSEnvironment {
-  @override
-  final PSNode token;
-
-  @override
-  final PSEntry? flutter;
-
-  @override
-  final PSEntry? sdk;
-
-  _PSEnvironment(this.token, {required this.flutter, required this.sdk});
-
-  @override
-  String toString() => '''
-    $token:
-      $sdk
-      $flutter''';
-}
-
-class _PSGitRepo implements PSGitRepo {
-  @override
-  final PSNode token;
-
-  @override
-  final PSEntry? ref;
-
-  @override
-  final PSEntry? url;
-
-  _PSGitRepo(this.token, {this.ref, required this.url});
-
-  @override
-  String toString() => '''
-    $token:
-      $url
-      $ref''';
-}
-
-class _PSHost implements PSHost {
-  @override
-  final bool isShortForm;
-
-  @override
-  final PSEntry? name;
-
-  @override
-  final PSNode token;
-
-  @override
-  final PSEntry? url;
-
-  _PSHost(this.token, {required this.isShortForm, this.name, this.url});
-
-  @override
-  String toString() => '''
-    $token:
-      $name
-      $url''';
-}
-
-class _PSNode implements PSNode {
+class PubspecNodeImpl implements PubspecNode {
   @override
   final String? text;
 
@@ -560,12 +202,12 @@
 
   final ResourceProvider _resourceProvider;
 
-  _PSNode(YamlScalar node, ResourceProvider? resourceProvider)
+  PubspecNodeImpl(YamlScalar node, ResourceProvider? resourceProvider)
     : text = node.value?.toString(),
       span = node.span,
       _resourceProvider = resourceProvider ?? PhysicalResourceProvider.INSTANCE;
 
-  @override
+  /// The [Source] information of the pubspec file in which this node is located.
   Source get source {
     var uri = span.sourceUrl!;
     var filePath = _resourceProvider.pathContext.fromUri(uri);
@@ -577,81 +219,64 @@
   String toString() => '$text';
 }
 
-class _PSNodeList extends PSNodeList {
-  @override
-  final PSNode token;
-
-  final Iterable<PSNode> nodes;
-
-  _PSNodeList(this.token, this.nodes);
-
-  @override
-  Iterator<PSNode> get iterator => nodes.iterator;
-
-  @override
-  String toString() => '''
-$token:
-  - ${nodes.join('\n  - ')}''';
-}
-
 class _Pubspec implements Pubspec {
   @override
-  final PSEntry? author;
+  final PubspecEntry? author;
 
   @override
-  final PSNodeList? authors;
+  final PubspecNodeList? authors;
 
   @override
-  final PSEntry? description;
+  final PubspecEntry? description;
 
   @override
-  final PSEntry? documentation;
+  final PubspecEntry? documentation;
 
   @override
-  final PSEnvironment? environment;
+  final PubspecEnvironment? environment;
 
   @override
-  final PSEntry? homepage;
+  final PubspecEntry? homepage;
 
   @override
-  final PSEntry? issueTracker;
+  final PubspecEntry? issueTracker;
 
   @override
-  final PSEntry? name;
+  final PubspecEntry? name;
 
   @override
-  final PSEntry? repository;
+  final PubspecEntry? repository;
 
   @override
-  final PSEntry? version;
+  final PubspecEntry? version;
 
   @override
-  final PSDependencyList? dependencies;
+  final PubspecDependencyList? dependencies;
 
   @override
-  final PSDependencyList? devDependencies;
+  final PubspecDependencyList? devDependencies;
 
   @override
-  final PSDependencyList? dependencyOverrides;
+  final PubspecDependencyList? dependencyOverrides;
 
   factory _Pubspec.parse(YamlNode yaml, {ResourceProvider? resourceProvider}) {
     if (yaml is! YamlMap) {
       return _Pubspec._();
     }
 
-    PSEntry? author;
-    PSNodeList? authors;
-    PSEntry? description;
-    PSEntry? documentation;
-    PSEnvironment? environment;
-    PSEntry? homepage;
-    PSEntry? issueTracker;
-    PSEntry? name;
-    PSEntry? repository;
-    PSEntry? version;
-    PSDependencyList? dependencies;
-    PSDependencyList? devDependencies;
-    PSDependencyList? dependencyOverrides;
+    PubspecEntry? author;
+    PubspecNodeList? authors;
+    PubspecEntry? description;
+    PubspecEntry? documentation;
+    PubspecEnvironment? environment;
+    PubspecEntry? homepage;
+    PubspecEntry? issueTracker;
+    PubspecEntry? name;
+    PubspecEntry? repository;
+    PubspecEntry? version;
+    PubspecDependencyList? dependencies;
+    PubspecDependencyList? devDependencies;
+    PubspecDependencyList? dependencyOverrides;
 
     yaml.nodes.forEach((k, v) {
       if (k is! YamlScalar) {
@@ -785,6 +410,193 @@
   }
 }
 
+class _PubspecDependency extends PubspecDependency {
+  @override
+  final PubspecNode? name;
+
+  @override
+  final PubspecEntry? path;
+
+  @override
+  final PubspecEntry? version;
+
+  @override
+  final PubspecHost? host;
+
+  @override
+  final PubspecGitRepo? git;
+
+  factory _PubspecDependency(
+    YamlScalar key,
+    YamlNode value,
+    ResourceProvider? resourceProvider,
+  ) {
+    var name = PubspecNodeImpl(key, resourceProvider);
+    PubspecEntry? path;
+    PubspecEntry? version;
+    PubspecHost? host;
+    PubspecGitRepo? git;
+
+    if (value is YamlScalar) {
+      // Simple version constraint.
+      version = PubspecEntry(null, PubspecNodeImpl(value, resourceProvider));
+    } else if (value is YamlMap) {
+      value.nodes.forEach((k, v) {
+        if (k is! YamlScalar) {
+          return;
+        }
+        YamlScalar key = k;
+        switch (key.toString()) {
+          case 'path':
+            path = _processScalar(key, v, resourceProvider);
+          case 'version':
+            version = _processScalar(key, v, resourceProvider);
+          case 'hosted':
+            host = _processHost(key, v, resourceProvider);
+          case 'git':
+            git = _processGitRepo(key, v, resourceProvider);
+        }
+      });
+    }
+
+    return _PubspecDependency._(
+      name: name,
+      path: path,
+      version: version,
+      host: host,
+      git: git,
+    );
+  }
+
+  _PubspecDependency._({
+    required this.name,
+    required this.path,
+    required this.version,
+    required this.host,
+    required this.git,
+  });
+
+  @override
+  String toString() {
+    var sb = StringBuffer();
+    if (name != null) {
+      sb.write('$name:');
+    }
+    var versionInfo = '';
+    if (version != null) {
+      if (version!.key == null) {
+        versionInfo = ' $version';
+      } else {
+        versionInfo = '\n    $version';
+      }
+    }
+    sb.writeln(versionInfo);
+    if (host != null) {
+      sb.writeln(host);
+    }
+    if (git != null) {
+      sb.writeln(git);
+    }
+    return sb.toString();
+  }
+}
+
+class _PubspecDependencyList extends PubspecDependencyList {
+  final dependencies = <PubspecDependency>[];
+  final PubspecNode token;
+
+  _PubspecDependencyList(this.token);
+
+  @override
+  Iterator<PubspecDependency> get iterator => dependencies.iterator;
+
+  void add(PubspecDependency? dependency) {
+    if (dependency != null) {
+      dependencies.add(dependency);
+    }
+  }
+
+  @override
+  String toString() => '$token\n${dependencies.join('  ')}';
+}
+
+class _PubspecEnvironment implements PubspecEnvironment {
+  @override
+  final PubspecNode token;
+
+  @override
+  final PubspecEntry? flutter;
+
+  @override
+  final PubspecEntry? sdk;
+
+  _PubspecEnvironment(this.token, {required this.flutter, required this.sdk});
+
+  @override
+  String toString() => '''
+    $token:
+      $sdk
+      $flutter''';
+}
+
+class _PubspecGitRepo implements PubspecGitRepo {
+  @override
+  final PubspecNode token;
+
+  @override
+  final PubspecEntry? ref;
+
+  @override
+  final PubspecEntry? url;
+
+  _PubspecGitRepo(this.token, {this.ref, required this.url});
+
+  @override
+  String toString() => '''
+    $token:
+      $url
+      $ref''';
+}
+
+class _PubspecHost implements PubspecHost {
+  @override
+  final bool isShortForm;
+
+  @override
+  final PubspecEntry? name;
+
+  @override
+  final PubspecNode token;
+
+  @override
+  final PubspecEntry? url;
+
+  _PubspecHost(this.token, {required this.isShortForm, this.name, this.url});
+
+  @override
+  String toString() => '''
+    $token:
+      $name
+      $url''';
+}
+
+class _PubspecNodeList extends PubspecNodeList {
+  @override
+  final PubspecNode token;
+
+  final Iterable<PubspecNode> nodes;
+
+  _PubspecNodeList(this.token, this.nodes);
+
+  @override
+  Iterator<PubspecNode> get iterator => nodes.iterator;
+
+  @override
+  String toString() => '''
+$token:
+  - ${nodes.join('\n  - ')}''';
+}
+
 extension on StringBuffer {
   void maybeWrite(Object? value) {
     if (value != null) {
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
index 52fcc96..333e964 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_validator.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/pubspec.dart';
 import 'package:analyzer/dart/analysis/analysis_options.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 1b8bb5e..c07dd40 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/analysis_rule/rule_visitor_registry.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -20,7 +21,6 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/fine/requirements.dart';
 import 'package:analyzer/src/lint/linter.dart';
-import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer/src/test_utilities/lint_registration_mixin.dart';
 import 'package:analyzer/src/utilities/extensions/async.dart';
 import 'package:analyzer/utilities/package_config_file_builder.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart b/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart
index af67e7a..61ea50e 100644
--- a/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unignorable_ignore_test.dart
@@ -2,12 +2,12 @@
 // 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_visitor_registry.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/lint/linter.dart';
-import 'package:analyzer/src/lint/linter_visitor.dart';
 import 'package:analyzer/src/test_utilities/lint_registration_mixin.dart';
 import 'package:analyzer_testing/utilities/utilities.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analyzer/test/src/lint/pub_test.dart b/pkg/analyzer/test/src/lint/pub_test.dart
index d70527b..15409a5 100644
--- a/pkg/analyzer/test/src/lint/pub_test.dart
+++ b/pkg/analyzer/test/src/lint/pub_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/pubspec.dart';
 import 'package:analyzer/src/lint/pub.dart';
 import 'package:source_span/source_span.dart';
 import 'package:test/test.dart';
@@ -100,11 +101,11 @@
       testValue('author', ps.author, equals('Dart Team <misc@dartlang.org>'));
 
       group('authors', () {
-        PSNodeList authors = ps.authors!;
+        PubspecNodeList authors = ps.authors!;
         test('contents', () {
           expect(authors, isNotNull);
-          expect(authors.any((PSNode n) => n.text == 'Bill'), isTrue);
-          expect(authors.any((PSNode n) => n.text == 'Ted'), isTrue);
+          expect(authors.any((PubspecNode n) => n.text == 'Bill'), isTrue);
+          expect(authors.any((PubspecNode n) => n.text == 'Ted'), isTrue);
         });
       });
 
@@ -121,7 +122,7 @@
       ]);
 
       group('environment', () {
-        PSEnvironment environment = ps.environment!;
+        PubspecEnvironment environment = ps.environment!;
         test('contents', () {
           expect(environment, isNotNull);
           expect(environment.sdk!.value.text, equals('>=2.12.0 <3.0.0'));
@@ -130,20 +131,20 @@
       });
 
       group('path', () {
-        PSDependency dep = findDependency(
+        PubspecDependency dep = findDependency(
           ps.dependencies,
           name: 'relative_path',
         );
-        PSEntry depPath = dep.path!;
+        PubspecEntry depPath = dep.path!;
         testValue('path', depPath, equals('../somewhere'));
       });
 
       group('hosted', () {
-        PSDependency dep = findDependency(
+        PubspecDependency dep = findDependency(
           ps.dependencies,
           name: 'transmogrify',
         );
-        PSHost host = dep.host!;
+        PubspecHost host = dep.host!;
         testValue('name', host.name, equals('transmogrify'));
         testValue('url', host.url, equals('http://your-package-server.com'));
         testKeySpan('name', host.name, startOffset: 293, endOffset: 297);
@@ -151,11 +152,11 @@
       });
 
       group('hosted (optional name)', () {
-        PSDependency dep = findDependency(
+        PubspecDependency dep = findDependency(
           ps.dependencies,
           name: 'transmogrify_optional_name',
         );
-        PSHost host = dep.host!;
+        PubspecHost host = dep.host!;
         test('name', () => expect(host.name, isNull));
         testValue('url', host.url, equals('http://your-package-server.com'));
         testKeySpan('url', host.url, startOffset: 432, endOffset: 435);
@@ -163,11 +164,11 @@
       });
 
       group('hosted (short-form)', () {
-        PSDependency dep = findDependency(
+        PubspecDependency dep = findDependency(
           ps.dependencies,
           name: 'transmogrify_short_form',
         );
-        PSHost host = dep.host!;
+        PubspecHost host = dep.host!;
         test('name', () => expect(host.name, isNull));
         testValue('url', host.url, equals('http://your-package-server.com'));
         testKeySpan('url', host.url, startOffset: 529, endOffset: 535);
@@ -175,8 +176,11 @@
       });
 
       group('git', () {
-        PSDependency dep = findDependency(ps.dependencies, name: 'kittens');
-        PSGitRepo git = dep.git!;
+        PubspecDependency dep = findDependency(
+          ps.dependencies,
+          name: 'kittens',
+        );
+        PubspecGitRepo git = dep.git!;
         testValue('ref', git.ref, equals('some-branch'));
         testValue(
           'url',
@@ -186,8 +190,11 @@
       });
 
       group('git (short form)', () {
-        PSDependency dep = findDependency(ps.devDependencies, name: 'kittens2');
-        PSGitRepo git = dep.git!;
+        PubspecDependency dep = findDependency(
+          ps.devDependencies,
+          name: 'kittens2',
+        );
+        PubspecGitRepo git = dep.git!;
         test('ref', () => expect(git.ref, isNull));
         testValue(
           'url',
@@ -235,18 +242,18 @@
   });
 }
 
-PSDependency findDependency(PSDependencyList? deps, {String? name}) =>
+PubspecDependency findDependency(PubspecDependencyList? deps, {String? name}) =>
     deps!.firstWhere((dep) => dep.name!.text == name);
 
 testDepListContains(
   String label,
-  PSDependencyList? list,
+  PubspecDependencyList? list,
   List<Map<String, String>> exp,
 ) {
   test(label, () {
     for (var entry in exp) {
       entry.forEach((k, v) {
-        PSDependency dep = findDependency(list, name: k);
+        PubspecDependency dep = findDependency(list, name: k);
         expect(dep, isNotNull);
         expect(dep.version!.value.text, equals(v));
       });
@@ -254,7 +261,12 @@
   });
 }
 
-testKeySpan(String label, PSEntry? node, {int? startOffset, int? endOffset}) {
+testKeySpan(
+  String label,
+  PubspecEntry? node, {
+  int? startOffset,
+  int? endOffset,
+}) {
   group(label, () {
     group('key', () {
       testSpan(node!.key!.span, startOffset: startOffset, endOffset: endOffset);
@@ -273,7 +285,7 @@
   });
 }
 
-testValue(String label, PSEntry? node, Matcher m) {
+testValue(String label, PubspecEntry? node, Matcher m) {
   group(label, () {
     test('value', () {
       expect(node!.value.text, m);
@@ -281,7 +293,12 @@
   });
 }
 
-testValueSpan(String label, PSEntry? node, {int? startOffset, int? endOffset}) {
+testValueSpan(
+  String label,
+  PubspecEntry? node, {
+  int? startOffset,
+  int? endOffset,
+}) {
   group(label, () {
     group('value', () {
       testSpan(
diff --git a/pkg/analyzer_testing/lib/analysis_rule/analysis_rule.dart b/pkg/analyzer_testing/lib/analysis_rule/analysis_rule.dart
index a6e91bb..0ffbfee 100644
--- a/pkg/analyzer_testing/lib/analysis_rule/analysis_rule.dart
+++ b/pkg/analyzer_testing/lib/analysis_rule/analysis_rule.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/pubspec.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
diff --git a/pkg/linter/lib/src/analyzer.dart b/pkg/linter/lib/src/analyzer.dart
index d88f288..ff78ee5 100644
--- a/pkg/linter/lib/src/analyzer.dart
+++ b/pkg/linter/lib/src/analyzer.dart
@@ -14,7 +14,6 @@
         LinterContext,
         MultiAnalysisRule,
         NodeLintRegistry;
-export 'package:analyzer/src/lint/pub.dart' show PSEntry, PubspecVisitor;
 export 'package:analyzer/src/workspace/pub.dart' show PubPackage;
 
 export 'lint_codes.dart';
diff --git a/pkg/linter/lib/src/rules/pub/package_names.dart b/pkg/linter/lib/src/rules/pub/package_names.dart
index 95b12b0..88eae2b 100644
--- a/pkg/linter/lib/src/rules/pub/package_names.dart
+++ b/pkg/linter/lib/src/rules/pub/package_names.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/pubspec.dart';
 import 'package:analyzer/error/error.dart';
 
 import '../../analyzer.dart';
@@ -25,7 +26,7 @@
   Visitor(this.rule);
 
   @override
-  void visitPackageName(PSEntry name) {
+  void visitPackageName(PubspecEntry name) {
     var packageName = name.value.text;
     if (packageName != null && !isValidPackageName(packageName)) {
       rule.reportAtPubNode(name.value, arguments: [packageName]);
diff --git a/pkg/linter/lib/src/rules/pub/secure_pubspec_urls.dart b/pkg/linter/lib/src/rules/pub/secure_pubspec_urls.dart
index ed2a4d5..5290e57 100644
--- a/pkg/linter/lib/src/rules/pub/secure_pubspec_urls.dart
+++ b/pkg/linter/lib/src/rules/pub/secure_pubspec_urls.dart
@@ -2,8 +2,8 @@
 // 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/pubspec.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/pub.dart'; // ignore: implementation_imports
 
 import '../../analyzer.dart';
 
@@ -26,41 +26,41 @@
   Visitor(this.rule);
 
   @override
-  void visitPackageDependencies(PSDependencyList dependencies) {
+  void visitPackageDependencies(PubspecDependencyList dependencies) {
     _visitDeps(dependencies);
   }
 
   @override
-  void visitPackageDependencyOverrides(PSDependencyList dependencies) {
+  void visitPackageDependencyOverrides(PubspecDependencyList dependencies) {
     _visitDeps(dependencies);
   }
 
   @override
-  void visitPackageDevDependencies(PSDependencyList dependencies) {
+  void visitPackageDevDependencies(PubspecDependencyList dependencies) {
     _visitDeps(dependencies);
   }
 
   @override
-  void visitPackageDocumentation(PSEntry documentation) {
+  void visitPackageDocumentation(PubspecEntry documentation) {
     _checkUrl(documentation.value);
   }
 
   @override
-  void visitPackageHomepage(PSEntry homepage) {
+  void visitPackageHomepage(PubspecEntry homepage) {
     _checkUrl(homepage.value);
   }
 
   @override
-  void visitPackageIssueTracker(PSEntry issueTracker) {
+  void visitPackageIssueTracker(PubspecEntry issueTracker) {
     _checkUrl(issueTracker.value);
   }
 
   @override
-  void visitPackageRepository(PSEntry repository) {
+  void visitPackageRepository(PubspecEntry repository) {
     _checkUrl(repository.value);
   }
 
-  void _checkUrl(PSNode? node) {
+  void _checkUrl(PubspecNode? node) {
     if (node == null) return;
     var text = node.text;
     if (text != null) {
@@ -71,7 +71,7 @@
     }
   }
 
-  void _visitDeps(PSDependencyList dependencies) {
+  void _visitDeps(PubspecDependencyList dependencies) {
     for (var dep in dependencies) {
       _checkUrl(dep.git?.url?.value);
       _checkUrl(dep.host?.url?.value);
diff --git a/pkg/linter/lib/src/rules/pub/sort_pub_dependencies.dart b/pkg/linter/lib/src/rules/pub/sort_pub_dependencies.dart
index 2abab21..2ee0af2 100644
--- a/pkg/linter/lib/src/rules/pub/sort_pub_dependencies.dart
+++ b/pkg/linter/lib/src/rules/pub/sort_pub_dependencies.dart
@@ -2,8 +2,8 @@
 // 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/pubspec.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/lint/pub.dart'; // ignore: implementation_imports
 import 'package:source_span/source_span.dart';
 
 import '../../analyzer.dart';
@@ -27,21 +27,21 @@
   Visitor(this.rule);
 
   @override
-  void visitPackageDependencies(PSDependencyList dependencies) {
+  void visitPackageDependencies(PubspecDependencyList dependencies) {
     _visitDeps(dependencies);
   }
 
   @override
-  void visitPackageDependencyOverrides(PSDependencyList dependencies) {
+  void visitPackageDependencyOverrides(PubspecDependencyList dependencies) {
     _visitDeps(dependencies);
   }
 
   @override
-  void visitPackageDevDependencies(PSDependencyList dependencies) {
+  void visitPackageDevDependencies(PubspecDependencyList dependencies) {
     _visitDeps(dependencies);
   }
 
-  void _visitDeps(PSDependencyList dependencies) {
+  void _visitDeps(PubspecDependencyList dependencies) {
     int compare(SourceLocation? lc1, SourceLocation? lc2) {
       if (lc1 == null || lc2 == null) {
         return 0;