Skip to main content

AnalysisSession

Struct AnalysisSession 

Source
pub struct AnalysisSession { /* private fields */ }
Expand description

Long-lived analysis context. Owns the salsa database and tracks which stubs have been loaded.

Send but not Sync: share it across threads through AnalysisSession::snapshot, never by reference.

Implementations§

Source§

impl AnalysisSession

Source

pub fn analyze_paths( &mut self, paths: &[PathBuf], opts: &BatchOptions, ) -> AnalysisResult

Run the full batch analysis pipeline on a set of file paths.

Source

pub fn re_analyze_file( &mut self, file_path: &str, new_content: &str, opts: &BatchOptions, ) -> AnalysisResult

Re-analyze a single file (definition collection + body analysis) within the batch context, consulting the disk cache.

Use Self::reanalyze_dependents for LSP-style per-file flows that don’t need batch options.

Source

pub fn collect_definitions(&mut self, paths: &[PathBuf])

Collect type definitions only from paths into the codebase without analyzing method bodies or emitting issues. Used to load vendor types.

When a disk-backed cache is attached, per-file StubSlice results from previous runs are reused on a content-hash match, eliminating the parse + definition-collection step. Cache misses run the normal pipeline and write back so subsequent runs hit.

Source§

impl AnalysisSession

Source

pub fn source_of(&self, file: &str) -> Option<Arc<str>>

Retrieve the source text the session has registered for file, if any. Returns None when the file has never been ingested. Used by the parallel re-analysis path to re-feed dependents to body analysis without the caller having to track sources independently.

Source

pub fn reanalyze_dependents( &mut self, file: &str, ) -> Vec<(Arc<str>, FileAnalysis)>

Re-analyze every transitive dependent of file.

When the user saves a file that other files depend on (e.g. editing a base class, an interface, or a trait), those dependents may have new diagnostics. Returns the per-file analysis results so the LSP server can publish updated diagnostics in one batch.

Source text for dependents is retrieved from the session’s salsa inputs (set by previous ingest_file calls) — the caller doesn’t need to track or re-read files. Files for which the session has no source are silently skipped (returns the analyzable subset).

Cross-file inferred return types are resolved on demand via salsa.

Source

pub fn reanalyze_dependents_cancellable( &mut self, file: &str, cancel: &IndexCancel, ) -> Vec<(Arc<str>, FileAnalysis)>

Cancellable variant of Self::reanalyze_dependents.

The consumer flips cancel (typically because a newer edit arrived) to abandon the re-analysis; the flag is checked at each file boundary. Salsa cannot unwind the plain-Rust body-analysis walk mid-flight, so a file already in progress finishes, but no further files are started. Files skipped due to cancellation are simply absent from the returned vec — the consumer should drop a stale flag and start fresh work on each edit.

Source

pub fn reanalyze_files_cancellable( &mut self, files: &[Arc<str>], cancel: &IndexCancel, ) -> Vec<(Arc<str>, FileAnalysis)>

Re-analyze an explicit file set — typically the editor’s currently open files — after an edit elsewhere in the workspace.

The caller passes the files it publishes diagnostics for instead of computing the edited file’s transitive dependents; salsa memoization makes unaffected files ~free. Per-edit cost is O(open files).

Files the session has no source for are silently skipped. Cancellation semantics match Self::reanalyze_dependents_cancellable.

Source

pub fn class_imports(&self, file: &str) -> Vec<(Arc<str>, Arc<str>)>

Return the use-import alias map for a file: a list of (alias, fqcn) pairs where alias is the local name (e.g. "Str") and fqcn is the fully-qualified name (e.g. "Illuminate\\Support\\Str").

Completion handlers can use this to expand a short class name written before :: into its FQN before looking up static members, mirroring the same alias expansion that go-to-definition already performs via symbol_at + definition_of.

Returns an empty Vec if the file has not been ingested or has no use imports.

Source

pub fn pending_lazy_loads(&self, file: &str) -> Vec<Arc<str>>

FQCNs that file imports via use statements but that aren’t yet in the session’s symbol index.

