registerSaropaLintRules function

void registerSaropaLintRules(
  1. PluginRegistry registry
)

Registers Saropa lint rules and their quick-fix generators on registry.

When to call

Invoke from your analyzer plugin’s Plugin.register after loadNativePluginConfig has run (typically from Plugin.start). Reads SaropaLintRule.enabledRules and SaropaLintRule.disabledRules, which that loader fills from analysis_options.yaml, analysis_options_custom.yaml, and environment overrides.

Semantics

  • Registers every rule from _ruleFactories unconditionally. The per-rule enable gate happens at visitor-entry time in the SaropaContext visitor wrapper (_wrapCallback in source), NOT here. This is required because the analysis_server_plugin API calls Plugin.register synchronously in the PluginServer constructor — before start(), before any communication channel, before any context-root information. At registration time the plugin cannot know the consumer's project root, so it cannot know which rules are enabled. The previous design read SaropaLintRule.enabledRules here and early-returned when it was null/empty, which silently killed every rule for every consumer whose Directory.current at plugin-start time was not the project root — e.g. every VS Code user whose workspace was opened via the file picker rather than code . from the project folder.
  • Skips a rule when SaropaLintRule.isDisabled is true (honors SaropaLintRule.configAliases).
  • Skips rules whose LintCode resolves to an empty LintCode.lowerCaseName.
  • Registers each remaining rule and its SaropaLintRule.fixGenerators on registry. Failures are logged and swallowed so a bad rule cannot crash the analysis server isolate.

Composite (meta-)plugins

Dart allows one analyzer plugin per analysis context. To ship Saropa plus org-specific rules, create a single dev_dependency package that depends on package:saropa_lints, exposes the top-level plugin in lib/main.dart, calls loadNativePluginConfig in start, calls this function in register, then registers your own rules. Put Saropa’s version, diagnostics, and rule_packs under your plugin’s YAML key. See doc/guides/composite_analyzer_plugin.md.

Implementation

void registerSaropaLintRules(PluginRegistry registry) {
  try {
    // Instantiate every factory. ~2100 lightweight rule instances is
    // acceptable — the alternative (conditionally instantiating only an
    // "enabled" subset at register time) is structurally broken because
    // the plugin cannot know the project root when `register()` is called
    // (see doc comment above). Per-visitor early-return on non-enabled
    // rules happens in `SaropaContext._wrapCallback` at ~O(1) per visit.
    final rules = _ruleFactories.values.map((f) => f()).toList(growable: false);
    if (rules.isEmpty) return;
    _logUnknownRelatedRuleReferences(rules);
    _logUnknownConflictingRuleReferences(rules);
    _logUnknownSupersedesRuleReferences(rules);

    var registered = 0;
    for (final rule in rules) {
      final code = rule.code;
      if (code.lowerCaseName.isEmpty) continue;

      if (rule.isDisabled) {
        continue;
      }

      registry.registerLintRule(rule);
      registered++;

      for (final generator in rule.fixGenerators) {
        registry.registerFixForRule(code, generator);
      }
    }

    // User-visible telemetry — once the project root is known and the
    // buffered log flushes, consumers can see "Registered N rules" in
    // `reports/.saropa_lints/plugin.log`. If they instead see "Registered
    // 0 rules" or no line at all, the plugin is mis-wired (e.g. every
    // rule landed in disabledRules, or register() was never called).
    PluginLogger.log(
      'registerSaropaLintRules: registered $registered rules '
      '(${rules.length} candidates, ${rules.length - registered} disabled)',
    );
  } on Object catch (e, st) {
    PluginLogger.error(
      'registerSaropaLintRules failed',
      error: e,
      stackTrace: st,
    );
  }
}