Skip to content

Commit 982e930

Browse files
committed
Restructure
1 parent 8ee1b83 commit 982e930

10 files changed

Lines changed: 1381 additions & 1211 deletions

File tree

src/completion/builder.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/// Completion item building.
2+
///
3+
/// This module contains the logic for constructing LSP `CompletionItem`s from
4+
/// resolved `ClassInfo`, filtered by the `AccessKind` (arrow vs double-colon).
5+
use tower_lsp::lsp_types::*;
6+
7+
use crate::Backend;
8+
use crate::types::*;
9+
10+
impl Backend {
11+
/// Build the label showing the full method signature.
12+
///
13+
/// Example: `regularCode(string $text, $frogs = false): string`
14+
pub(crate) fn build_method_label(method: &MethodInfo) -> String {
15+
let params: Vec<String> = method
16+
.parameters
17+
.iter()
18+
.map(|p| {
19+
let mut parts = Vec::new();
20+
if let Some(ref th) = p.type_hint {
21+
parts.push(th.clone());
22+
}
23+
if p.is_reference {
24+
parts.push(format!("&{}", p.name));
25+
} else if p.is_variadic {
26+
parts.push(format!("...{}", p.name));
27+
} else {
28+
parts.push(p.name.clone());
29+
}
30+
let param_str = parts.join(" ");
31+
if !p.is_required && !p.is_variadic {
32+
format!("{} = ...", param_str)
33+
} else {
34+
param_str
35+
}
36+
})
37+
.collect();
38+
39+
let ret = method
40+
.return_type
41+
.as_ref()
42+
.map(|r| format!(": {}", r))
43+
.unwrap_or_default();
44+
45+
format!("{}({}){}", method.name, params.join(", "), ret)
46+
}
47+
48+
/// Build completion items for a resolved class, filtered by access kind.
49+
///
50+
/// - `Arrow` access: returns only non-static methods and properties.
51+
/// - `DoubleColon` access: returns only static methods, static properties, and constants.
52+
/// - `Other` access: returns all members.
53+
pub(crate) fn build_completion_items(
54+
target_class: &ClassInfo,
55+
access_kind: AccessKind,
56+
) -> Vec<CompletionItem> {
57+
let mut items: Vec<CompletionItem> = Vec::new();
58+
59+
// Methods — filtered by static / instance
60+
for method in &target_class.methods {
61+
let include = match access_kind {
62+
AccessKind::Arrow => !method.is_static,
63+
AccessKind::DoubleColon => method.is_static,
64+
AccessKind::Other => true,
65+
};
66+
if !include {
67+
continue;
68+
}
69+
70+
let label = Self::build_method_label(method);
71+
items.push(CompletionItem {
72+
label,
73+
kind: Some(CompletionItemKind::METHOD),
74+
detail: Some(format!("Class: {}", target_class.name)),
75+
insert_text: Some(method.name.clone()),
76+
filter_text: Some(method.name.clone()),
77+
..CompletionItem::default()
78+
});
79+
}
80+
81+
// Properties — filtered by static / instance
82+
for property in &target_class.properties {
83+
let include = match access_kind {
84+
AccessKind::Arrow => !property.is_static,
85+
AccessKind::DoubleColon => property.is_static,
86+
AccessKind::Other => true,
87+
};
88+
if !include {
89+
continue;
90+
}
91+
92+
let detail = if let Some(ref th) = property.type_hint {
93+
format!("Class: {} — {}", target_class.name, th)
94+
} else {
95+
format!("Class: {}", target_class.name)
96+
};
97+
98+
items.push(CompletionItem {
99+
label: property.name.clone(),
100+
kind: Some(CompletionItemKind::PROPERTY),
101+
detail: Some(detail),
102+
insert_text: Some(property.name.clone()),
103+
..CompletionItem::default()
104+
});
105+
}
106+
107+
// Constants — only for `::` or unqualified access
108+
if access_kind == AccessKind::DoubleColon || access_kind == AccessKind::Other {
109+
for constant in &target_class.constants {
110+
let detail = if let Some(ref th) = constant.type_hint {
111+
format!("Class: {} — {}", target_class.name, th)
112+
} else {
113+
format!("Class: {}", target_class.name)
114+
};
115+
116+
items.push(CompletionItem {
117+
label: constant.name.clone(),
118+
kind: Some(CompletionItemKind::CONSTANT),
119+
detail: Some(detail),
120+
insert_text: Some(constant.name.clone()),
121+
filter_text: Some(constant.name.clone()),
122+
..CompletionItem::default()
123+
});
124+
}
125+
}
126+
127+
items
128+
}
129+
}

src/completion/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// Completion-related modules.
2+
///
3+
/// This sub-module groups all completion logic:
4+
/// - **target**: Extracting the completion target (access operator and subject)
5+
/// - **resolver**: Resolving the subject to a concrete class type
6+
/// - **builder**: Building LSP `CompletionItem`s from resolved class info
7+
pub mod builder;
8+
pub mod resolver;
9+
pub mod target;

0 commit comments

Comments
 (0)