Designed as the input to background prefetching: after the LSP server ingests an open buffer, it can call this and lazy-load the returned FQCNs on a worker thread so the user’s first Cmd+Click into vendor code doesn’t pay the file-read+parse cost.

Returns an empty Vec if the file hasn’t been ingested or has no unresolved imports.

Source

pub fn prefetch_imports(&mut self, file: &str) -> usize

Convenience: synchronously lazy-load every import of file that isn’t already in the symbol index. Returns the number successfully loaded.

Loads only the imported files themselves; their ancestors and signature types resolve through the symbol index or on demand.

Source

pub fn all_classes(&self) -> Vec<(Arc<str>, Option<Location>)>

All class / interface / trait / enum FQCNs currently known to the session, each paired with the file that defines them when available.

Use this to build workspace-wide views (outline, fuzzy search, etc.). Consumers implement their own search/match logic on top — the analyzer only exposes the iterator.

Source

pub fn all_functions(&self) -> Vec<(Arc<str>, Option<Location>)>

All global function FQNs currently known to the session, each paired with their declaration location when available.

Source

pub fn ancestors_of(&self, fqcn: &str) -> Vec<Arc<str>>

Every ancestor of fqcn — extended class, implemented interfaces, used traits, transitively — most-derived first. Does not include fqcn itself. Memoized per FQCN (shares class_ancestors_by_fqcn’s tracked cache with member-resolution paths).

Source

pub fn function_signature(&self, fqn: &str) -> Option<Arc<FunctionDef>>

Full signature for a global function, resolved by FQN.

Source

pub fn dependency_graph(&self) -> DependencyGraph

File dependency graph: which files depend on which other files. Used for incremental invalidation in LSP servers and build systems.

O(E) in the (file, symbol) edges from the reference index and file_structural_symbols, each resolved to its defining file by index lookup. Cached until the file set or an edge changes.

Source§

impl AnalysisSession

Source

pub fn ingest_file(&mut self, file: Arc<str>, source: Arc<str>)

definition-collection ingestion. Updates the file’s source text in the salsa db, runs definition collection, and ingests the resulting stub slice. Triggers stub loading on first call. Also updates the cache’s reverse- dependency graph for file so cross-file invalidation stays correct across incremental edits — without rebuilding the graph from scratch.

If file was previously ingested, its old definitions and reference locations are removed first so renames / deletions don’t leave stale state in the codebase. (Without this, long-running sessions would accumulate dead reference-location entries indefinitely.)

Source

pub fn ingest_file_prepared(&mut self, file: Arc<str>, source: Arc<str>)

Self::ingest_file followed by the file’s Phase-1 warm-up (Self::prepare_file_for_analysis): its direct class references are resolved and lazy-loaded now, at write time, instead of serially at the front of the next references / re-analysis read.

The host edit-path entry point: mutation happens only when text changes; requests are pure reads. Lazy loads triggered by the warm-up go through plain Self::ingest_file, so faulting in a dependency never cascades into preparing its dependencies — the load frontier stays one file wide.

Source

pub fn set_file_text(&mut self, file: Arc<str>, source: Arc<str>)

Register source as the text of file in the salsa input layer without parsing or running definition collection.

This is the LSP-friendly bulk-population entry point: after a workspace scan, callers can feed every discovered file’s text to the session cheaply (an Arc clone plus a HashMap insert per file). Name resolution then happens on demand via Self::load_class, which reads the file from disk through the configured crate::ClassResolver and runs definition collection lazily when a class FQCN actually needs to resolve.

Contrast with Self::ingest_file, which eagerly parses, runs definition collection, and populates the symbol index. Use ingest_file for files the user is actively editing (where in-memory text diverges from disk); use set_file_text for files known only through the workspace scan.

Clears the negative cache: a previously-unresolvable FQCN may now resolve if its defining file is among the newly-registered set.

Source

pub fn set_vendor_files<I>(&mut self, files: I)
where I: IntoIterator<Item = (Arc<str>, Arc<str>)>,

Bulk-register vendor / library files with HIGH salsa durability.

