pub struct ProjectDb { /* private fields */ }Expand description
Stateful incremental project database.
A thin, path-keyed shell around a salsa
database: file texts are salsa inputs, and every derived artifact (parse
tree, HIR, symbol index, resolutions, LIR, StoryData) is a memoized
tracked query with real dependency tracking and early cutoff. Both the
compiler (one-shot) and LSP/IDE (long-lived) use this as their project
model; editor overlays are plain input writes.
Implementations§
Source§impl ProjectDb
impl ProjectDb
Sourcepub fn with_id_base(id_base: u32) -> ProjectDb
pub fn with_id_base(id_base: u32) -> ProjectDb
Create an empty project database whose FileIds start counting from
id_base instead of 0 (issue #1580).
A long-lived host that keeps multiple independent ProjectDb
instances alive at once — brink-lsp’s per-native-project extent
partitioning, one db per governing brink.toml — needs every
instance’s FileIds to be mutually disjoint: each db mints its own
FileIds starting at 0 internally, so two dbs each holding a
first-registered file would otherwise both mint FileId(0), and a
caller merging per-project data into one FileId-keyed map (as
brink-lsp’s cross-project ProjectAnalyses does) would silently
conflate two unrelated files. Callers are responsible for choosing
non-overlapping id_base ranges (e.g. a fixed stride per project
index) — this constructor only seeds the counter, it does not police
collisions across instances it knows nothing about.
Sourcepub fn set_file(&mut self, path: &str, source: String) -> FileId
pub fn set_file(&mut self, path: &str, source: String) -> FileId
Add or replace a file. An existing file’s text is overwritten in place (an input write); derived queries recompute lazily on next read.
Path→FileId identity is durable (#536): re-adding a path that was
previously remove_filed reinstates its original
FileId and salsa input, so per-file memos are overwritten in place
instead of accumulating under freshly-minted dead ids.
Sourcepub fn update_file(&mut self, path: &str, source: String) -> FileId
pub fn update_file(&mut self, path: &str, source: String) -> FileId
Incrementally update a file. Identical to set_file:
salsa’s dependency tracking decides what recomputes.
Sourcepub fn remove_file(&mut self, path: &str)
pub fn remove_file(&mut self, path: &str)
Remove a file from the database.
The salsa input is tombstoned, not forgotten (#536): salsa can never
reclaim an input or the memos keyed on it, so the SourceFile is
parked in retired with its text cleared (releasing the source and
invalidating stale derived memos) while dropping out of the project
file list and every path/id map. From a consumer’s view the file is
gone — enumeration, lookups, and INCLUDE resolution behave exactly as
if it never existed; re-adding the path reuses its original FileId.
Sourcepub fn set_entry(&mut self, path: &str) -> Option<FileId>
pub fn set_entry(&mut self, path: &str) -> Option<FileId>
Set the compile entry point (for the lir_product
and story_data queries). The file must already
be in the database.
Sourcepub fn set_dialect(&mut self, dialect: Option<DialogueDialect>)
pub fn set_dialect(&mut self, dialect: Option<DialogueDialect>)
Set the analysis options (host manifest + external-check severity)
used by the analysis and downstream queries.
Register (or clear) the screenplay dialect config (#3064 B1).
UNGUARDED like set_analysis_options — the salsa write stamps the
revision unconditionally, so callers guard against no-op writes
(IdeSession::set_dialect does).
Sourcepub fn dialect_config(&self) -> Option<&DialogueDialect>
pub fn dialect_config(&self) -> Option<&DialogueDialect>
The registered dialect config, if any.
Sourcepub fn resolved_dialect(&self) -> Option<&Arc<ResolvedDialect>>
pub fn resolved_dialect(&self) -> Option<&Arc<ResolvedDialect>>
The compiled dialect (memoized — regexes compile once per config change), if one is registered and valid.
pub fn set_analysis_options(&mut self, options: AnalysisOptions)
Sourcepub fn analysis_options(&self) -> &AnalysisOptions
pub fn analysis_options(&self) -> &AnalysisOptions
The analysis options currently registered with the database.
Sourcepub fn set_native_root(&mut self, root: Option<String>)
pub fn set_native_root(&mut self, root: Option<String>)
Register the directory native .brink file keys are root-relative
to (issue #1572).
A native file’s module — and therefore every DefinitionId it
qualifies — is a pure function of its root-relative key
(decision-log 2026-07-22 “Native module identity”). brink-driver’s
discover_native already registers such keys, so a compile leaves
this None and nothing changes. A consumer that must key by some
other prefix — the LSP keys by absolute OS path, because every path it
holds round-trips through a file:// URI — declares that prefix here,
and the identity it mints then matches a real compile of the same
tree byte for byte instead of embedding the machine’s directory
layout. Paths not under root are unaffected.
Ink (.ink) files never consult this: their module is their file
stem, which no path prefix can change.
Sourcepub fn native_root(&self) -> Option<&str>
pub fn native_root(&self) -> Option<&str>
The registered native source root, if any — see
set_native_root.
Sourcepub fn set_ink_root(&mut self, root: Option<String>)
pub fn set_ink_root(&mut self, root: Option<String>)
Register the directory .ink file keys are root-relative to
(issue #1696) — ink’s sibling of set_native_root,
consulted by hir::root_content_scope_path’s
qualifier rather than by module identity.
brink-compiler/src/driver.rs’s prepare_driver registers this for
every ink compile, using brink_driver::native_source_root (the same
root-discovery rule native compiles already use) fed the entry path.
None — no caller has registered a root — is byte-identical to the
pre-#1696 world: the qualifier stays the file’s raw registered path.
Sourcepub fn ink_root(&self) -> Option<&str>
pub fn ink_root(&self) -> Option<&str>
The registered ink source root, if any — see
set_ink_root.
Sourcepub fn segment_count(&self, id: FileId) -> Option<usize>
pub fn segment_count(&self, id: FileId) -> Option<usize>
The number of per-knot segments a file splits into (#3084) —
pulling this warms file_segments_query, so perf instrumentation
can price the segmentation toll as its own stage. None for an
unknown file id.
Sourcepub fn projection(&self, id: FileId) -> Option<Arc<Projection>>
pub fn projection(&self, id: FileId) -> Option<Arc<Projection>>
The file’s assembled, identity-joined projection (#3064 B2) — the
per-segment memoized replacement for IdeSession’s retired
wipe-on-every-edit projection cache. None for an unknown id.
Sourcepub fn line_contexts(&self, id: FileId) -> Option<Arc<Vec<LineContext>>>
pub fn line_contexts(&self, id: FileId) -> Option<Arc<Vec<LineContext>>>
The file’s assembled per-line contexts (#3064 B3) — per-segment
memoized for ink (an edit reclassifies the edited knot’s fragment
only), whole-file for native. Dialect-classified when a dialect
config is registered (set_dialect).
Sourcepub fn semantic_tokens(&self, id: FileId) -> Option<Arc<Vec<RawToken>>>
pub fn semantic_tokens(&self, id: FileId) -> Option<Arc<Vec<RawToken>>>
The file’s assembled semantic tokens (#3064 B4) — per-segment memoized for ink with a range-free resolution-kind seam, so both shift edits and unrelated-content edits leave untouched segments’ token memos validated. Whole-file for native.
Sourcepub fn segment_manifest(&self, id: FileId) -> Option<(Vec<(String, u32)>, u32)>
pub fn segment_manifest(&self, id: FileId) -> Option<(Vec<(String, u32)>, u32)>
The outbound-delta segment manifest (#3064 option A, ruled
2026-08-24): one entry per segment — its VERSION KEY and the first
line it owns — plus the file’s total line count. The version key
is the salsa tracked-struct id as index:generation: stable
across shift edits (only the tracked offset field moves),
changed exactly when the segment’s content changes (a new
identity), and ABA-safe (slot reuse and identity-hash collisions
both bump the generation). A consumer caches per-segment slices
under this key, re-fetches only keys it hasn’t seen, and drops
keys that leave the manifest. None for an unknown file or a
non-ink file (no segment road there).
Sourcepub fn segment_line_contexts_slice(
&self,
id: FileId,
key: &str,
) -> Option<Vec<LineContext>>
pub fn segment_line_contexts_slice( &self, id: FileId, key: &str, ) -> Option<Vec<LineContext>>
One segment’s owned line-context slice by manifest version key
(#3064 option A) — concatenating every manifest entry’s slice in
order reproduces line_contexts exactly
(parity-gated). None when the key no longer names a live
segment (the consumer’s manifest is stale — re-fetch it).
Sourcepub fn segment_semantic_tokens_slice(
&self,
id: FileId,
key: &str,
) -> Option<Vec<RawToken>>
pub fn segment_semantic_tokens_slice( &self, id: FileId, key: &str, ) -> Option<Vec<RawToken>>
One segment’s owned semantic-token slice by manifest version key, token lines RELATIVE to the segment’s owned start (#3064 option A) — cached slices survive shift edits; the consumer adds the manifest’s owned-from line back at assembly.
Sourcepub fn segment_semantic_tokens_slice_fast(
&self,
id: FileId,
key: &str,
) -> Option<Vec<RawToken>>
pub fn segment_semantic_tokens_slice_fast( &self, id: FileId, key: &str, ) -> Option<Vec<RawToken>>
segment_semantic_tokens_slice’s
classifier-only sibling (#3064 micro): never pulls the symbol
index or resolutions — the keystroke path’s source, refined by
the deferred refresh.
Sourcepub fn file_ids_topo(&self, entry: FileId) -> Vec<FileId>
pub fn file_ids_topo(&self, entry: FileId) -> Vec<FileId>
Return file IDs in topological include order (included files before
the files that include them), matching ink’s INCLUDE paste
semantics. Only entry and files it transitively INCLUDEs are
returned — see [IncludeGraph::topological_order] (issue #815).
Sourcepub fn compilation_closure(&self) -> Vec<FileId>
pub fn compilation_closure(&self) -> Vec<FileId>
The current compile closure — the exact file set codegen builds from
(compilation_closure_files):
an ink entry’s transitive INCLUDE closure in topological order, or
every discovered .brink module for a native entry. Empty when no
entry is set. Issue #3017 reads this through brink-ide/brink-web
to mark files that are on disk but not in the story — absent
diagnostics on such a file look identical to clean diagnostics, so
the editor says so instead.
Sourcepub fn parse_native(&self, id: FileId) -> Option<&Parse>
pub fn parse_native(&self, id: FileId) -> Option<&Parse>
Get the native (.brink) parse tree for a file (B0.10a, the native
compile seam, issue #1106). The native-frontend sibling of
parse — a distinct nominal Parse type. This runs the
native parser regardless of the file’s extension; the extension-based
frontend dispatch that decides which parser lowering uses lives in
lowered_query, so parse() stays ink-typed and untouched for the
LSP/IDE ink path.
Sourcepub fn hir(&self, id: FileId) -> Option<&HirFile>
pub fn hir(&self, id: FileId) -> Option<&HirFile>
Get the HIR for a file. None for an unknown file id, or for a
tracked file [is_source_file] excludes (issue #2329 review
finding): this per-file accessor reads lowered_query directly, so
without this gate a brink.toml/.md/.json document would still
return its bogus ink-lowered HIR.
Sourcepub fn manifest(&self, id: FileId) -> Option<&SymbolManifest>
pub fn manifest(&self, id: FileId) -> Option<&SymbolManifest>
Get the symbol manifest for a file. None for an unknown file id, or
for a tracked file [is_source_file] excludes — see Self::hir’s
doc (issue #2329 review finding).
Sourcepub fn file_diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
pub fn file_diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
Get per-file diagnostics (parse + lowering). None for an unknown
file id, or for a tracked file [is_source_file] excludes — see
Self::hir’s doc (issue #2329 review finding).
Sourcepub fn admission_diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
pub fn admission_diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
Get the B0.3 HIR admission validator’s output for a file
(docs/hir-admission-contract.md §4.2, issue #1172) — kept separate
from Self::file_diagnostics because it is non-suppressible
(never routed through apply_suppressions). None for an unknown
file id, or for a tracked file [is_source_file] excludes — see
Self::hir’s doc (issue #2329 review finding).
Sourcepub fn suppressions(&self, id: FileId) -> Option<&Suppressions>
pub fn suppressions(&self, id: FileId) -> Option<&Suppressions>
Get suppression directives for a file — the text-scanned
brink-disable/brink-expect comments merged with the file’s
HIR-derived @[allow(…)] scopes (issue #1161), i.e. parsed ∪
HIR-derived, not parsed alone.
Sourcepub fn rebuild_include_graph(&mut self)
pub fn rebuild_include_graph(&mut self)
Rebuild include graph edges for all files.
No-op since the salsa migration: the include graph is a tracked query over the full file set and is always complete. Kept so batch-loading call sites need no change.
Sourcepub fn find_cycle(&self) -> Option<Vec<FileId>>
pub fn find_cycle(&self) -> Option<Vec<FileId>>
Detect cycles in the include graph.
Returns the first cycle found as an ordered path of file IDs.
Sourcepub fn compute_projects(&self) -> Vec<(FileId, Vec<FileId>)>
pub fn compute_projects(&self) -> Vec<(FileId, Vec<FileId>)>
Compute independent projects — the unit every editor surface scopes itself to (the LSP analyzes one project at a time, and navigation only ever sees the files of the project the cursor’s file belongs to).
Returns (root, members) pairs sorted by root FileId; each
project’s members are sorted by FileId.
One rule per frontend:
- Ink groups by
INCLUDEreachability — a root file plus its transitiveINCLUDEclosure (seeIncludeGraph::compute_projects). Unchanged. - Native
.brinkfiles are one project, all of them. Issue #1562:.brinkhas noINCLUDE(the module system replaced it), so running them through the ink rule made every native file its own single-file project and broke go-to-definition, find-references, completion, and diagnostics across every real native workspace. The rule here is the onecompilation_closure_filesalready applies to codegen (decision-log “Native multi-file linking”, 2026-07-23): the discovered module set is the compilation unit, so it is also the editor’s scope. No second discovery mechanism is involved — this partitions the files the db already holds.
The two sets are disjoint, so an INCLUDE in an ink file that names a
.brink target (not expressible in native, and meaningless as ink)
contributes no edge: the native file is in the native project only.
Sourcepub fn is_native(&self, id: FileId) -> bool
pub fn is_native(&self, id: FileId) -> bool
Whether id is a native (.brink) module rather than an ink file.
pub (issue #1562 review finding) so per-root callers —
brink-lsp, which needs the “does this project’s dialect axis even
apply” answer for a project root — can ask it of a FileId without
rederiving [crate::queries::file_language] themselves. (The
off-db analyze_with_modules pass this originally served retired
with option A, 2026-08-24; per-root analysis now runs
Self::analysis_for_members.)
Sourcepub fn is_all_native(&self) -> bool
pub fn is_all_native(&self) -> bool
Whether every recognized source file (.ink or .brink) this db
holds is a native (.brink) module — false for an empty db, one
holding even a single ink source file, or one whose tracked files are
all non-source documents. A tracked file with neither extension (a
project’s own brink.toml, e.g. — issue #2318) does not count either
way; see [crate::queries::project_is_all_native]’s doc for the full
reasoning and the bug this exemption fixes.
The whole-db view of [crate::queries::project_is_all_native], for a
caller that analyzes this db’s entire file set as one unit off-db
(IdeSession, whose editor analysis runs
[brink_analyzer::analyze_with_modules] over
analysis_inputs). That flag is
whole-project, so it is only correct when the set is entirely
native: a mixed set must analyze as ink, or an ink file would get the
native arm of passes that would then mis-judge it.
Distinct from is_native, which answers for one
file and is what a per-project caller (brink-lsp’s analysis_loop,
which analyzes each project root separately) asks of its root.
Sourcepub fn reachable_from(&self, entry: FileId) -> BTreeSet<FileId>
pub fn reachable_from(&self, entry: FileId) -> BTreeSet<FileId>
All files reachable from entry via the forward INCLUDE graph,
entry included.
A forward DFS over INCLUDE edges (transitive). The result is a
BTreeSet, so iteration order is deterministic regardless of graph
internals — callers that compare or render the set get stable output.
Sourcepub fn analysis_inputs_for(
&self,
file_ids: &[FileId],
) -> Vec<(FileId, HirFile, SymbolManifest)>
pub fn analysis_inputs_for( &self, file_ids: &[FileId], ) -> Vec<(FileId, HirFile, SymbolManifest)>
Snapshot analysis inputs for a subset of files.
Like analysis_inputs() but filtered to the given set.
Sourcepub fn analysis_inputs(&self) -> Vec<(FileId, HirFile, SymbolManifest)>
pub fn analysis_inputs(&self) -> Vec<(FileId, HirFile, SymbolManifest)>
Snapshot all analysis inputs for background analysis.
Returns (FileId, HirFile, SymbolManifest) tuples cloned out of the db,
so the caller can run brink_analyzer::analyze_with_modules (with
module_map, also snapshotted) without holding
the lock. Issue #1526: a bare brink_analyzer::analyze() /
analyze_with_options over these inputs is module-blind and mints
different DefinitionIds than this db’s own queries for native
.brink files — see module_map’s doc.
Sourcepub fn file_metadata(&self) -> Vec<(FileId, String, String)>
pub fn file_metadata(&self) -> Vec<(FileId, String, String)>
Snapshot file metadata for diagnostic publishing.
Returns (FileId, path, source) tuples for all files in the db.
Sourcepub fn symbol_index(&self) -> Arc<SymbolIndex> ⓘ
pub fn symbol_index(&self) -> Arc<SymbolIndex> ⓘ
The merged project-wide symbol index (layer 2, symbol_index()).
Sourcepub fn symbol_index_diagnostics(&self) -> &[Diagnostic]
pub fn symbol_index_diagnostics(&self) -> &[Diagnostic]
Indexing diagnostics (duplicate definitions, built-in shadowing)
produced alongside symbol_index.
Sourcepub fn harvest_index(&self) -> Arc<HarvestIndex> ⓘ
pub fn harvest_index(&self) -> Arc<HarvestIndex> ⓘ
The project-wide harvest index (layer 2, issue #2114,
docs/prose-dialect-spec.md §5): every @NAME cue payload and every
inline-markup span kind/attribute name written anywhere in the
project, upgraded by the registered host manifest’s markup
vocabulary where one is declared. The compiler-side sibling of
symbol_index — a completion consumer reads
this the same way it reads that index, and gets the same per-file
[lowered_query] early cutoff the symbol index has: an edit
backdates this memo when it backdates the symbol index’s
lowered_query half, but this index also depends on the registered
host manifest, so a manifest-only edit backdates this memo without
touching the symbol index at all (see
harvest_index_query’s own
doc for the full dependency set).
Sourcepub fn harvest_completion_names(&self) -> Arc<HarvestNames> ⓘ
pub fn harvest_completion_names(&self) -> Arc<HarvestNames> ⓘ
The harvest index’s range-free completion projection (issue #2134):
every harvested cue and span/attribute name, with every site’s
TextRange dropped. This is the query a keystroke-driven completion
path should read instead of harvest_index
itself — see [harvest_completion_index_query]’s own doc for why
the raw index can never Eq-cutoff.
Sourcepub fn conventions_projection(&self) -> Arc<ConventionsProjection> ⓘ
pub fn conventions_projection(&self) -> Arc<ConventionsProjection> ⓘ
The conventions projection (issue #2111, NS-T seam 1/6): every
@[convention] handler declared in the project’s one configured
conventions module, ascending by order — “THE SOLE EDITOR
INTERCHANGE” the design-backport comment on #2111 names
(docs/decision-log.md 2026-08-03). Reads the [project] conventions
pointer, the project module map, the resolved conventions module’s
transitive IMPORT closure (import_closure_query, issue #2111
finding 3), and every file in that closure’s own lowered_query
output — see conventions_projection_query’s doc for the exact
dependency set, and brink_ir::ConventionsProjection’s doc for the
one part of #2111 this still does not deliver: it is not yet
serialized into .inkb/StoryData (the attach schema IS now
resolved to its fields and types, not merely a struct name — that
gap closed in the 2026-08-04 continuation).
Sourcepub fn module_map(&self) -> &BTreeMap<FileId, ResolvedModule>
pub fn module_map(&self) -> &BTreeMap<FileId, ResolvedModule>
Every file’s resolved module (M-1, docs/modules-spec.md §1/§5) — the
map that qualifies DefinitionId identity, built here from file
stems, #@module declarations, the INCLUDE graph, and (for native
.brink files) the path-derived story::… module.
Exposed (issue #1526) for callers that must run
[brink_analyzer::analyze_with_modules] outside the db — the LSP’s
background analysis pass and analysis_inputs
consumers generally — so their DefinitionIds match the ones this
db’s per-def queries (effects,
signature, infer_body) are
keyed by. Identity is minted here and nowhere else.
The map’s diagnostics half is
module_map_diagnostics — an
off-db analyze_with_modules pass has to fold it back in itself
(issue #1553).
Sourcepub fn module_map_diagnostics(&self) -> &[Diagnostic]
pub fn module_map_diagnostics(&self) -> &[Diagnostic]
Stem-collision diagnostics (E085) produced alongside
module_map: a file with no #@module whose
stem is some other file’s declared module name.
A db-driven compile picks these up through
symbol_index_diagnostics, which
folds them in. A caller that instead runs
[brink_analyzer::analyze_with_modules] outside the db (the LSP’s
background pass, IdeSession’s editor analysis) gets only the
analyzer’s own diagnostics, so before issue #1553 the collision was
silently dropped on every editor surface. Such callers must snapshot
this alongside module_map and extend their
result with the entries belonging to their file set.
Sourcepub fn resolve(
&self,
id: FileId,
) -> Option<(Arc<Vec<ResolvedRef>>, &[Diagnostic])>
pub fn resolve( &self, id: FileId, ) -> Option<(Arc<Vec<ResolvedRef>>, &[Diagnostic])>
One file’s resolved references + resolution diagnostics (layer 2,
resolve(FileId)).
Sourcepub fn signature(&self, def: DefinitionId) -> Option<Arc<Sig>>
pub fn signature(&self, def: DefinitionId) -> Option<Arc<Sig>>
Per-declaration signature stub (layer 2, signature(def)). None
for an unknown definition id.
Sourcepub fn local_signature(&self, id: FileId, def: DefinitionId) -> Option<Arc<Sig>>
pub fn local_signature(&self, id: FileId, def: DefinitionId) -> Option<Arc<Sig>>
Signature stub for a local (Param/Temp) def, declared in
id (issue #530): the per-file locals path signature
itself can’t take — see local_signature_query’s doc for why a
local’s DefinitionId needs a caller-supplied file. None for an
unknown file id or a def not declared as a local in that file
(including a declaration id — those stay signature’s
job).
Sourcepub fn analysis_for_members(&self, members: &[FileId]) -> &AnalysisResult
pub fn analysis_for_members(&self, members: &[FileId]) -> &AnalysisResult
Full cross-file analysis over all files, honoring the registered
AnalysisOptions. Memoized; module-aware — identical to
brink_analyzer::analyze_with_modules over
analysis_inputs and
module_map by construction. For native
.brink files this is not identical to analyze_with_options
(module-blind), which mints different DefinitionIds — see
module_map’s doc (issue #1526).
Subset analysis for one project root’s member files (option A total,
2026-08-24) — the retired analyze_with_modules monolith’s
composition, relocated into the member-set-keyed
subset_analysis_query (see its doc). Members are canonicalized
(sorted, deduped) before interning, so caller ordering never mints a
distinct memo. For the whole file set, prefer
analysis — the FG-decomposed incremental chain.
pub fn analysis(&self) -> &AnalysisResult
Sourcepub fn resolutions_index(&self) -> Arc<ResolvedProject> ⓘ
pub fn resolutions_index(&self) -> Arc<ResolvedProject> ⓘ
Index + resolutions, no diagnostics (issue #632 / FG-3 — the
RESOLUTIONS/INDEX half of analysis, split off
from the diagnostics half so a diagnostics-only AnalysisOptions
edit leaves this Arc’s pointer identity untouched).
Sourcepub fn per_file_diagnostics(&self, id: FileId) -> Option<Arc<Vec<Diagnostic>>>
pub fn per_file_diagnostics(&self, id: FileId) -> Option<Arc<Vec<Diagnostic>>>
One file’s per-file diagnostic contributors — structural validation,
the dialect gate, and (brink dialect only) annotation-content checks
(issue #632 / FG-3). None for an unknown file id. A body edit in a
different file leaves this Arc’s pointer identity untouched.
Sourcepub fn file_value_meta(
&self,
id: FileId,
) -> Option<Arc<BTreeMap<DefinitionId, SymbolMeta>>>
pub fn file_value_meta( &self, id: FileId, ) -> Option<Arc<BTreeMap<DefinitionId, SymbolMeta>>>
One file’s VAR/CONST/LIST initializer/doc enrichment (issue #750 /
FG-3 completion) — purely presentational symbol_meta entries, no
diagnostics. None for an unknown file id. A body edit in a
different file leaves this Arc’s pointer identity untouched.
Sourcepub fn file_call_site_diagnostics(
&self,
id: FileId,
) -> Option<Arc<Vec<Diagnostic>>>
pub fn file_call_site_diagnostics( &self, id: FileId, ) -> Option<Arc<Vec<Diagnostic>>>
One file’s external call-site literal checks (E041/E042, issue
#750 / FG-3 completion). None for an unknown file id; empty when
the external_check severity is Off. A body edit in a different
file leaves this Arc’s pointer identity untouched.
Sourcepub fn call_site_metas(&self) -> Arc<BTreeMap<String, SymbolMeta>> ⓘ
pub fn call_site_metas(&self) -> Arc<BTreeMap<String, SymbolMeta>> ⓘ
The range-free, name-keyed external metas feeding the per-file call-site checks (issue #750 / FG-3 completion) — the cutoff seam between the (often re-executed, full-ranged-index-reading) enrichment pass and every file’s call-site memo. Exposed for the dependency-edge tests; pointer identity across an edit proves the seam backdated.
Sourcepub fn diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
pub fn diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
Per-file diagnostics including this file’s share of analysis
diagnostics (layer 3, diagnostics(FileId)). Raw — no suppression
filtering.
Sourcepub fn type_inference(&self) -> &InferenceResult
pub fn type_inference(&self) -> &InferenceResult
Whole-project type inference (TM-1, typed-mode-spec §2/§9 step 1).
Advisory-only substrate: infer_body/type_diagnostics are thin
per-def/per-file views over this. Lazy — nothing in story_data,
lir_product, or diagnostics reads it, so calling this (directly
or via infer_body/type_diagnostics) is the only thing that
triggers the underlying computation.
Sourcepub fn infer_body(&self, def: DefinitionId) -> Option<Arc<BodyTypes>>
pub fn infer_body(&self, def: DefinitionId) -> Option<Arc<BodyTypes>>
Per-def inferred body types (infer_body(def)). None for a def
with no inferable body (not a knot/stitch, or an unknown id).
Sourcepub fn inferred_signature(&self, def: DefinitionId) -> Option<Arc<InferredSig>>
pub fn inferred_signature(&self, def: DefinitionId) -> Option<Arc<InferredSig>>
Per-def inferred signature (inferred_signature(def), FG-2 issue
#631) — the firewall-facing per-def view: params + return type only,
no locals, no ranges. This is the boundary TM-2’s annotation-override
consumer reads. None for a def with no inferable body (not a
knot/stitch, or an unknown id) — same None contract as
signature/infer_body.
Sourcepub fn effects(&self, def: DefinitionId) -> Option<Arc<EffectRow>>
pub fn effects(&self, def: DefinitionId) -> Option<Arc<EffectRow>>
Per-def effect row (effects(def), T2-1, docs/effects-spec.md §2/§4,
issue #860) — the advisory {reads, writes, calls} summary of the
atomic effects def (and everything it transitively calls) may
perform, sited beside inferred_signature.
Conservative-total (spec §3): the row over-reports, never under-reports;
a call through a function value or an unknown callee makes it pessimal
(EffectRow::opaque). None for a def with no inferable body (not a
knot/stitch, or an unknown id) — same contract as
inferred_signature.
Advisory-only: nothing in story_data/lir_product/diagnostics
reads this, so the row is additive metadata that leaves compiled output
byte-identical. Lazy — calling this is the only thing that triggers the
underlying atom harvest + per-SCC fixpoint.
Sourcepub fn ufcs_verdict(
&self,
file: FileId,
range: TextRange,
) -> Option<&UfcsVerdict>
pub fn ufcs_verdict( &self, file: FileId, range: TextRange, ) -> Option<&UfcsVerdict>
The B3a UFCS resolution verdict for the call site at range in
file (issue #1507) — reads the same memoized ufcs_resolution_query
(#1506) LIR lowering already shares, rather than re-running the
analyzer’s ufcs pass a second time for IDE hover/go-to-def. None
when the pass recorded no verdict at this exact range: not a
UFCS-shaped call site, an unresolved one (already diagnosed
E140–E143 elsewhere), or the project has no dotted-callee call
anywhere (ufcs_resolution_query’s own laziness gate).
Sourcepub fn ufcs_call_sites_for_target(
&self,
target: DefinitionId,
) -> Vec<(FileId, TextRange)>
pub fn ufcs_call_sites_for_target( &self, target: DefinitionId, ) -> Vec<(FileId, TextRange)>
Every UFCS call site (recv.verb(args)) whose verdict desugars to a
free function targeting target, project-wide (issue #1539) — reads
the same memoized ufcs_resolution_query table
ufcs_verdict does. The find_references/
rename counterpart to that single-site lookup: renaming or listing
references to a free function must also reach every UFCS call site
that resolves to it, not just its plain ResolutionMap references.
Sourcepub fn type_diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
pub fn type_diagnostics(&self, id: FileId) -> Option<&[Diagnostic]>
Per-file type diagnostics (type_diagnostics(FileId)). Advisory-only
in this slice — always empty (see type_diagnostics_query’s docs).
Sourcepub fn lir_product(&self) -> Option<&LirProduct>
pub fn lir_product(&self) -> Option<&LirProduct>
Whole-project LIR lowering (layer 3). None until an entry point is
set via set_entry.
Sourcepub fn has_errors(&self) -> bool
pub fn has_errors(&self) -> bool
Whether the project has at least one Error-severity diagnostic after
suppression filtering (issue #791 / FG-4a) — the narrow boolean
projection lir_product’s gate reads instead of
the full diagnostics vector. false (never None) when no entry
point is set, matching partition_diagnostics’s empty-errors
default in that case. Exposed for the dependency-edge tests; a
diagnostics-content edit that leaves this boolean unchanged proves
the cutoff seam backdated.
Sourcepub fn story_data(&self) -> Option<&CompileProduct>
pub fn story_data(&self) -> Option<&CompileProduct>
Whole-project compile to brink_format::StoryData (layer 3,
story_data()). None until an entry point is set via
set_entry.