Skip to content

Commit fa95595

Browse files
committed
完成 bangls 的启发式片段补全 (参数系统)
1 parent 56dca7f commit fa95595

File tree

5 files changed

+84
-13
lines changed

5 files changed

+84
-13
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.8"
3+
version = "0.1.9"
44
edition = "2024"
55

66
[features]

tools/bangls/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ bangls 是一个 bang 语言的语言服务器, 使用语言服务器协议 (LSP
2626
- [x] 基本补全
2727
- [x] 实时分析
2828
- [x] 报错显示
29-
- [ ] 启发式片段补全
29+
- [x] 启发式片段补全
3030
- [ ] 定义跳转
3131
- [ ] 引用跳转
3232
- [x] 文档查看

tools/bangls/src/main.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use display_source::DisplaySourceMeta;
88
use line_column::line_column;
99
use linked_hash_map::LinkedHashMap;
1010
use lsp_server::{IoThreads, Message};
11-
use lsp_types::{CompletionItem, CompletionItemKind, CompletionOptions, Diagnostic, DiagnosticSeverity, InitializeParams, InitializeResult, MessageType, Position, ServerCapabilities, ShowMessageParams, TextDocumentSyncCapability, TextDocumentSyncKind, Uri, notification::{self, Notification}, request::{self, Request}};
11+
use lsp_types::{CompletionItem, CompletionItemKind, CompletionOptions, Diagnostic, DiagnosticSeverity, InitializeParams, InitializeResult, InsertTextFormat, MessageType, Position, ServerCapabilities, ShowMessageParams, TextDocumentSyncCapability, TextDocumentSyncKind, Uri, notification::{self, Notification}, request::{self, Request}};
1212
use syntax::{Compile, CompileMeta, CompileMetaExtends, Emulate, EmulateInfo, Expand, LSP_DEBUG, LSP_HOVER};
1313

1414
fn main() {
@@ -318,21 +318,26 @@ impl RequestHandler for request::DocumentDiagnosticRequest {
318318
}
319319

320320
fn generate_completes(infos: &[EmulateInfo]) -> Vec<CompletionItem> {
321+
let on_line_first = infos.iter().any(|it| it.in_other_line_first);
321322
let infos = infos.iter()
322323
.filter_map(|it| it.exist_vars.as_ref());
323324
let full_count = infos.clone().count() as u32;
324-
let mut var_counter: LinkedHashMap<&syntax::Var, (u32, Vec<_>)> = LinkedHashMap::new();
325+
let mut var_counter: LinkedHashMap<&syntax::Var, (u32, Vec<_>, bool)> = LinkedHashMap::new();
325326
for info in infos {
326-
for (kind, var) in info {
327+
for (kind, var, use_args) in info {
327328
if var.starts_with("__") {
328329
continue;
329330
}
330-
let (slot, kinds) = var_counter.entry(var).or_default();
331+
let (slot, kinds, use_args_slot)
332+
= var_counter.entry(var).or_default();
331333
*slot += 1;
334+
*use_args_slot |= *use_args;
332335
kinds.push(kind);
333336
}
334337
}
335-
let mut items: Vec<CompletionItem> = var_counter.iter().map(|(&var, &(count, ref kinds))| {
338+
let mut items: Vec<CompletionItem> = var_counter.iter().map(
339+
|(&var, &(count, ref kinds, use_args))|
340+
{
336341
let is_full_deps = count == full_count;
337342

338343
let mut first_kind = None;
@@ -358,11 +363,20 @@ fn generate_completes(infos: &[EmulateInfo]) -> Vec<CompletionItem> {
358363
Emulate::NakedBind(_) => CompletionItemKind::FIELD,
359364
});
360365

366+
let insert_snippet = match (use_args, on_line_first) {
367+
(true, true) => format!("{var}!$0;"),
368+
(true, false) => format!("{var}[$0]"),
369+
_ => var.to_string(),
370+
};
371+
let insert_text_format = (*insert_snippet != **var)
372+
.then_some(InsertTextFormat::SNIPPET);
373+
361374
CompletionItem {
362375
label,
363376
detail: Some(detail),
364377
kind: first_kind,
365-
insert_text: Some(var.to_string()),
378+
insert_text: Some(insert_snippet),
379+
insert_text_format,
366380
..Default::default()
367381
}
368382
}).collect();

tools/syntax/src/lib.rs

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,47 @@ impl Value {
312312
pub fn is_value_bind(&self) -> bool {
313313
matches!(self, Self::ValueBind(..))
314314
}
315+
316+
fn like_used_args_system(&self, meta: &CompileMeta) -> bool {
317+
let value = match self {
318+
Value::Var(var) => meta.get_const_value(var).map(|d| &d.value),
319+
_ => Some(self),
320+
};
321+
let Some(slot) = value else { return false };
322+
let mut slot = slot.clone();
323+
for _ in 0..8 {
324+
match slot {
325+
Value::Var(_) | Value::ReprVar(_) | Value::ResultHandle |
326+
Value::Cmper(_) | Value::Binder => return false,
327+
Value::BuiltinFunc(_) => return true,
328+
Value::ClosuredValue(ClosuredValue::Uninit { value, .. }) => slot = *value,
329+
Value::ClosuredValue(ClosuredValue::Inited { bind_handle, .. }) => {
330+
match meta.view_bind(&ClosuredValue::make_valkey(bind_handle.clone()).into()) {
331+
Ok(value) => slot = value,
332+
Err(_) => return false,
333+
}
334+
},
335+
Value::ClosuredValue(_) => return false,
336+
value @ (Value::ValueBind(_) | Value::ValueBindRef(_)) => {
337+
match meta.view_bind(&value) {
338+
Ok(value) => slot = value,
339+
Err(_) => return false,
340+
}
341+
},
342+
Value::DExp(dexp) => return dexp.lines.iter().find_map(|line| {
343+
match line {
344+
LogicLine::ArgsRepeat(_) => Some(true),
345+
LogicLine::Match(m) => Some(m.args.is_expanded()),
346+
LogicLine::ConstMatch(m) => Some(m.args.is_expanded()),
347+
LogicLine::Other(args) => Some(args.is_expanded()),
348+
LogicLine::SetArgs(args) => Some(args.is_expanded()),
349+
_ => None,
350+
}
351+
}).unwrap_or(false),
352+
}
353+
}
354+
false
355+
}
315356
}
316357
impl TakeHandle for Value {
317358
fn take_handle(self, meta: &mut CompileMeta) -> Var {
@@ -3831,6 +3872,16 @@ impl Compile for LogicLine {
38313872
meta.push(lab.to_string().into())
38323873
},
38333874
Self::Other(args) => {
3875+
if meta.is_emulated && let Some(normal) = args.as_normal()
3876+
&& let Some(first) = normal.first()
3877+
&& let Some(var) = first.as_var()
3878+
&& var.ends_with(LSP_DEBUG)
3879+
{
3880+
meta.emulate(EmulateInfo {
3881+
in_other_line_first: true,
3882+
..Default::default()
3883+
});
3884+
}
38343885
let handles: Vec<Var> = args.into_taked_args_handle(meta);
38353886
let args = handles.into_iter()
38363887
.map_to_string()
@@ -4193,11 +4244,13 @@ pub enum Emulate {
41934244

41944245
#[derive(Debug, Default)]
41954246
pub struct EmulateInfo {
4196-
pub exist_vars: Option<Vec<(Emulate, Var)>>,
4247+
/// ...needs arg system
4248+
pub exist_vars: Option<Vec<(Emulate, Var, bool)>>,
41974249
pub location: Option<(u32, u32)>,
41984250
pub diagnostic: Option<String>,
41994251
pub is_error: bool,
42004252
pub hover_doc: Option<String>,
4253+
pub in_other_line_first: bool,
42014254
}
42024255

42034256
struct HoverGuard<'a> { meta: &'a mut CompileMeta, handle: Option<Var> }
@@ -4534,7 +4587,8 @@ impl CompileMeta {
45344587
.map(|var| (Emulate::Const, var))
45354588
.chain(self.value_bind_pairs.keys().map(|var| (Emulate::Binder, var)))
45364589
.for_each(|(kind, var)| if printed.insert(var) {
4537-
vars.push((kind, var.clone()));
4590+
let value = Value::from(var.clone());
4591+
vars.push((kind, var.clone(), value.like_used_args_system(self)));
45384592
});
45394593
self.emulate(EmulateInfo { exist_vars: Some(vars), ..Default::default() });
45404594
}
@@ -4562,13 +4616,16 @@ impl CompileMeta {
45624616
let mut is_const = HashSet::new();
45634617
let mut bind_vars = bind.bind_names.take().unwrap()
45644618
.inspect(|(var, _)| _ = is_const.insert(*var))
4565-
.map(|(var, _)| (Emulate::ConstBind(handle.clone()), var.clone()))
4619+
.map(|(var, _)| {
4620+
let value = Value::from(var);
4621+
(Emulate::ConstBind(handle.clone()), var.clone(), value.like_used_args_system(self))
4622+
})
45664623
.collect::<Vec<_>>();
45674624

45684625
if let Some(pairs) = self.value_bind_pairs.get(handle) {
45694626
let naked_binds = pairs.keys()
45704627
.filter(|var| !is_const.contains(var))
4571-
.map(|var| (Emulate::NakedBind(handle.clone()), var.clone()));
4628+
.map(|var| (Emulate::NakedBind(handle.clone()), var.clone(), false));
45724629
bind_vars.extend(naked_binds);
45734630
}
45744631
bind_vars

0 commit comments

Comments
 (0)