HIGH-durability files are not expected to change during the session. When a LOW-durability project file is edited, salsa can skip O(N) dependency verification for every HIGH-durability file, reducing workspace_symbol_index re-verification cost to O(project files only).

Definition collection runs lazily on first symbol access; no parsing at call time.

Source

pub fn rebuild_workspace_symbol_index(&mut self)

Build or refresh the WorkspaceSymbolIndexSingleton from all currently registered files.

After this call, find_class_like, find_function, and find_global_constant read the singleton through per-name projections instead of recomputing the full O(N_files) dep list via workspace_symbol_index.

Call this once after all vendor + stub + project files have been ingested (end of workspace warm-up). Also called automatically by Self::ingest_file when a file’s declared names change.

Source

pub fn set_workspace_files<I>(&mut self, files: I)
where I: IntoIterator<Item = (Arc<str>, Arc<str>)>,

Bulk variant of Self::set_file_text, with one revision bump for the whole batch.

The intended LSP scan loop is:

let files: Vec<_> = walk_workspace()
    .map(|path| (path, fs::read(&path).unwrap()))
    .collect();
session.set_workspace_files(files);

After this call, every file’s source text is known to salsa. No parsing has happened yet — Definition collection runs per file on the first load_class that needs to consult it.

Source

pub fn index_generation(&self) -> u64

The workspace generation epoch (“are we up to date” counter). Bumped whenever a file is added or removed. A consumer records this alongside the diagnostics it publishes for a file; when the value later advances (background indexing registered more files), those files become candidates for re-analysis + re-publish.

Source

pub fn text_revision(&self) -> Revision

The text-write epoch — salsa’s own global revision, which bumps on every source-file add, edit, or removal (any input write at all), unlike Self::index_generation which only bumps on file add/remove/declaration changes (a body-only edit deliberately leaves it unchanged, to avoid over-invalidating workspace-enumeration queries). A cache of a per-file or per-query result — as opposed to declaration-shape state — must key on this instead: any text write can move or add/remove a reference location within that file, even when no declaration changed. See MirDbStorage::current_revision’s doc comment for why this must be salsa’s own revision rather than a hand-rolled counter.

Source

pub fn index_batch( &mut self, files: &[(Arc<str>, Arc<str>)], parallelism: IndexParallelism, cancel: &IndexCancel, ) -> IndexBatchOutcome

Index one bounded chunk of (path, text) files — the chunked background indexing primitive.

For each chunk this: (1) registers the files as Durability::HIGH salsa inputs in one short write window, (2) parses them to prime the in-process and on-disk declaration caches (in parallel for crate::IndexParallelism::Rayon; sequentially for wasm / single-thread consumers), and (3) merges their declarations into the workspace symbol index singleton incrementally (no full rebuild) so partially-indexed symbols resolve immediately.

The library spawns no thread: the consumer pumps chunks from its own driver (LSP worker thread, or one chunk per wasm event-loop tick), re-checking higher-priority work between calls. cancel is honoured at chunk boundaries so an edit can abandon queued indexing cheaply.

Contract: index the workspace incrementally through this method; don’t bulk-register the entire file set up front and then index — the first call lazily seeds the singleton from the currently-registered set (built-in stubs + this chunk), so keeping that initial set small keeps the first call cheap. Call Self::finalize_index once after the last chunk to reconcile authoritatively.

Responsiveness: parsing runs on a snapshot; only the cheap symbol-map merge writes salsa. Queries running on other threads’ snapshots during that write may unwind with salsa::Cancelled and should be retried.

Source

pub fn finalize_index(&mut self)

Authoritative full rebuild of the workspace symbol index. Call once after the consumer has pumped every Self::index_batch chunk (end of warm-up) to reconcile the incrementally-merged index against the full registered set. Cheap after indexing — every file’s declarations are already cached.

Source

pub fn warm_start_files( &mut self, files: &[(Arc<str>, Arc<str>)], ) -> Vec<Arc<str>>

