Skip to content

Commit 9899b22

Browse files
committed
将const片段挪到bangls, 修复take时才能识别补全语句
1 parent e5d7ef9 commit 9899b22

File tree

8 files changed

+268
-31
lines changed

8 files changed

+268
-31
lines changed

syntax/vim/UltiSnips/mdtlbl.snippets

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ inline$1@ $2{
5151
$0
5252
}
5353
endsnippet
54-
snippet const "const value" w
55-
const $1 = ${2:()};
56-
endsnippet
5754
snippet take "take" w
5855
take ${1};
5956
endsnippet

syntax/vscode/support/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "mdtlbl",
33
"displayName": "mdtlbl",
44
"description": "Mindustry Logic Bang Lang syntax highlight for VSCode",
5-
"version": "1.0.12",
5+
"version": "1.0.13",
66
"engines": {
77
"vscode": "^1.80.0"
88
},
15.6 KB
Binary file not shown.

syntax/vscode/support/snippets/snippets.json

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,6 @@
9696
"}"
9797
]
9898
},
99-
"const value": {
100-
"prefix": "const",
101-
"description": "const value",
102-
"body": [
103-
"const $1 = ${2:()};"
104-
]
105-
},
10699
"take": {
107100
"prefix": "take",
108101
"description": "take",

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.10"
3+
version = "0.1.11"
44
edition = "2024"
55

66
[features]

tools/bangls/src/main.rs

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

1414
fn main() {
1515
main_loop().unwrap();
@@ -262,9 +262,10 @@ impl RequestHandler for request::Completion {
262262
let Some((top, src)) = ctx.try_parse_for_complete((line, col), &file) else {
263263
return Ok(None);
264264
};
265+
let on_line_first = on_line_first(&top);
265266
let infos = emulate(top, src);
266267

267-
let completes = generate_completes(&infos);
268+
let completes = generate_completes(&infos, on_line_first);
268269
let completes = lsp_types::CompletionResponse::Array(completes);
269270
Ok(Some(completes))
270271
}
@@ -317,8 +318,25 @@ impl RequestHandler for request::DocumentDiagnosticRequest {
317318
}
318319
}
319320

320-
fn generate_completes(infos: &[EmulateInfo]) -> Vec<CompletionItem> {
321-
let on_line_first = infos.iter().any(|it| it.in_other_line_first);
321+
fn solid_snippets(on_line_first: bool) -> impl Iterator<Item = CompletionItem> {
322+
[
323+
("const", "const($0)", "const $1 = ${2:($0)};"),
324+
].into_iter().map(move |(label, value, stmt)| {
325+
let snip = if on_line_first { stmt } else { value };
326+
327+
CompletionItem {
328+
label: label.into(),
329+
kind: Some(CompletionItemKind::KEYWORD),
330+
insert_text: Some(snip.into()),
331+
insert_text_format: Some(InsertTextFormat::SNIPPET),
332+
detail: Some(snip.into()),
333+
sort_text: Some(label.to_uppercase()),
334+
..Default::default()
335+
}
336+
})
337+
}
338+
339+
fn generate_completes(infos: &[EmulateInfo], on_line_first: bool) -> Vec<CompletionItem> {
322340
let infos = infos.iter()
323341
.filter_map(|it| it.exist_vars.as_ref());
324342
let full_count = infos.clone().count() as u32;
@@ -379,7 +397,7 @@ fn generate_completes(infos: &[EmulateInfo]) -> Vec<CompletionItem> {
379397
insert_text_format,
380398
..Default::default()
381399
}
382-
}).collect();
400+
}).chain(solid_snippets(on_line_first)).collect();
383401
items.sort_by(|a, b| {
384402
let a = a.sort_text.as_ref().unwrap_or(&a.label);
385403
let b = b.sort_text.as_ref().unwrap_or(&b.label);
@@ -388,6 +406,27 @@ fn generate_completes(infos: &[EmulateInfo]) -> Vec<CompletionItem> {
388406
items
389407
}
390408

409+
fn on_line_first(top: &Expand) -> bool {
410+
let mut on_line_first = false;
411+
let _ = walk::lines(top.iter(), |line| {
412+
if let syntax::LogicLine::Other(args) = line
413+
&& let Some(normal) = args.as_normal()
414+
&& let Some(syntax::Value::Var(tail)
415+
|syntax::Value::ValueBind(syntax::ValueBind(_, tail))
416+
|syntax::Value::ValueBindRef(syntax::ValueBindRef {
417+
bind_target: syntax::ValueBindRefTarget::NameBind(tail),
418+
..
419+
})) = normal.first()
420+
&& tail.ends_with(LSP_DEBUG)
421+
{
422+
on_line_first = true;
423+
return std::ops::ControlFlow::Break(());
424+
}
425+
std::ops::ControlFlow::Continue(())
426+
});
427+
on_line_first
428+
}
429+
391430
trait NotificationHandler: Notification {
392431
fn handle(ctx: &mut Ctx, param: Self::Params) -> Result<()>;
393432
}

tools/syntax/src/lib.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod builtins;
2+
pub mod walk;
23
#[cfg(test)]
34
mod tests;
45

@@ -710,7 +711,7 @@ impl BoolOpsExtend for bool {
710711
#[derive(Debug, PartialEq, Clone)]
711712
pub struct ValueBindRef {
712713
value: Box<Value>,
713-
bind_target: ValueBindRefTarget,
714+
pub bind_target: ValueBindRefTarget,
714715
}
715716
impl ValueBindRef {
716717
pub fn new(value: Box<Value>, bind_target: ValueBindRefTarget) -> Self {
@@ -3872,18 +3873,6 @@ impl Compile for LogicLine {
38723873
meta.push(lab.to_string().into())
38733874
},
38743875
Self::Other(args) => {
3875-
if meta.is_emulated && let Some(normal) = args.as_normal()
3876-
&& let Some(Value::Var(tail)
3877-
|Value::ValueBind(ValueBind(_, tail))
3878-
|Value::ValueBindRef(ValueBindRef { bind_target: ValueBindRefTarget::NameBind(tail), .. })
3879-
) = normal.first()
3880-
&& tail.ends_with(LSP_DEBUG)
3881-
{
3882-
meta.emulate(EmulateInfo {
3883-
in_other_line_first: true,
3884-
..Default::default()
3885-
});
3886-
}
38873876
let handles: Vec<Var> = args.into_taked_args_handle(meta);
38883877
let args = handles.into_iter()
38893878
.map_to_string()
@@ -4252,7 +4241,6 @@ pub struct EmulateInfo {
42524241
pub diagnostic: Option<String>,
42534242
pub is_error: bool,
42544243
pub hover_doc: Option<String>,
4255-
pub in_other_line_first: bool,
42564244
}
42574245

42584246
struct HoverGuard<'a> { meta: &'a mut CompileMeta, handle: Option<Var> }

tools/syntax/src/walk.rs

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
use std::ops::ControlFlow;
2+
3+
use either::Either;
4+
5+
use crate::{
6+
Args, ClosuredValue, CmpTree, Cmper, Const, ConstKey, ConstMatchPat, ConstMatchPatAtom, Goto,
7+
LogicLine, MatchPat, MatchPatAtom, Take, Value, ValueBind,
8+
};
9+
10+
pub fn line(line: &LogicLine, mut f: impl FnMut(&LogicLine) -> ControlFlow<()>) -> ControlFlow<()> {
11+
walk_internal(line, &mut |elem| {
12+
match elem {
13+
Internal::Line(logic_line) => f(logic_line),
14+
_ => ControlFlow::Continue(()),
15+
}
16+
})
17+
}
18+
19+
pub fn lines<'a>(lines: impl IntoIterator<Item = &'a LogicLine>, mut f: impl FnMut(&LogicLine) -> ControlFlow<()>) -> ControlFlow<()> {
20+
for line in lines {
21+
self::line(line, &mut f)?;
22+
}
23+
ControlFlow::Continue(())
24+
}
25+
26+
#[derive(Debug, Clone, Copy)]
27+
enum Internal<'a> {
28+
Value(&'a Value),
29+
Line(&'a LogicLine),
30+
Cmp(&'a CmpTree),
31+
Key(&'a ConstKey),
32+
MatchPatAtom(&'a MatchPatAtom),
33+
ConstMatchPatAtom(&'a ConstMatchPatAtom),
34+
}
35+
impl<'a> From<&'a ConstMatchPatAtom> for Internal<'a> {
36+
fn from(v: &'a ConstMatchPatAtom) -> Self {
37+
Self::ConstMatchPatAtom(v)
38+
}
39+
}
40+
impl<'a> From<&'a MatchPatAtom> for Internal<'a> {
41+
fn from(v: &'a MatchPatAtom) -> Self {
42+
Self::MatchPatAtom(v)
43+
}
44+
}
45+
impl<'a> From<&'a Box<ConstKey>> for Internal<'a> {
46+
fn from(v: &'a Box<ConstKey>) -> Self {
47+
Self::Key(v)
48+
}
49+
}
50+
impl<'a> From<&'a ConstKey> for Internal<'a> {
51+
fn from(v: &'a ConstKey) -> Self {
52+
Self::Key(v)
53+
}
54+
}
55+
impl<'a> From<&'a Box<CmpTree>> for Internal<'a> {
56+
fn from(v: &'a Box<CmpTree>) -> Self {
57+
Self::Cmp(v)
58+
}
59+
}
60+
impl<'a> From<&'a CmpTree> for Internal<'a> {
61+
fn from(v: &'a CmpTree) -> Self {
62+
Self::Cmp(v)
63+
}
64+
}
65+
impl<'a> From<&'a Box<Value>> for Internal<'a> {
66+
fn from(v: &'a Box<Value>) -> Self {
67+
Self::Value(v)
68+
}
69+
}
70+
impl<'a> From<&'a Value> for Internal<'a> {
71+
fn from(v: &'a Value) -> Self {
72+
Self::Value(v)
73+
}
74+
}
75+
76+
impl<'a> From<&'a LogicLine> for Internal<'a> {
77+
fn from(v: &'a LogicLine) -> Self {
78+
Self::Line(v)
79+
}
80+
}
81+
82+
fn walk_internal<'a>(elem: impl Into<Internal<'a>>, f: &mut impl FnMut(Internal<'_>) -> ControlFlow<()>) -> ControlFlow<()> {
83+
let elem = elem.into();
84+
f(elem)?;
85+
match elem {
86+
Internal::Value(value) => match value {
87+
Value::Var(_) | Value::ReprVar(_) | Value::ResultHandle | Value::Binder |
88+
Value::BuiltinFunc(_) => (),
89+
Value::ValueBind(ValueBind(value, _)) => walk_internal(value, f)?,
90+
Value::ValueBindRef(it) => walk_internal(&it.value, f)?,
91+
Value::ClosuredValue(it) => match it {
92+
ClosuredValue::Uninit { value, .. } => walk_internal(value, f)?,
93+
ClosuredValue::Inited { .. } | ClosuredValue::Empty => (),
94+
},
95+
Value::DExp(dexp) => walk_lines_internal(dexp.lines.iter(), f)?,
96+
Value::Cmper(Cmper(cmp)) => walk_internal(cmp.as_ref().value, f)?,
97+
},
98+
Internal::Line(logic_line) => match logic_line {
99+
LogicLine::Op(op) => {
100+
let crate::OpInfo { result, arg1, arg2, .. } = op.get_info();
101+
walk_internal(result, f)?;
102+
walk_internal(arg1, f)?;
103+
if let Some(arg2) = arg2 {
104+
walk_internal(arg2, f)?;
105+
}
106+
},
107+
LogicLine::Label(_) | LogicLine::NoOp | LogicLine::Ignore | LogicLine::ConstLeak(_) => (),
108+
LogicLine::Goto(Goto(_var, cmp)) => walk_internal(cmp, f)?,
109+
LogicLine::Other(args) => walk_args_internal(args, f)?,
110+
LogicLine::Expand(expand) => walk_lines_internal(expand.iter(), f)?,
111+
LogicLine::InlineBlock(inline_block) => walk_lines_internal(inline_block.iter(), f)?,
112+
LogicLine::Select(select) => {
113+
walk_internal(&select.0, f)?;
114+
walk_lines_internal(select.1.iter(), f)?;
115+
},
116+
LogicLine::GSwitch(gswitch) => {
117+
walk_internal(&gswitch.value, f)?;
118+
walk_lines_internal(gswitch.extra.iter(), f)?;
119+
for (case, body) in gswitch.cases.iter() {
120+
match case {
121+
crate::GSwitchCase::Catch { to, .. } => {
122+
if let Some(to) = to {
123+
walk_internal(to, f)?;
124+
}
125+
},
126+
crate::GSwitchCase::Normal { ids, guard, .. } => {
127+
walk_args_internal(&ids.value, f)?;
128+
if let Some(guard) = guard {
129+
walk_internal(guard, f)?;
130+
}
131+
},
132+
}
133+
walk_lines_internal(body.iter(), f)?;
134+
}
135+
},
136+
LogicLine::Take(Take(k, v)) |
137+
LogicLine::Const(Const(k, v, _)) => {
138+
walk_internal(k, f)?;
139+
walk_internal(v, f)?;
140+
},
141+
LogicLine::SetResultHandle(value, _) => walk_internal(value, f)?,
142+
LogicLine::SetArgs(args) => walk_args_internal(args, f)?,
143+
LogicLine::ArgsRepeat(it) => {
144+
if let Either::Right(count) = it.count.as_ref().value {
145+
walk_internal(count, f)?;
146+
}
147+
walk_lines_internal(it.block.iter(), f)?;
148+
},
149+
LogicLine::Match(it) => {
150+
walk_args_internal(&it.args, f)?;
151+
for (pats, body) in it.cases() {
152+
walk_matchpat_internal(pats, f)?;
153+
walk_lines_internal(body.iter(), f)?;
154+
}
155+
},
156+
LogicLine::ConstMatch(it) => {
157+
walk_args_internal(it.args(), f)?;
158+
for (pats, body) in it.cases() {
159+
walk_cmatchpat_internal(pats, f)?;
160+
walk_lines_internal(body.iter(), f)?;
161+
}
162+
},
163+
},
164+
Internal::Cmp(cmp) => match cmp {
165+
CmpTree::Deps(inline_block, cmp_tree) => {
166+
walk_lines_internal(inline_block.iter(), f)?;
167+
walk_internal(cmp_tree, f)?;
168+
},
169+
CmpTree::Expand(_var, cmp_tree) => {
170+
walk_internal(cmp_tree, f)?;
171+
},
172+
CmpTree::Or(cmp_tree, cmp_tree1) |
173+
CmpTree::And(cmp_tree, cmp_tree1) => {
174+
walk_internal(cmp_tree, f)?;
175+
walk_internal(cmp_tree1, f)?;
176+
},
177+
CmpTree::Atom(_) => (),
178+
},
179+
Internal::Key(key) => match key {
180+
ConstKey::Var(_) | ConstKey::Unused(_) => (),
181+
ConstKey::ValueBind(ValueBind(value, _)) => walk_internal(value, f)?,
182+
}
183+
Internal::MatchPatAtom(match_pat_atom) => {
184+
for value in &match_pat_atom.pattern {
185+
walk_internal(value, f)?;
186+
}
187+
},
188+
Internal::ConstMatchPatAtom(const_match_pat_atom) => {
189+
for value in const_match_pat_atom.pattern.as_ref().map_right(std::slice::from_ref).into_iter() {
190+
walk_internal(value, f)?;
191+
}
192+
},
193+
}
194+
ControlFlow::Continue(())
195+
}
196+
197+
fn walk_lines_internal<'a>(lines: impl IntoIterator<Item = &'a LogicLine>, f: &mut impl FnMut(Internal<'_>) -> ControlFlow<()>) -> ControlFlow<()> {
198+
lines.into_iter().try_for_each(|line| walk_internal(line, f))
199+
}
200+
201+
fn walk_args_internal(args: &Args, f: &mut impl FnMut(Internal<'_>) -> ControlFlow<()>) -> ControlFlow<()> {
202+
match args {
203+
Args::Normal(values) => values.iter().chain(const { &Vec::new() }),
204+
Args::Expanded(values, values1) => values.iter().chain(values1),
205+
}.try_for_each(|value| walk_internal(value, f))
206+
}
207+
208+
fn walk_matchpat_internal(pats: &MatchPat, f: &mut impl FnMut(Internal<'_>) -> ControlFlow<()>) -> ControlFlow<()> {
209+
match pats {
210+
MatchPat::Normal(match_pat_atoms) => match_pat_atoms.iter().chain(const { &Vec::new() }),
211+
MatchPat::Expanded(match_pat_atoms, match_pat_atoms1) => match_pat_atoms.iter().chain(match_pat_atoms1),
212+
}.try_for_each(|value| walk_internal(value, f))
213+
}
214+
215+
fn walk_cmatchpat_internal(pats: &ConstMatchPat, f: &mut impl FnMut(Internal<'_>) -> ControlFlow<()>) -> ControlFlow<()> {
216+
match pats {
217+
ConstMatchPat::Normal(match_pat_atoms) => match_pat_atoms.iter().chain(const { &Vec::new() }),
218+
ConstMatchPat::Expanded(match_pat_atoms, _, match_pat_atoms1) => match_pat_atoms.iter().chain(match_pat_atoms1),
219+
}.try_for_each(|value| walk_internal(value, f))
220+
}

0 commit comments

Comments
 (0)