analysis_server_plugin_core 1.1.5 copy "analysis_server_plugin_core: ^1.1.5" to clipboard
analysis_server_plugin_core: ^1.1.5 copied to clipboard

Core components to build a custom Dart analysis server plugin.

analysis_server_plugin_core #

Core components to build a custom Dart analysis server plugin.

Installation #

From pub.dev

Add this to your pubspec.yaml

dependencies:
  analysis_server_plugin_core: ^1.1.5

Or, From Git repo

dependencies:
  analysis_server_plugin_core:
    git:
      url: https://github.com/Ragibn5/dart-flutter-packages.git
      path: analysis_server_plugin_core
      ref: analysis_server_plugin_core-1.1.5

๐Ÿ’ก Why This Package Exists #

analysis_server_plugin_core is a small foundational package for writing custom Dart analyzer plugins. It sits on top of the official analyzer/plugin APIs and adds the reusable structure most real plugins need.

The official APIs give you the raw building blocks โ€“ plugins, lint rules, visitors, rule contexts, diagnostics, AST nodes, type information, and much more. This package focuses on the missing application-level layer around those APIs.

It provides:

  • Package context โ€” access useful metadata about the package currently being analyzed.
  • Shared plugin config โ€” load plugin-specific config once and reuse it across rules.
  • Typed rule context โ€” pass typed config and debugging setup into visitors without manual wiring.
  • Analyzer-friendly debugging โ€” write structured file logs from rules running inside the analysis server.
  • Consistent scan scope โ€” define where your rules should run without repeating checks in every rule.
  • Semantic rule helpers โ€” use analyzer-backed utilities for common rule logic instead of fragile manual checks.

๐Ÿš€ Quick start #

The core idea is straightforward.

  • write your own config model
  • write a config loader that loads the config
  • Write rules and visitors for processing those rules

And, the package handles the repeated infrastructure around them. Here is how you build a minimal analyzer plugin in 5 steps:

1. Build the plugin #

The analysis server looks for a top-level variable named plugin. Use PluginBuilder to create it.

import 'package:analysis_server_plugin_core/analysis_server_plugin_core.dart';

final plugin = PluginBuilder<ExampleConfig>(name: 'ExamplePlugin', configLoader: ExampleConfigLoader())
    .addLintRule((sessionDataManager) => ExampleLintRule(sessionDataManager))
    .addWarningRule((sessionDataManager) => ExampleWarningRule(sessionDataManager))
    .build();
Method Description
name Plugin identifier reported to the Dart analysis server.
configLoader A ContextConfigLoader subclass that loads config for each analyzed package.
addLintRule() Registers a lint rule factory โ€” receives the shared SessionDataManager.
addWarningRule() Registers a warning rule factory โ€” same shape as addLintRule().

2. Define plugin config #

Extend ContextConfig to bundle your plugin's settings with the built-in PackageInfo, LogConfig, and ScanConfig.

class ExampleConfig extends ContextConfig {
  final String requiredAnnotationName;

  const ExampleConfig({
    required super.packageInfo,
    required super.logConfig,
    required super.scanConfig,
    this.requiredAnnotationName = 'DomainModel',
  });

  @override
  Map<String, dynamic> toMap() =>
      {
        'packageInfo': packageInfo.toMap(),
        'logConfig': logConfig.toMap(),
        'scanConfig': scanConfig.toMap(),
        'requiredAnnotationName': requiredAnnotationName,
      };
}

3. Load config per package #

Extend ContextConfigLoader and implement loadPluginConfig. The base class extracts PackageInfo from pubspec.yaml for you โ€” you fill in plugin-specific values.

It is up to you where you want to load the config from. For example, a YAML file or any other source.

class ExampleConfigLoader extends ContextConfigLoader<ExampleConfig> {
  @override
  ExampleConfig loadPluginConfig(RuleContext context, PackageInfo packageInfo) {
    return ExampleConfig(
      packageInfo: packageInfo,
      logConfig: const LogConfig(
        enabled: true,
        allowInfoLog: true,
        logDirectoryRelativePathFromProjectRoot: 'logs/analyzer_plugins/example',
      ),
      scanConfig: const ScanConfig(scanLibDir: true, scanTestDir: false),
    );
  }
}