Replay disk-cached reference-location postings and subtype-index class edges for files, so a returning session’s find-references / goto-implementation queries are answered from the index immediately instead of paying the on-demand analysis sweep the first time each file is queried (indexed_references_to/indexed_subtype_classes’s freshness pass already handles a miss correctly — this only shortens the common warm-start case).

A no-op (per file) unless the disk cache from a previous run has an entry whose content hash matches files’ current text: Self::with_cache/ Self::with_cache_dir must be attached, and each file’s reference locations ([AnalysisCache], populated by the CLI batch pipeline) or definitions ([crate::stub_cache::StubSliceCache], populated by Self::ingest_file/vendor ingestion) must already be on disk from some earlier run/tool invocation against this exact content. A first- ever run (nothing cached yet) is unaffected — every file simply falls through to the existing lazy on-demand paths, same as without this call.

Registers files as Durability::HIGH salsa inputs (like Self::index_batch) if not already registered. Safe to call alongside index_batch in any order; both merge into the same maintained indexes.

Returns every file whose replayed postings carry an unresolved name (live_analyzed: false in RefCommit terms) — these are seeded, but indexed_references_to’s freshness pass can never treat them as immune to growth, so the first query that touches one of them pays a full analyze_file synchronously on the request path (measured: ~1.3-1.5s on a distinctive static method in a 15K-file workspace). The subset is known right here, at warm-start time — a caller with idle time between warm-start and the first live query (e.g. an LSP server between indexReady and the user’s first request) can close most of that gap by handing this list to Self::reanalyze_files_cancellable on a background thread, the same pattern Self::prefetch_imports uses for lazy-loaded vendor FQCNs:

ⓘ
let unresolved = session.warm_start_files(&files);
let s = session.clone();
std::thread::spawn(move || {
    s.reanalyze_files_cancellable(&unresolved, &crate::IndexCancel::new());
});

This only relocates cost that would otherwise land on a user-facing query — it cannot eliminate the freshness check itself, since an unresolved posting is workspace-generation-sensitive by design.

Source

pub fn settle_workspace_index(&mut self)

Reconcile the symbol-index singleton with mirror-only text writes.

Plain upsert_source_file_with_durability calls (an LSP host mirroring watcher-driven external edits or new files) bypass ingest_file’s incremental index maintenance; those files accumulate in a pending set while a singleton exists. Query entry points call this first so the singleton is never consulted stale. Declaration memos are pre-warmed on a snapshot in parallel, so the per-file merge is a memo hit.

Source

pub fn prepare_for_query(&mut self, file: Option<&Arc<str>>)

The single write prelude every interactive query needs before it can read a consistent snapshot: reconcile the workspace index, then (if a specific file is the target of the query) warm up that file’s direct dependencies via Self::prepare_file_for_analysis.

Run it before handing out an super::AnalysisSnapshot: snapshot queries load missing classes on demand, but workspace-wide ones only enumerate what this has settled. Pass the file a query is about, or None for workspace-wide queries.

Source

pub fn invalidate_file(&mut self, file: &str)

Drop a file’s contribution to the session: codebase definitions, reference locations, salsa input handle, cache entry, and outgoing reverse-dependency edges. Cache entries of dependent files are also evicted (cross-file invalidation).

Use this when a file is closed by the consumer, or before a re-ingest of substantially changed content. (Plain re-ingest via Self::ingest_file also drops old definitions, but does not remove the salsa input handle — call this for full cleanup.)

Source

pub fn tracked_file_count(&self) -> usize

Number of files currently tracked in this session’s salsa input set. Stable across reads; useful for diagnostics and memory bounds checks.

Source§

impl AnalysisSession

Source

pub fn contains_function(&self, fqn: &str) -> bool

Returns true if a function with fqn is registered and active in the codebase. Case-insensitive lookup with optional leading backslash.

Source

pub fn contains_class(&self, fqcn: &str) -> bool

Returns true if a class / interface / trait / enum with fqcn is registered and active in the codebase.

Source

pub fn contains_method(&self, class: &str, name: &str) -> bool

Returns true if class has a method named name registered. Method names are matched case-insensitively (PHP method dispatch semantics).

