Skip to main content

Module fingerprint

Module fingerprint 

Source
Expand description

Position-independent fingerprints of AST nodes.

structural_fingerprint hashes a node’s full structure — kinds, names, literals, operators, doc comments — while ignoring every Span. Two nodes that differ only in where they sit in the file (an edit above a function shifts every offset inside it) get the same fingerprint.

This is meant for incremental tools such as salsa-based analyzers: store the fingerprint next to a declaration’s subtree and compare fingerprints instead of nodes, so a declaration whose code did not change compares equal after unrelated edits and its downstream results can be reused. Results derived from such a node must not carry its absolute positions; keep them relative to the declaration and add its current start when reporting.

It works on anything that implements serde::Serialize, so both the arena and the owned AST are supported.

use php_ast::fingerprint::structural_fingerprint;
use php_ast::owned::{Expr, ExprKind};
use php_ast::Span;

let var = |name: &str, start: u32| Expr {
    kind: ExprKind::Variable(name.into()),
    span: Span::new(start, start + 1 + name.len() as u32),
};
// Same variable at two positions: equal fingerprints.
assert_eq!(structural_fingerprint(&var("x", 10)), structural_fingerprint(&var("x", 90)));
// A different variable: different fingerprints.
assert_ne!(structural_fingerprint(&var("x", 10)), structural_fingerprint(&var("y", 10)));

Functions§

structural_fingerprint
A 64-bit hash of node’s structure that ignores every Span.