Skip to main content

brink_analyzer/
lib.rs

1//! Cross-file semantic analysis for inkle's ink narrative scripting language.
2//!
3//! The analyzer merges per-file `SymbolManifest`s from `brink-ir` into a
4//! unified `SymbolIndex`, then runs validation passes (name resolution,
5//! duplicate detection, type checking). Both `brink-compiler` and `brink-lsp`
6//! consume the analysis result.
7
8mod manifest;
9mod resolve;
10mod validate;
11
12pub use brink_ir::FileId;
13pub use brink_ir::ResolutionMap;
14
15use brink_ir::{Diagnostic, HirFile, SymbolIndex, SymbolManifest};
16
17/// The output of cross-file semantic analysis.
18#[derive(Debug, Clone)]
19pub struct AnalysisResult {
20    /// The unified symbol index.
21    pub index: SymbolIndex,
22    /// Resolved references: maps source range → definition id.
23    pub resolutions: ResolutionMap,
24    /// Diagnostics produced during analysis (duplicate definitions, unresolved refs, etc.).
25    pub diagnostics: Vec<Diagnostic>,
26}
27
28/// Run cross-file semantic analysis on a set of lowered files.
29///
30/// Each entry is a `(FileId, HirFile, SymbolManifest)` tuple produced by
31/// per-file HIR lowering. Returns the unified symbol index, resolution map,
32/// and any diagnostics.
33pub fn analyze(files: &[(FileId, &HirFile, &SymbolManifest)]) -> AnalysisResult {
34    let manifest_inputs: Vec<(FileId, &SymbolManifest)> = files
35        .iter()
36        .map(|&(id, _hir, manifest)| (id, manifest))
37        .collect();
38
39    let hir_inputs: Vec<(FileId, &HirFile)> = files.iter().map(|&(id, hir, _)| (id, hir)).collect();
40
41    let (index, mut diagnostics) = manifest::merge_manifests(&manifest_inputs);
42    let (resolutions, resolve_diags) = resolve::resolve_refs(&index, &manifest_inputs);
43    diagnostics.extend(resolve_diags);
44    diagnostics.extend(validate::validate(&hir_inputs));
45
46    AnalysisResult {
47        index,
48        resolutions,
49        diagnostics,
50    }
51}