registerSaropaLintRules function
- 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
_ruleFactoriesunconditionally. The per-rule enable gate happens at visitor-entry time in theSaropaContextvisitor wrapper (_wrapCallbackin source), NOT here. This is required because theanalysis_server_pluginAPI callsPlugin.registersynchronously in thePluginServerconstructor — beforestart(), 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 whoseDirectory.currentat plugin-start time was not the project root — e.g. every VS Code user whose workspace was opened via the file picker rather thancode .from the project folder. - Skips a rule when SaropaLintRule.isDisabled is true (honors SaropaLintRule.configAliases).
- Skips rules whose
LintCoderesolves to an emptyLintCode.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,
);
}
}