start method
Loads plugin configuration (enabled rules, severity overrides, etc.) from analysis_options / SAROPA env vars before rules are registered.
Logs the start event via PluginLogger — the entry will be buffered
in memory until loadNativePluginConfigFromProjectRoot runs and
PluginLogger.setProjectRoot is called on the first analyzed file, then
flushed to reports/.saropa_lints/plugin.log so users have a visible
surface confirming the plugin actually started.
Implementation
@override
FutureOr<void> start() {
PluginLogger.log('Plugin.start() — loading initial config');
// Arm the rapid-edit gate: this runs ONLY inside the interactive analysis
// server (no bin/ CLI instantiates the plugin), so it is the reliable signal
// that in-flux relief is safe. Batch runners (scan/baseline/health, `dart
// analyze`) leave this false and therefore report every rule at full
// fidelity. See SaropaLintRule.deferForRapidEdit / isAnalysisServer.
SaropaLintRule.isAnalysisServer = true;
try {
loadNativePluginConfig();
} on Object catch (e, st) {
PluginLogger.log(
'loadNativePluginConfig failed in Plugin.start()',
error: e,
stackTrace: st,
);
// Defensive: plugin still registers with defaults
}
// Arm the memory-relief subsystem. Before this call,
// initializeCacheManagement() was defined but never invoked anywhere, so
// MemoryPressureHandler stayed disabled: none of the plugin's own caches
// (compilation-unit, file-content, metrics, source-location, semantic
// tokens, import-graph, string interner, …) were ever registered for
// eviction, and auto-relief never armed. They therefore grew for the
// entire analysis-server process lifetime. Wiring it here bounds the
// plugin's OWN footprint and sheds it under pressure.
//
// Scope honesty: this caps the plugin's caches only (sub-GB on a large
// project). It does NOT bound the analyzer's resolved element/AST model,
// which is the dominant cost when many element-resolving rules run over a
// large codebase under strict modes — that is reduced by doing less
// resolution, not by cache relief.
try {
initializeCacheManagement();
// initializeCacheManagement registers the project_context caches but not
// the report-layer ImportGraphTracker, which holds a per-file set of
// import/export URIs for every analyzed file and is never evicted across
// the server lifetime. Register it for pressure relief at clear-late
// priority (rebuilding the graph requires re-walking files, so shed it
// only after cheaper caches). Non-destructive in normal operation — it
// is cleared only when the memory estimate crosses the threshold, and
// repopulates as files are re-analyzed.
MemoryPressureHandler.registerCache(
'importGraphTracker',
ImportGraphTracker.reset,
priority: 85,
);
} on Object catch (e, st) {
PluginLogger.log(
'initializeCacheManagement failed in Plugin.start()',
error: e,
stackTrace: st,
);
}
}