fingerprint library
Issue fingerprinting for the Flutter accessibility scanner.
Mirrors the rule-engine fingerprint builder (FNV-1a hash + fluent builder), ported from the React integration and adapted for the analyzer/AST world.
Because the reporter (bin/reporter.dart) runs the lint rules as a subprocess
(dart run custom_lint --format json) and only sees their JSON output, a custom fingerprint set
inside a rule cannot reach the reporter in-process the way it does under ESLint. Instead, the
report helper records overrides to a side-channel file in .dart_tool/; the reporter reads
them back (see readOverrides/takeOverride) and otherwise falls back to
generateDefaultFingerprint.
Overriding looks like this inside a rule's run, replacing reporter.atNode(node, code):
report(
resolver,
reporter,
node,
code,
fingerprint: createFingerprint(resolver, node, ruleId: code.name)
.includeRuleId()
.includeElementName()
.includeAttributeHash()
.build(),
);
Classes
- FingerprintBuilder
- Part-composition + hashing engine. Reads from a plain field bag so the same builder backs both the rule-facing createFingerprint and the reporter-facing generateDefaultFingerprint.
Constants
- overridesEnvVar → const String
-
Environment variable the reporter sets on the custom_lint subprocess to pin the absolute path of
the side-channel file. Consulted by
_overridesFileForon both the write and read sides.
Functions
-
clearOverrides(
{String? rootPath}) → void -
Delete the side-channel file. The reporter calls this before a run (so a previous run's entries
can't leak in) and after consuming overrides.
rootPathdefaults to the reporter's cwd. -
createFingerprint(
CustomLintResolver resolver, AstNode node, {required String ruleId}) → FingerprintBuilder -
Fluent builder for custom fingerprints, used inside rules. Extracts the fields from the resolver +
AST node, then delegates to the shared FingerprintBuilder.
ruleIdis passed explicitly because it lives on the rule'sLintCode, not the node. -
defaultOverridesFilePath(
[String? rootPath]) → String -
Absolute path of the side-channel file under
rootPath(defaults to cwd). The reporter calls this to compute the value it exports as overridesEnvVar to the subprocess. -
fingerprintKey(
{required String ruleId, required String filePath, required int line, required int column}) → String - Stable key joining a diagnostic's identity. Both the rule side (write) and the reporter side (read) reconstruct the same key from the rule id, absolute file path and 1-based line/column.
-
fnv1a(
String str) → String - FNV-1a hash → 8-char zero-padded hex string. Matches the rule-engine / React implementation.
-
generateDefaultFingerprint(
{required String ruleId, required String relativePath, required String snippet}) → String - Default fingerprint computed by the reporter from a custom_lint diagnostic + its source snippet.
-
normalizeText(
String? str) → String - Collapse runs of whitespace and trim, so cosmetic formatting changes don't alter fingerprints.
-
readOverrides(
{String? rootPath}) → Map< String, String> -
Read the override file into a
key → fingerprintmap (last entry wins per key). Returns an empty map when no overrides were recorded.rootPathdefaults to the reporter's cwd. -
recordOverride(
{required String rootPath, required String ruleId, required String filePath, required int line, required int column, required String fingerprint}) → void - Append one override entry to the side-channel file. Best-effort: a failed write just means the reporter falls back to the default fingerprint for that diagnostic.
-
report(
CustomLintResolver resolver, DiagnosticReporter reporter, AstNode node, LintCode code, {String? fingerprint}) → void -
Opt-in replacement for
reporter.atNode. Reports the diagnostic as usual; iffingerprintis supplied, records it under the key the reporter will reconstruct from the same location. -
takeOverride(
Map< String, String> overrides, String key) → String? - Read and remove an override, so a stale entry can't be reused within the same report.
-
toRelativePath(
String filePath) → String -
Forward-slashed path relative to the current working directory, falling back to the raw path when
the file lives outside it. Mirrors the reporter's
makeRelativePath.