4. Write a rule #

Extend SessionManagedAnalysisRule<T>. By the time registerSessionedNodeProcessors runs, config is loaded, the type is verified, and ScanConfig filtering is done.

class ExampleLintRule extends SessionManagedAnalysisRule<ExampleConfig> {
  static const code = LintCode(
    'example_rule',
    'Classes annotated with @{0} must be public.',
  );

  ExampleLintRule(SessionDataManager sessionDataManager)
      : super(RuleMetadata(code.name, code.problemMessage), sessionDataManager);

  @override
  DiagnosticCode get diagnosticCode => code;

  @override
  void registerSessionedNodeProcessors(RuleContext context,
      RuleVisitorRegistry registry,
      RuleSessionContext<ExampleConfig> sessionContext,) {
    registry.addClassDeclaration(
      this,
      _ExampleVisitor(rule: this, sessionContext: sessionContext),
    );
  }
}

5. Write a visitor #

The visitor contains the AST analysis logic. Use sessionContext for config and logging, and rule.reportAtNode() to emit diagnostics.

class _ExampleVisitor extends SimpleAstVisitor<void> {
  final ExampleLintRule rule;
  final RuleSessionContext<ExampleConfig> sessionContext;

  const _ExampleVisitor({required this.rule, required this.sessionContext});

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    final annotationName = sessionContext.config.requiredAnnotationName;
    final hasAnnotation = node.metadata.any(
          (a) => a.name.name == annotationName,
    );

    if (hasAnnotation && node.name.lexeme.startsWith('_')) {
      sessionContext.logger.logWarning(
        tag: 'ExampleLintRule',
        message: 'Private annotated class: ${node.name.lexeme}',
      );
      rule.reportAtNode(node, arguments: [annotationName]);
    }
  }
}

๐Ÿงฐ Utilities #

Resolve annotations #


final resolver = AnnotationTypeResolverFactory.create();
final typeName = resolver.resolveTypeName(annotation);

Match collection types #


final resolver = CollectionTypeResolverFactory.create();
final isStringList = resolver.isListOf(returnType, valueType: 'String');
final isJsonMap = resolver.isMapOf(returnType, keyType: 'String', valueType: 'dynamic');

Work with paths #


final relativePath = context.packageRelativeUnitPath(pathSeparator: '/');
final normalized = r'lib\src\rule.dart'.normalizePathSeparators(pathSeparator: '/');

๐Ÿ“ฆ API #

Everything is exported from a single import:

import 'package:analysis_server_plugin_core/analysis_server_plugin_core.dart';
Component Purpose
PluginBuilder<C> Type-safe builder โ€” wires config loader, rules, and session manager into a Plugin.
SessionedRuleFactory<C> Function signature: receives a SessionDataManager, returns a rule.
SessionManagedAnalysisRule<T> Base class for rules with typed config, logging, session reuse, and scan filtering.
ContextConfig Base config model โ€” extend with your plugin's options.
ContextConfigLoader<T> Loads config and resolves package metadata per RuleContext.
RuleSessionContext<T> Typed config + logger passed to visitors.
RuleMetadata Rule identity (code name and problem message).
PackageInfo Package name and root path.
LogConfig Enables/disables file logging and log levels.
ScanConfig Controls lib/ and test/ scanning.
SessionDataManager Caches session data per package.
SessionDataManagerFactory Creates a SessionDataManager (also used internally by PluginBuilder).
SessionLogger Logger with global and per-level switches.
AnnotationTypeResolver Resolves annotation class names through constant values.
CollectionTypeResolver Matches List<T> and Map<K, V> with typedef and nullability support.
PathStringExtensions Normalizes and manipulates path separators.
RuleContextExtensions Converts unit paths to package-relative paths.

๐Ÿงช Examples #

See example.dart for a complete minimal plugin.

Real plugins built with this package:

0
likes
150
points
56
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Core components to build a custom Dart analysis server plugin.

Homepage
Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

analysis_server_plugin, analyzer, analyzer_plugin, analyzer_testing, dart_functionals, intl, loghub, meta, path, yaml

More

Packages that depend on analysis_server_plugin_core