Source

pub fn load_class(&mut self, fqcn: &str) -> LoadOutcome

Resolve fqcn via the configured crate::ClassResolver and ingest the mapped file into the symbol index. Lookups already find such a class on demand; ingesting also makes workspace enumeration see it. The session keeps a negative cache so repeated calls for an unresolvable name don’t re-hit the resolver; the cache is invalidated on any Self::ingest_file / Self::invalidate_file.

This is the LSP-friendly entry point: the analyzer never touches vendor/ on its own, but consumers can ask it to resolve individual symbols on demand. Designed to be called when a diagnostic would otherwise report UndefinedClass.

Returns a crate::LoadOutcome distinguishing already-loaded / freshly-loaded / not-resolvable. Use crate::LoadOutcome::is_loaded when only success matters.

Source§

impl AnalysisSession

Source

pub fn analyze_file_diagnostics( &mut self, file: &str, source: &str, ) -> FileAnalysis

Open-file diagnostics entrypoint for issue-only consumers.

Updates the session’s current text for file, reuses the tracked parse and definition queries for syntax/collector diagnostics, then runs the targeted open-file body-analysis path without retaining whole-file ResolvedSymbol payloads.

Source

pub fn name_at(&mut self, file: &str, byte_offset: u32) -> Option<Name>

Resolve the codebase-level symbol name at byte_offset in file.

The identity half of Self::symbol_at, for consumers that only need a crate::Name to feed Self::definition_of or Self::indexed_references_to.

Source

pub fn outgoing_calls( &mut self, file: &str, byte_offset: u32, ) -> Vec<(Name, Range)>

Calls inside the function or method whose declaration contains byte_offset in file, as (callee, call-site name range) in source order. Callees are resolved crate::Names — a trait alias reports the original method, parent::/self:: the declaring class — so the result feeds Self::definition_of and Self::indexed_references_to directly. Calls in nested closures belong to the enclosing function. new Foo is a class reference, not reported. Empty when the offset is outside a function or method body.

Source

pub fn variable_references( &mut self, file: &str, byte_offset: u32, ) -> Vec<Range>

Every occurrence of the local variable or parameter under byte_offset in file, in source order, as name ranges including the $. An occurrence belongs to the variable when it binds to the same declaration: nested functions and closures start a new scope, except where a closure captures the variable with use; arrow functions share the enclosing scope except for their own parameters. Empty when the offset is not on a variable. Powers document highlight and local rename.

Source

pub fn symbol_at( &mut self, file: &str, byte_offset: u32, ) -> Option<ResolvedSymbol>

Resolve the symbol at byte_offset in file’s current ingested text.

Answers the same as crate::FileAnalysis::symbol_at without the caller retaining a whole-file symbol list: the containing scope is re-analyzed on demand and only its symbol payload is searched.

Side effects: may fault in direct dependencies of file by running the open-file warm-up path (prepare_file_for_analysis).

Source

pub fn definition_of( &mut self, symbol: &Name, ) -> Result<Location, SymbolLookupError>

Resolve a top-level symbol (class or function) to its declaration location. Powers go-to-definition.

Side effects: ingests the file defining the symbol’s class if the symbol index lacks it. Self::definition_of_cached answers the same without writing inputs.

Returns:

  • Ok(Location) — symbol found with a source location
  • Err(NotFound) — no such symbol in the codebase
  • Err(NoSourceLocation) — symbol exists but has no recorded span (e.g. some stub-only declarations)
Source

pub fn definition_of_cached( &self, symbol: &Name, ) -> Result<Location, SymbolLookupError>

Pure variant of Self::definition_of: never writes salsa inputs. Symbols the index lacks load on demand through the resolver and crate::SourceProvider as pure reads.

Source

pub fn implemented_method(&self, method: &Name) -> Option<Name>

Source

pub fn subtype_files( &mut self, class_fqn: &str, include_trait_users: bool, ) -> Vec<Arc<str>>

