mir_analyzer/symbol.rs
1//! Per-expression resolved symbol data, retained from Pass 2.
2//!
3//! The static analyzer already resolves types for every expression during
4//! analysis but historically discarded the intermediate state. This module
5//! exposes that data so that downstream consumers (e.g. php-lsp) can build
6//! position indexes for hover, go-to-definition, and completions.
7
8use std::sync::Arc;
9
10use mir_types::Union;
11use php_ast::Span;
12
13/// A single resolved symbol observed during Pass 2.
14#[derive(Debug, Clone)]
15pub struct ResolvedSymbol {
16 /// Absolute path of the file this symbol was found in.
17 pub file: Arc<str>,
18 /// Byte-offset span in the source file.
19 pub span: Span,
20 /// What kind of symbol this is.
21 pub kind: SymbolKind,
22 /// The resolved type at this location.
23 pub resolved_type: Union,
24}
25
26impl ResolvedSymbol {
27 /// Return the key used in `Codebase::symbol_reference_locations` for this
28 /// symbol, or `None` for kinds that are not tracked there (e.g. variables).
29 ///
30 /// Key format mirrors `mark_*_referenced_at`:
31 /// - method / static call : `"ClassName::methodname"` (method lowercased)
32 /// - property access : `"ClassName::propName"`
33 /// - function call : fully-qualified function name
34 /// - class reference : fully-qualified class name
35 pub fn codebase_key(&self) -> Option<String> {
36 match &self.kind {
37 SymbolKind::MethodCall { class, method } | SymbolKind::StaticCall { class, method } => {
38 Some(format!("{}::{}", class, method.to_lowercase()))
39 }
40 SymbolKind::PropertyAccess { class, property } => {
41 Some(format!("{}::{}", class, property))
42 }
43 SymbolKind::FunctionCall(fqn) => Some(fqn.to_string()),
44 SymbolKind::ClassReference(fqcn) => Some(fqcn.to_string()),
45 SymbolKind::Variable(_) => None,
46 }
47 }
48}
49
50/// The kind of symbol that was resolved.
51#[derive(Debug, Clone)]
52pub enum SymbolKind {
53 /// A variable reference (`$foo`).
54 Variable(String),
55 /// An instance method call (`$obj->method()`).
56 MethodCall { class: Arc<str>, method: Arc<str> },
57 /// A static method call (`Foo::method()`).
58 StaticCall { class: Arc<str>, method: Arc<str> },
59 /// A property access (`$obj->prop`).
60 PropertyAccess { class: Arc<str>, property: Arc<str> },
61 /// A free function call (`foo()`).
62 FunctionCall(Arc<str>),
63 /// A class reference (`new Foo`, `instanceof Foo`, type hints).
64 ClassReference(Arc<str>),
65}