Skip to content

Commit 57cfa2c

Browse files
authored
Merge pull request #100 from Pivot-Studio/feat/typehint
Feat/typehint
2 parents f6ae49e + 0c4c023 commit 57cfa2c

File tree

12 files changed

+186
-36
lines changed

12 files changed

+186
-36
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ jobs:
168168
mkdir -p ${{ matrix.config.debdir }}/pl
169169
cp -r ${{ matrix.config.dir }}/* ${{ matrix.config.debdir }}/pl
170170
rm ${{ matrix.config.debdir }}/pl/plc
171-
172171
- uses: Pivot-Studio/build-deb-action@master
173172
if: ${{ matrix.config.os == 'ubuntu-latest' }}
174173
id: build-deb
@@ -264,15 +263,12 @@ jobs:
264263
# Optional - multiline string.
265264
depends_on: |
266265
"llvm@14"
267-
268266
# Custom install command for your formula.
269267
# Required - string.
270268
install: |
271269
lib.install Dir["./planglib"]
272270
lib.install "./libvm.a"
273271
bin.install "./plc"
274-
275-
276272
# Custom test command for your formula so you can run `brew test`.
277273
# Optional - string.
278274
# test: 'assert_match("my script output", shell_output("my-script-command"))'
@@ -312,4 +308,4 @@ jobs:
312308

313309
# Logs debugging info to console.
314310
# Default is shown - boolean.
315-
debug: true
311+
debug: true

deb/DEBIAN/postinst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ if [ "$1" = configure ]; then
1717
echo "see https://apt.llvm.org/ for more details"
1818
echo "-------------------------------------------------------------------"
1919
echo "${NC}"
20-
fi
20+
fi

src/ast/accumulators.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::{cell::RefCell, path::PathBuf, rc::Rc};
22

33
use lsp_types::{
4-
CompletionItem, GotoDefinitionResponse, Hover, InlayHint, Location, SemanticTokens, TextEdit,
4+
CompletionItem, DocumentSymbol, GotoDefinitionResponse, Hover, InlayHint, Location,
5+
SemanticTokens, TextEdit,
56
};
67

78
use super::ctx::PLDiag;
@@ -31,3 +32,5 @@ pub struct ModBuffer(PathBuf);
3132
pub struct PLFormat(Vec<TextEdit>);
3233
#[salsa::accumulator]
3334
pub struct Hints(Vec<InlayHint>);
35+
#[salsa::accumulator]
36+
pub struct DocSymbols(Vec<DocumentSymbol>);

src/ast/compiler.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub enum ActionType {
9999
Fmt,
100100
LspFmt,
101101
Hint,
102+
DocSymbol,
102103
}
103104

104105
#[cfg(feature = "jit")]

src/ast/ctx.rs

Lines changed: 96 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use lsp_types::CompletionItem;
2626
use lsp_types::CompletionItemKind;
2727
use lsp_types::Diagnostic;
2828
use lsp_types::DiagnosticSeverity;
29+
use lsp_types::DocumentSymbol;
2930
use lsp_types::GotoDefinitionResponse;
3031
use lsp_types::Hover;
3132
use lsp_types::HoverContents;
@@ -35,6 +36,7 @@ use lsp_types::InsertTextFormat;
3536
use lsp_types::Location;
3637
use lsp_types::MarkedString;
3738
use lsp_types::SemanticTokenType;
39+
use lsp_types::SymbolKind;
3840
use lsp_types::Url;
3941
use rustc_hash::FxHashMap;
4042
use rustc_hash::FxHashSet;
@@ -95,6 +97,7 @@ pub struct Ctx<'a, 'ctx> {
9597
pub ditypes_placeholder: Rc<RefCell<FxHashMap<String, RefCell<Vec<MemberType<'ctx>>>>>>, // hold the generated debug info type place holder
9698
pub ditypes: Rc<RefCell<FxHashMap<String, DIType<'ctx>>>>, // hold the generated debug info type
9799
pub hints: Rc<RefCell<Box<Vec<InlayHint>>>>,
100+
pub doc_symbols: Rc<RefCell<Box<Vec<DocumentSymbol>>>>,
98101
pub semantic_tokens_builder: Rc<RefCell<Box<SemanticTokensBuilder>>>, // semantic token builder
99102
pub goto_def: Rc<Cell<Option<GotoDefinitionResponse>>>, // hold the goto definition result
100103
pub completion_items: Rc<Cell<Vec<CompletionItem>>>, // hold the completion items
@@ -493,7 +496,7 @@ impl PLType {
493496
PLType::PRIMITIVE(pri) => pri.get_name(),
494497
PLType::ARR(arr) => format!("[{} * {}]", arr.element_type.get_name(), arr.size),
495498
PLType::VOID => "void".to_string(),
496-
PLType::POINTER(p) => "&".to_string() + &p.get_name(),
499+
PLType::POINTER(p) => "*".to_string() + &p.get_name(),
497500
}
498501
}
499502

@@ -792,6 +795,19 @@ impl Field {
792795
offset + debug_type.get_size_in_bits(),
793796
)
794797
}
798+
pub fn get_doc_symbol<'a, 'ctx>(&self, ctx: &Ctx<'a, 'ctx>) -> DocumentSymbol {
799+
#[allow(deprecated)]
800+
DocumentSymbol {
801+
name: self.name.clone(),
802+
detail: Some(self.pltype.get_type(ctx).unwrap().get_name()),
803+
kind: SymbolKind::FIELD,
804+
tags: None,
805+
deprecated: None,
806+
range: self.range.to_diag_range(),
807+
selection_range: self.range.to_diag_range(),
808+
children: None,
809+
}
810+
}
795811
}
796812

797813
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -804,6 +820,7 @@ pub struct FNType {
804820
pub range: Range,
805821
pub refs: Rc<RefCell<Vec<Location>>>,
806822
pub doc: Vec<Box<NodeEnum>>,
823+
pub method: bool,
807824
}
808825

809826
impl TryFrom<PLType> for FNType {
@@ -838,6 +855,47 @@ impl FNType {
838855
.add_function(&self.llvmname, fn_type, Some(Linkage::External));
839856
fn_value
840857
}
858+
pub fn get_doc_symbol(&self) -> DocumentSymbol {
859+
#[allow(deprecated)]
860+
DocumentSymbol {
861+
name: if self.method {
862+
self.name.split("::").last().unwrap().to_string()
863+
} else {
864+
self.name.clone()
865+
},
866+
detail: Some(self.get_signature()),
867+
kind: if self.method {
868+
SymbolKind::METHOD
869+
} else {
870+
SymbolKind::FUNCTION
871+
},
872+
tags: None,
873+
deprecated: None,
874+
range: self.range.to_diag_range(),
875+
selection_range: self.range.to_diag_range(),
876+
children: None,
877+
}
878+
}
879+
pub fn get_signature(&self) -> String {
880+
let mut params = String::new();
881+
if !self.param_name.is_empty() {
882+
if !self.method {
883+
params += &format!(
884+
"{}: {}",
885+
self.param_name[0],
886+
self.param_pltypes[0].get_name()
887+
);
888+
}
889+
for i in 1..self.param_name.len() {
890+
params += &format!(
891+
", {}: {}",
892+
self.param_name[i],
893+
self.param_pltypes[i].get_name()
894+
);
895+
}
896+
}
897+
format!("fn ({}) {}", params, self.ret_pltype.get_name())
898+
}
841899
}
842900

843901
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -918,6 +976,24 @@ impl STType {
918976
pub fn get_st_full_name(&self) -> String {
919977
format!("{}..{}", self.path, self.name)
920978
}
979+
pub fn get_doc_symbol<'a, 'ctx>(&self, ctx: &Ctx<'a, 'ctx>) -> DocumentSymbol {
980+
let children: Vec<DocumentSymbol> = self
981+
.ordered_fields
982+
.iter()
983+
.map(|order_field| order_field.get_doc_symbol(ctx))
984+
.collect();
985+
#[allow(deprecated)]
986+
DocumentSymbol {
987+
name: self.name.clone(),
988+
detail: None,
989+
kind: SymbolKind::STRUCT,
990+
tags: None,
991+
deprecated: None,
992+
range: self.range.to_diag_range(),
993+
selection_range: self.range.to_diag_range(),
994+
children: Some(children),
995+
}
996+
}
921997
}
922998

923999
fn add_primitive_types<'a, 'ctx>(ctx: &mut Ctx<'a, 'ctx>) {
@@ -1082,6 +1158,7 @@ impl<'a, 'ctx> Ctx<'a, 'ctx> {
10821158
lspparams: completion,
10831159
refs: Rc::new(Cell::new(None)),
10841160
hints: Rc::new(RefCell::new(Box::new(vec![]))),
1161+
doc_symbols: Rc::new(RefCell::new(Box::new(vec![]))),
10851162
semantic_tokens_builder: Rc::new(RefCell::new(Box::new(SemanticTokensBuilder::new(
10861163
src_file_path.to_string(),
10871164
)))),
@@ -1129,6 +1206,7 @@ impl<'a, 'ctx> Ctx<'a, 'ctx> {
11291206
lspparams: self.lspparams.clone(),
11301207
refs: self.refs.clone(),
11311208
hints: self.hints.clone(),
1209+
doc_symbols: self.doc_symbols.clone(),
11321210
semantic_tokens_builder: self.semantic_tokens_builder.clone(),
11331211
goto_def: self.goto_def.clone(),
11341212
completion_items: self.completion_items.clone(),
@@ -1227,7 +1305,7 @@ impl<'a, 'ctx> Ctx<'a, 'ctx> {
12271305
&mut self,
12281306
name: String,
12291307
pv: PointerValue<'ctx>,
1230-
tp: PLType,
1308+
pltype: PLType,
12311309
range: Range,
12321310
is_const: bool,
12331311
) -> Result<(), PLDiag> {
@@ -1237,9 +1315,10 @@ impl<'a, 'ctx> Ctx<'a, 'ctx> {
12371315
let refs = Rc::new(RefCell::new(vec![]));
12381316
if is_const {
12391317
self.plmod
1240-
.add_global_symbol(name, tp, range, refs.clone())?;
1318+
.add_global_symbol(name, pltype.clone(), range, refs.clone())?;
12411319
} else {
1242-
self.table.insert(name, (pv, tp, range, refs.clone()));
1320+
self.table
1321+
.insert(name, (pv, pltype.clone(), range, refs.clone()));
12431322
}
12441323
self.send_if_go_to_def(range, range, self.plmod.path.clone());
12451324
self.set_if_refs(refs, range);
@@ -1299,14 +1378,25 @@ impl<'a, 'ctx> Ctx<'a, 'ctx> {
12991378
set.insert(name);
13001379
}
13011380

1302-
pub fn add_type(&mut self, name: String, tp: PLType, range: Range) -> Result<(), PLDiag> {
1381+
pub fn add_type(&mut self, name: String, pltype: PLType, range: Range) -> Result<(), PLDiag> {
13031382
if self.plmod.types.contains_key(&name) {
13041383
return Err(self.add_err(range, ErrorCode::REDEFINE_TYPE));
13051384
}
13061385
self.send_if_go_to_def(range, range, self.plmod.path.clone());
1307-
self.plmod.types.insert(name, tp.clone());
1386+
self.plmod.types.insert(name, pltype.clone());
13081387
Ok(())
13091388
}
1389+
pub fn add_doc_symbols(&mut self, pltype: PLType) {
1390+
match &pltype {
1391+
PLType::FN(f) => {
1392+
if !f.method {
1393+
self.doc_symbols.borrow_mut().push(f.get_doc_symbol())
1394+
}
1395+
}
1396+
PLType::STRUCT(st) => self.doc_symbols.borrow_mut().push(st.get_doc_symbol(self)),
1397+
_ => {}
1398+
}
1399+
}
13101400

13111401
pub fn add_err(&self, range: Range, code: ErrorCode) -> PLDiag {
13121402
let dia = PLDiag::new_error(range, code);

src/ast/node/function.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ impl Node for FuncDefNode {
105105
}
106106
}
107107
ctx.push_semantic_token(self.typenode.ret.range(), SemanticTokenType::TYPE, 0);
108+
let res = ctx.get_type(self.typenode.id.as_str(), self.range);
109+
if res.is_err() {
110+
let diag = res.unwrap_err();
111+
ctx.add_diag(diag.clone());
112+
return Err(diag);
113+
}
114+
let pltype = res.unwrap().clone();
108115
if let Some(body) = self.body.as_mut() {
109116
let subroutine_type = ctx.dibuilder.create_subroutine_type(
110117
ctx.diunit.get_file(),
@@ -126,15 +133,7 @@ impl Node for FuncDefNode {
126133
false,
127134
);
128135
// add function
129-
let func;
130-
let res = ctx.get_type(self.typenode.id.as_str(), self.range);
131-
if res.is_err() {
132-
let diag = res.unwrap_err();
133-
ctx.add_diag(diag.clone());
134-
return Err(diag);
135-
}
136-
let fu = res.unwrap();
137-
func = match fu {
136+
let func = match &pltype {
138137
PLType::FN(fu) => fu.get_or_insert_fn(ctx),
139138
_ => return Ok((None, None, TerminatorEnum::NONE)),
140139
};
@@ -238,9 +237,9 @@ impl Node for FuncDefNode {
238237
}
239238
ctx.nodebug_builder.position_at_end(allocab);
240239
ctx.nodebug_builder.build_unconditional_branch(entry);
241-
return Ok((None, None, TerminatorEnum::NONE));
240+
return Ok((None, Some(pltype.clone()), TerminatorEnum::NONE));
242241
}
243-
Ok((None, None, TerminatorEnum::NONE))
242+
Ok((None, Some(pltype.clone()), TerminatorEnum::NONE))
244243
}
245244
}
246245

@@ -399,6 +398,7 @@ impl FuncTypeNode {
399398
} else {
400399
ctx.plmod.get_full_name(&self.id)
401400
},
401+
method: receiver.is_some(),
402402
};
403403
if let Some(mut receiver) = receiver {
404404
receiver
@@ -411,7 +411,8 @@ impl FuncTypeNode {
411411
let res = ftp.get_or_insert_fn(ctx);
412412
let pltype = PLType::FN(ftp);
413413
ctx.set_if_refs_tp(&pltype, self.range);
414-
ctx.add_type(self.id.clone(), pltype, self.range)?;
414+
ctx.add_type(self.id.clone(), pltype.clone(), self.range)?;
415+
ctx.add_doc_symbols(pltype);
415416
Ok(res)
416417
}
417418
}

src/ast/node/implement.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::*;
22
use crate::{ast::ctx::Ctx, utils::read_config::enter};
33
use internal_macro::range;
4+
use lsp_types::{DocumentSymbol, SymbolKind};
45

56
#[range]
67
#[derive(Clone, PartialEq, Eq, Debug)]
@@ -33,9 +34,34 @@ impl Node for ImplNode {
3334
}
3435
fn emit<'a, 'ctx>(&'a mut self, ctx: &mut Ctx<'a, 'ctx>) -> NodeResult<'ctx> {
3536
_ = self.target.emit_highlight(ctx);
37+
let mut method_docsymbols = vec![];
3638
for method in &mut self.methods {
37-
_ = method.emit(ctx);
39+
let res = method.emit(ctx);
40+
if res.is_err() {
41+
continue;
42+
}
43+
let (_, pltype, _) = res.unwrap();
44+
if pltype.is_none() {
45+
continue;
46+
}
47+
let f = match pltype.unwrap() {
48+
PLType::FN(f) => f,
49+
_ => continue,
50+
};
51+
method_docsymbols.push(f.get_doc_symbol());
3852
}
53+
#[allow(deprecated)]
54+
let docsymbol = DocumentSymbol {
55+
name: format!("impl {}", self.target.format(0, "")),
56+
detail: None,
57+
kind: SymbolKind::OBJECT,
58+
tags: None,
59+
deprecated: None,
60+
range: self.range.to_diag_range(),
61+
selection_range: self.range.to_diag_range(),
62+
children: Some(method_docsymbols),
63+
};
64+
ctx.doc_symbols.borrow_mut().push(docsymbol);
3965
Ok((None, None, TerminatorEnum::NONE))
4066
}
4167
}

src/ast/node/program.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ pub fn emit_file(db: &dyn Db, params: ProgramEmitParam) -> ModWrapper {
300300
let hints = ctx.hints.take();
301301
Hints::push(db, *hints);
302302
}
303+
if action == ActionType::DocSymbol {
304+
let docs = ctx.doc_symbols.take();
305+
DocSymbols::push(db, *docs);
306+
}
303307
if let Some(c) = ctx.goto_def.take() {
304308
GotoDef::push(db, c);
305309
}

src/ast/node/types.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl StructDefNode {
315315
.collect::<Vec<_>>(),
316316
false,
317317
);
318-
let stu = PLType::STRUCT(STType {
318+
let pltype = PLType::STRUCT(STType {
319319
name: name.to_string(),
320320
path: ctx.plmod.path.clone(),
321321
fields,
@@ -325,8 +325,9 @@ impl StructDefNode {
325325
doc: self.doc.clone(),
326326
methods: FxHashMap::default(),
327327
});
328-
ctx.set_if_refs_tp(&stu, self.range);
329-
_ = ctx.plmod.replace_type(name, stu.clone());
328+
ctx.set_if_refs_tp(&pltype, self.range);
329+
_ = ctx.plmod.replace_type(name, pltype.clone());
330+
ctx.add_doc_symbols(pltype);
330331
ctx.save_if_comment_doc_hover(self.range, Some(self.doc.clone()));
331332
Ok(())
332333
}

0 commit comments

Comments
 (0)