Files declaring transitive subclasses of class_fqn, backed by the maintained subtype index (see Self::indexed_subtype_classes). Excludes class_fqn’s own declaring file — the caller adds it.

Lets a reference-search caller scope a protected member to its class hierarchy without reconstructing that hierarchy from declaration text: subclasses are matched by resolved FQCN, so extends \Ns\Base and aliased use forms are all found. Read-only from the caller’s perspective; may trigger an on-demand commit of stale/uncommitted candidates’ class edges (same self-heal indexed_subtype_classes uses). include_trait_users also counts classes that use the trait.

Source

pub fn indexed_use_import_locations( &mut self, symbol: &Name, files: &[Arc<str>], ) -> Vec<(Arc<str>, Range)>

Compatibility wrapper for callers that only want use import items. Delegates to Self::indexed_references_to so import references share the same freshness/self-heal path, scope filtering, and memoization boundary as every other reference query.

Source

pub fn indexed_references_to( &mut self, symbol: &Name, files: &[Arc<str>], include_declaration: bool, includes: ReferenceIncludes, should_cancel: &(dyn Fn() -> bool + Sync), ) -> Option<Vec<(Arc<str>, Range)>>

See AnalysisSnapshot::indexed_references_to. Unlike the snapshot form, this runs the owner-side warm-up for stale candidates first, so every one of them is analyzed with its referenced classes loaded.

should_cancel is polled at phase boundaries and between stale candidates; true aborts with None, as does an index settle that snapshot readers keep feeding past its round cap.

Source

pub fn prepare_references_query( &mut self, symbol: &Name, stale: &[Arc<str>], include_declaration: bool, should_cancel: &(dyn Fn() -> bool + Sync), ) -> bool

Owner-side prelude for AnalysisSnapshot::indexed_references_to: the warm-up Self::indexed_references_to runs before reading, so a snapshot taken afterwards analyzes every stale candidate with its dependencies loaded.

stale is AnalysisSnapshot::stale_reference_candidates, computed on a snapshot before the host takes its lock to call this: that scan is O(candidates) and, on a cold workspace, scans file text, so it must not run under the lock. Only the stale files are prepared (not every candidate), the workspace index is settled when it has pending work, and with include_declaration the file declaring symbol is loaded. With nothing stale and nothing pending this is a no-op. A file that went stale after stale was computed is analyzed without the warm-up, as it would be without this call. false when should_cancel stopped it first.

Source

pub fn declaration_name_range( &mut self, symbol: &Name, ) -> Option<(Arc<str>, Range)>

The symbol’s declaration site, narrowed from the collector’s whole-declaration span to the declared name’s own token (matching the span shape of recorded references).

Source

pub fn indexed_subtype_classes( &mut self, class_fqn: &str, files: &[Arc<str>], include_trait_users: bool, ) -> Vec<SubtypeClassSite>

Source

pub fn indexed_direct_subtype_classes( &mut self, class_fqn: &str, files: &[Arc<str>], include_trait_users: bool, ) -> Vec<SubtypeClassSite>

Source

pub fn indexed_method_implementations( &mut self, class_fqn: &str, method: &str, files: &[Arc<str>], ) -> Vec<(Arc<str>, Arc<str>, Range)>

Source

pub fn class_issues(&mut self, files: &[Arc<str>]) -> Vec<Issue>

See AnalysisSnapshot::class_issues. Call this after ingesting or re-analyzing a file and its dependents to get the full diagnostic picture.

Source

pub fn collector_issues(&self, files: &[Arc<str>]) -> Vec<Issue>

See AnalysisSnapshot::collector_issues. Correct regardless of which path put the file’s text into the db (ingest_file, set_file_text, lazy vendor load) or how many times.

Source

pub fn document_symbols(&self, file: &str) -> Vec<DocumentSymbol>

All declarations defined in file as a hierarchical tree.

Classes/interfaces/traits/enums are returned with their methods, properties, and constants nested in children. Top-level functions and constants are returned with empty children.

Source§

impl AnalysisSession

Source

pub fn ensure_all_stubs(&mut self)

