Skip to content

Commit b8484d5

Browse files
committed
bangls支持绑定补全
1 parent 82c5d1e commit b8484d5

File tree

4 files changed

+66
-25
lines changed

4 files changed

+66
-25
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/bangls/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bangls"
3-
version = "0.1.1"
3+
version = "0.1.2"
44
edition = "2024"
55

66
[features]

tools/bangls/src/main.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crossbeam_channel::{Receiver, Sender};
33
use linked_hash_map::LinkedHashMap;
44
use lsp_server::{IoThreads, Message};
55
use lsp_types::{CompletionItem, CompletionOptions, InitializeParams, MessageType, Position, ServerCapabilities, ShowMessageParams, TextDocumentSyncCapability, TextDocumentSyncKind, Uri, notification::{self, Notification}, request::{self, Request}};
6-
use syntax::{Compile, CompileMeta, EmulateInfo, Expand, LSP_DEBUG};
6+
use syntax::{Compile, CompileMeta, Emulate, EmulateInfo, Expand, LSP_DEBUG};
77

88
fn main() {
99
main_loop().unwrap();
@@ -44,7 +44,7 @@ fn main_loop() -> Result<()> {
4444
let _io = IoJoiner(Some(io));
4545
let server_capabilities = ServerCapabilities {
4646
completion_provider: Some(CompletionOptions {
47-
trigger_characters: Some(vec![]),
47+
trigger_characters: Some(vec![".".to_owned(), ">".to_owned()]),
4848
..Default::default()
4949
}),
5050
text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)),
@@ -207,24 +207,34 @@ impl RequestHandler for request::Completion {
207207
}
208208

209209
fn generate_completes(infos: &[EmulateInfo]) -> Vec<CompletionItem> {
210-
let mut var_counter = LinkedHashMap::new();
210+
let mut var_counter: LinkedHashMap<&syntax::Var, (u32, Vec<_>)> = LinkedHashMap::new();
211211
for info in infos {
212-
for var in info.exist_vars.iter() {
212+
for (kind, var) in info.exist_vars.iter() {
213213
if var.starts_with("__") {
214214
continue;
215215
}
216-
let slot: &mut u32 = var_counter.entry(var).or_default();
216+
let (slot, kinds) = var_counter.entry(var).or_default();
217217
*slot += 1;
218+
kinds.push(kind);
218219
}
219220
}
220221
let full_count = infos.len() as u32;
221-
var_counter.iter().map(|(&var, &count)| {
222+
var_counter.iter().map(|(&var, &(count, ref kinds))| {
222223
let is_full_deps = count == full_count;
224+
225+
let kind = kinds.iter().map(|kind| match kind {
226+
Emulate::Const => format!("constant"),
227+
Emulate::Binder => format!("binder"),
228+
Emulate::ConstBind(var) => format!("const bind to `{var}`"),
229+
Emulate::NakedBind(var) => format!("naked bind to `{var}`"),
230+
}).collect::<Vec<_>>().join(" & ");
231+
223232
let (label, detail) = if is_full_deps {
224-
(var.to_string(), format!("full deps ({count}/{full_count})"))
233+
(var.to_string(), format!("kind: {kind}\nfull deps ({count}/{full_count})"))
225234
} else {
226-
(format!("{var}?"), format!("partial deps ({count}/{full_count})"))
235+
(format!("{var}?"), format!("kind: {kind}\npartial deps ({count}/{full_count})"))
227236
};
237+
228238
CompletionItem {
229239
label,
230240
detail: Some(detail),
@@ -239,7 +249,6 @@ trait NotificationHandler: Notification {
239249
}
240250
impl NotificationHandler for notification::DidOpenTextDocument {
241251
fn handle(ctx: &mut Ctx, param: Self::Params) -> Result<()> {
242-
ctx.send_window_notif(MessageType::LOG, "open file")?;
243252
let file = ctx.open_files.entry(param.text_document.uri).or_default();
244253
*file = param.text_document.text;
245254
Ok(())

tools/syntax/src/lib.rs

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,8 @@ pub trait TakeHandle: Sized {
196196
impl TakeHandle for Var {
197197
fn take_handle(self, meta: &mut CompileMeta) -> Var {
198198
let mut this = self;
199-
if let Some(raw_this) = this.strip_suffix(LSP_DEBUG)
200-
&& meta.is_emulated
201-
{
202-
meta.debug_status();
199+
if let Some(raw_this) = this.strip_suffix(LSP_DEBUG) {
200+
meta.debug_expand_env_status();
203201
this = raw_this.into();
204202
}
205203
if let Some(value) = meta.const_expand_enter(&this) {
@@ -1073,8 +1071,12 @@ impl_derefs!(impl for DExp => (self: self.lines): Expand);
10731071
#[derive(Debug, PartialEq, Clone)]
10741072
pub struct ValueBind(pub Box<Value>, pub Var);
10751073
impl ValueBind {
1076-
pub fn take_unfollow_handle(self, meta: &mut CompileMeta) -> Var {
1074+
pub fn take_unfollow_handle(mut self, meta: &mut CompileMeta) -> Var {
10771075
let handle = self.0.take_handle(meta);
1076+
if let Some(bind_name) = self.1.strip_suffix(LSP_DEBUG) {
1077+
meta.debug_binds_status(handle.clone());
1078+
self.1 = bind_name.into();
1079+
}
10781080
meta.get_value_binded(handle, self.1)
10791081
}
10801082
}
@@ -4171,9 +4173,17 @@ pub trait CompileMetaExtends {
41714173
fn display_binds(&self, value: BindsDisplayer<'_>) -> Cow<'_, str>;
41724174
}
41734175

4176+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
4177+
pub enum Emulate {
4178+
Const,
4179+
Binder,
4180+
ConstBind(Var),
4181+
NakedBind(Var),
4182+
}
4183+
41744184
#[derive(Debug)]
41754185
pub struct EmulateInfo {
4176-
pub exist_vars: Vec<Var>,
4186+
pub exist_vars: Vec<(Emulate, Var)>,
41774187
}
41784188

41794189
pub struct CompileMeta {
@@ -4438,22 +4448,44 @@ impl CompileMeta {
44384448
}
44394449
}
44404450

4441-
fn debug_status(&mut self) {
4451+
fn debug_expand_env_status(&mut self) {
44424452
if !self.is_emulated {
44434453
return;
44444454
}
44454455
let mut printed = HashSet::new();
44464456
let mut vars = vec![];
4447-
for env in self.expand_env.iter().rev() {
4448-
for var in env.consts.keys() {
4449-
if printed.insert(var) {
4450-
vars.push(var.clone());
4451-
}
4452-
}
4453-
}
4457+
self.expand_env.iter().rev()
4458+
.flat_map(|env| env.consts.keys())
4459+
.map(|var| (Emulate::Const, var))
4460+
.chain(self.value_bind_pairs.keys().map(|var| (Emulate::Binder, var)))
4461+
.for_each(|(kind, var)| if printed.insert(var) {
4462+
vars.push((kind, var.clone()));
4463+
});
44544464
self.emulate_infos.push(EmulateInfo { exist_vars: vars });
44554465
}
44564466

4467+
fn debug_binds_status(&mut self, handle: Var) {
4468+
if !self.is_emulated {
4469+
return;
4470+
}
4471+
let bind_vars = self.with_get_binds(handle.clone(), |bind| {
4472+
let mut is_const = HashSet::new();
4473+
let mut bind_vars = bind.bind_names.take().unwrap()
4474+
.inspect(|(var, _)| _ = is_const.insert(*var))
4475+
.map(|(var, _)| (Emulate::ConstBind(handle.clone()), var.clone()))
4476+
.collect::<Vec<_>>();
4477+
4478+
if let Some(pairs) = self.value_bind_pairs.get(&handle) {
4479+
let naked_binds = pairs.keys()
4480+
.filter(|var| !is_const.contains(var))
4481+
.map(|var| (Emulate::NakedBind(handle.clone()), var.clone()));
4482+
bind_vars.extend(naked_binds);
4483+
}
4484+
bind_vars
4485+
});
4486+
self.emulate_infos.push(EmulateInfo { exist_vars: bind_vars });
4487+
}
4488+
44574489
/// 进入一个拥有子命名空间的子块
44584490
/// 返回该子块结束后的命名空间
44594491
pub fn with_block(&mut self,

0 commit comments

Comments
 (0)