Load every embedded PHP stub plus any configured user stubs. Use for batch tools (CLI, full project analysis) where comprehensive symbol coverage matters more than cold-start latency.

Source

pub fn loaded_stub_count(&self) -> usize

Number of distinct embedded stubs currently ingested into the session. Useful for diagnostics and bench reporting.

Source

pub fn ensure_stubs_for_source(&mut self, source: &str)

Auto-discover and ingest the embedded stubs needed to cover every built-in PHP function / class / constant referenced by source.

Used by the open-file analysis paths (crate::FileAnalyzer::analyze and crate::FileAnalyzer::analyze_diagnostics_only) to keep essentials-only mode correct without forcing callers to enumerate which stubs they need. Idempotent — already-loaded stubs are skipped.

The discovery scan is a coarse identifier sweep (see collect_referenced_builtin_paths) — it may pull in a slightly larger set than the file strictly needs, but never misses a referenced built-in. Cost is sub-millisecond per file.

Fast path: if every embedded stub is already loaded (e.g. after a batch tool called Self::ensure_all_stubs), the source scan is skipped entirely.

Source

pub fn ensure_stubs_for_ast(&mut self, program: &Program)

Discover and ingest stubs by walking the parsed AST of a PHP file.

Similar to Self::ensure_stubs_for_source, but takes an already-parsed AST instead of raw source text. Produces zero false positives since it only extracts identifiers from actual AST nodes (not from strings or comments). Preferred over ensure_stubs_for_source when the AST is already available (e.g., in crate::FileAnalyzer).

Idempotent and skips the scan if all stubs are already loaded.

Source

pub fn has_resolver(&self) -> bool

Returns true if this session has a configured class resolver (typically a PSR-4 / classmap autoloader chained with the stub resolver). Used by FileAnalyzer to skip the AST-scan preload when no resolver is wired up.

Source

pub fn prepare_ast_for_analysis(&mut self, program: &Program, file: &str)

Run all pre-passes (builtin-stub loading, vendor-eager-file loading, and PSR-4 class preloading) before body analysis of a single file.

Replaces the two separate ensure_stubs_for_ast / preload_psr4_classes_for_ast calls at every open-file analysis site.

Source

pub fn prepare_file_for_analysis(&mut self, path: &Arc<str>)

Run file’s Phase-1 warm-up — resolve its direct class references and lazy-load any not yet indexed — and record it as prepared against its current text. No-op when the file is unknown or already prepared.

This is the write-path home of the warm-up: hosts call it (via Self::ingest_file_prepared) when text lands, so read paths (indexed_references_to, reanalyze_files_cancellable) find every candidate prepared and stay pure.

Source

pub fn bump_prepare_generation(&mut self)

Invalidate every warm-up skip entry. Call when previously loaded declarations may have been removed outside Self::ingest_file / Self::invalidate_file — e.g. a host that writes file text straight into the salsa layer and detects a declaration-level change. A prepared file might then need its warm-up re-run to lazy-load a replacement (a vendor class shadowed by a since-deleted project class).

Source

pub fn priority_index_for_ast(&mut self, program: &Program, file: &str)

Priority-index the classes directly referenced by file’s AST.

Lookups already find unindexed classes on demand; this moves the buffer’s direct references to the front of the background indexer’s (Self::index_batch) queue so workspace enumeration and reverse lookups see them too. Bounded by one file’s direct references: their ancestors and signature types are left to the background walk. Each Self::load_class is a resolver lookup, a parse (or cache hit) and one index merge; a no-op once indexing has passed the file.

Source§

impl AnalysisSession

Source

pub fn new(php_version: PhpVersion) -> Self

Create a session targeting the given PHP language version.

Source

pub fn snapshot(&self) -> AnalysisSnapshot

A Send + Clone read handle on the current revision. See AnalysisSnapshot for the lifetime rules.

Source

pub fn ref_query_cache_hits(&self) -> u64

Hits served from Self::indexed_references_to’s memoization cache. Diagnostic only — lets tests assert a warm repeat skipped the freshness scan entirely.

Source

pub fn ref_query_cache_locations(&self) -> usize

Total cached reference-location count across the references memo. Diagnostic only — lets tests/hosts assert the cache stays under its byte-proportional cap rather than trusting entry count alone.

Source

pub fn subtype_query_cache_hits(&self) -> u64

Hits served from Self::indexed_subtype_classes’s memoization cache. Diagnostic only.

Source

pub fn subtype_query_cache_sites(&self) -> usize

Total cached site count across the subtype memo. Diagnostic only.

Source

pub fn ref_index_lock_count(&self) -> u64

Times the reference index has been locked on this session’s db.

Source

pub fn class_mention_stats(&self) -> ClassMentionStats

Coverage/size counters for the class-mention gate index (host metrics and memory-bound checks).

Source

pub fn files_mentioning_class( &self, files: &[Arc<str>], class_name: &str, ) -> Vec<Arc<str>>

Source

pub fn files_mentioning_any( &self, files: &[Arc<str>], needles: &[&str], ) -> Vec<Arc<str>>

Source

pub fn flush_analysis_cache(&self)

Persist the attached [AnalysisCache] to disk. No-op without an attached cache or when nothing changed since the last flush. Reference postings committed by session sweeps and on-demand query freshness passes reach disk only here — a host should call this after its warm sweep completes and on shutdown so the next launch’s Self::warm_start_files finds them.

Source

pub fn workspace_symbol_index_ready(&self) -> bool

Whether the workspace symbol index singleton is populated (seeded by Self::warm_start_files or built by index_batch) — symbol lookups answer from the O(1) map instead of the tracked O(all-files) walk.

Source

pub fn workspace_index_walks(&self) -> u64

Executions of the tracked O(all-files) workspace_symbol_index walk (diagnostic; a warm-started session should keep this at zero).

Source

pub fn work_count(&self, work: Work) -> u64

Units of work this session’s analysis has done (diagnostic).

Source

pub fn with_source_provider(self, provider: Arc<dyn SourceProvider>) -> Self

Swap in a custom crate::SourceProvider. LSPs install a VFS-backed provider here so the analyzer reads from unsaved editor buffers instead of disk.

Source

pub fn with_cache(self, cache: Arc<AnalysisCache>) -> Self

Attach a pre-built [AnalysisCache] (the body-analysis issue cache) and open a sibling definition StubSlice cache under the same root, so callers using this builder get the same speedup as with_cache_dir.

Call before any file is ingested. A debug assertion catches misuse.

Source

pub fn with_cache_dir(self, cache_dir: &Path) -> Self

Convenience: open a disk-backed cache at cache_dir and attach it.

Attaches both the body-analysis issue cache ([AnalysisCache]) and the definition StubSlice cache to the shared database. Call before any file is ingested. A debug assertion catches misuse.

Source

pub fn with_psr4(self, map: Arc<Psr4Map>) -> Self

Attach a Composer autoload map (PSR-4, PSR-0, classmap, files). Sets the same map as the active crate::ClassResolver so Self::load_class works out of the box.

Source

pub fn with_class_resolver(self, resolver: Arc<dyn ClassResolver>) -> Self

Attach a generic class resolver for projects that don’t use Composer (WordPress, Drupal, custom autoloaders, workspace-walk indexes). Replaces any previously-set Composer-backed resolver. Automatically wrapped with stub awareness so PHP built-ins remain resolvable.

Source

pub fn with_user_stubs(self, files: Vec<PathBuf>, dirs: Vec<PathBuf>) -> Self

Source

pub fn with_memoize_method_call_results(self, enabled: bool) -> Self

Assume repeated zero-arg method calls on the same receiver return the same value (Psalm’s memoizeMethodCallResults), so narrowing them (if (!$a->b()) throw; return $a->b();) holds. Call before Self::with_cache_dir.

Source

pub fn php_version(&self) -> PhpVersion

Source

pub fn cache(&self) -> Option<&AnalysisCache>

Source

pub fn psr4(&self) -> Option<&Psr4Map>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Lookup<T> for T

Source§

fn into_owned(self) -> T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more