Skip to content

Commit 3ab39fd

Browse files
committed
feat: support deep access
1 parent e0f39c5 commit 3ab39fd

File tree

7 files changed

+102
-72
lines changed

7 files changed

+102
-72
lines changed

src/lexer.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,22 +265,45 @@ impl Lexer {
265265
let ret = keyword("return");
266266
let assign = just('=').padded();
267267

268+
// obj = ID (prop)+ "="
269+
// fn = ID (prop | colon_op)
270+
// prop = (dot_op)+ ("(" | colon_op)
271+
// dot_op = "." ID
272+
// colon_op = ":" ID "("
273+
let colon_op = just(':')
274+
.ignore_then(ident())
275+
.then_ignore(just('('))
276+
.map(Op::Colon);
277+
278+
let dot_op = just('.')
279+
.ignore_then(ident().map(Op::Dot))
280+
.repeated()
281+
.at_least(1);
282+
283+
let prop = dot_op
284+
.then(choice((just('(').to(None), colon_op.map(Some))))
285+
.map(|(mut props, meth)| {
286+
if let Some(x) = meth {
287+
props.push(x)
288+
}
289+
Op::Deep(props)
290+
});
291+
268292
let dotted = ident()
269-
.then(choice((just('.').to(Kind::Dot), just(':').to(Kind::Colon))))
270-
.then(ident())
271-
.map(|((prefix, scope), name)| (Some(prefix), scope, name));
293+
.then(choice((prop, colon_op)))
294+
.map(|(prefix, op)| (prefix, op));
272295

273-
let expr = dotted.clone().then_ignore(assign);
296+
let expr = ident().then(dot_op).then_ignore(assign);
274297

275298
choice((
276299
triple.ignore_then(choice((tag, variant, comment.map(TagType::Comment)))),
277300
func.clone()
278301
.ignore_then(dotted)
279-
.map(|(prefix, kind, name)| TagType::Func { prefix, name, kind }),
302+
.map(|(prefix, op)| TagType::Func(prefix, op)),
280303
expr.then(func.or_not())
281-
.map(|((prefix, kind, name), is_func)| match is_func {
282-
Some(_) => TagType::Func { prefix, name, kind },
283-
None => TagType::Expr { prefix, name, kind },
304+
.map(|((prefix, op), is_fn)| match is_fn {
305+
Some(_) => TagType::Func(prefix, Op::Deep(op)),
306+
None => TagType::Expr(prefix, Op::Deep(op)),
284307
}),
285308
ret.ignore_then(ident().padded())
286309
.then_ignore(end())

src/lexer/token.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,12 @@ pub enum TagType {
1818
/// function one.two() end
1919
/// one.two = function() end
2020
/// ```
21-
Func {
22-
prefix: Option<String>,
23-
name: String,
24-
kind: Kind,
25-
},
21+
Func(String, Op),
2622
/// ```lua
2723
/// one = 1
2824
/// one.two = 12
2925
/// ```
30-
Expr {
31-
prefix: Option<String>,
32-
name: String,
33-
kind: Kind,
34-
},
26+
Expr(String, Op),
3527
/// ```lua
3628
/// ---@export <module>
3729
/// or
@@ -107,16 +99,29 @@ pub enum TagType {
10799
}
108100

109101
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
110-
pub enum Kind {
111-
Dot,
112-
Colon,
102+
pub enum Op {
103+
Deep(Vec<Op>),
104+
Dot(String),
105+
Colon(String),
113106
}
114107

115-
impl Kind {
116-
pub fn as_char(&self) -> char {
108+
impl Display for Op {
109+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117110
match self {
118-
Self::Dot => '.',
119-
Self::Colon => ':',
111+
Self::Deep(mixed) => {
112+
for mix in mixed {
113+
mix.fmt(f)?;
114+
}
115+
Ok(())
116+
}
117+
Self::Dot(dot) => {
118+
f.write_str(".")?;
119+
f.write_str(dot)
120+
}
121+
Self::Colon(colon) => {
122+
f.write_str(":")?;
123+
f.write_str(colon)
124+
}
120125
}
121126
}
122127
}

src/parser/tags/func.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use chumsky::{select, Parser};
22

33
use crate::{
4-
lexer::{Kind, Name, TagType, Ty},
4+
lexer::{Name, Op, TagType, Ty},
55
parser::{impl_parse, Prefix, See},
66
};
77

@@ -62,8 +62,7 @@ impl_parse!(Return, {
6262

6363
#[derive(Debug, Clone)]
6464
pub struct Func {
65-
pub name: String,
66-
pub kind: Kind,
65+
pub op: Op,
6766
pub prefix: Prefix,
6867
pub desc: Vec<String>,
6968
pub params: Vec<Param>,
@@ -81,14 +80,13 @@ impl_parse!(Func, {
8180
.then(Return::parse().repeated())
8281
.then(See::parse())
8382
.then(Usage::parse().or_not())
84-
.then(select! { TagType::Func { prefix, name, kind } => (prefix, name, kind) })
83+
.then(select! { TagType::Func(prefix, op) => (prefix, op) })
8584
.map(
86-
|(((((desc, params), returns), see), usage), (prefix, name, kind))| Self {
87-
name,
88-
kind,
85+
|(((((desc, params), returns), see), usage), (prefix, op))| Self {
86+
op,
8987
prefix: Prefix {
90-
left: prefix.clone(),
91-
right: prefix,
88+
left: Some(prefix.clone()),
89+
right: Some(prefix),
9290
},
9391
desc,
9492
params,

src/parser/tags/type.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
use chumsky::{select, Parser};
22

33
use crate::{
4-
lexer::{Kind, TagType, Ty},
4+
lexer::{Op, TagType, Ty},
55
parser::{impl_parse, Prefix, See},
66
};
77

88
use super::Usage;
99

1010
#[derive(Debug, Clone)]
1111
pub struct Type {
12-
pub prefix: Prefix,
13-
pub name: String,
1412
pub desc: (Vec<String>, Option<String>),
15-
pub kind: Kind,
13+
pub op: Op,
14+
pub prefix: Prefix,
1615
pub ty: Ty,
1716
pub see: See,
1817
pub usage: Option<Usage>,
@@ -26,16 +25,15 @@ impl_parse!(Type, {
2625
.then(select! { TagType::Type(ty, desc) => (ty, desc) })
2726
.then(See::parse())
2827
.then(Usage::parse().or_not())
29-
.then(select! { TagType::Expr { prefix, name, kind } => (prefix, name, kind) })
28+
.then(select! { TagType::Expr(prefix, op) => (prefix, op) })
3029
.map(
31-
|((((extract, (ty, desc)), see), usage), (prefix, name, kind))| Self {
30+
|((((extract, (ty, desc)), see), usage), (prefix, op))| Self {
3231
desc: (extract, desc),
3332
prefix: Prefix {
34-
left: prefix.clone(),
35-
right: prefix,
33+
left: Some(prefix.to_owned()),
34+
right: Some(prefix),
3635
},
37-
name,
38-
kind,
36+
op,
3937
ty,
4038
see,
4139
usage,

src/vimdoc/func.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,17 @@ impl ToDoc for FuncDoc {
1919
.join(", ");
2020

2121
format!(
22-
"{}{}{}({args})",
22+
"{}{}({args})",
2323
n.prefix.left.as_deref().unwrap_or_default(),
24-
n.kind.as_char(),
25-
n.name
24+
n.op
2625
)
2726
} else {
28-
format!(
29-
"{}{}{}()",
30-
n.prefix.left.as_deref().unwrap_or_default(),
31-
n.kind.as_char(),
32-
n.name
33-
)
27+
format!("{}{}()", n.prefix.left.as_deref().unwrap_or_default(), n.op)
3428
};
3529

3630
doc.push_str(&header!(
3731
name_with_param,
38-
&format!(
39-
"{}{}{}",
40-
n.prefix.right.as_deref().unwrap_or_default(),
41-
n.kind.as_char(),
42-
n.name,
43-
)
32+
&format!("{}{}", n.prefix.right.as_deref().unwrap_or_default(), n.op)
4433
));
4534

4635
if !n.desc.is_empty() {

src/vimdoc/type.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,8 @@ impl ToDoc for TypeDoc {
1111
let mut doc = String::new();
1212

1313
doc.push_str(&header!(
14-
&format!(
15-
"{}{}{}",
16-
n.prefix.left.as_deref().unwrap_or_default(),
17-
n.kind.as_char(),
18-
n.name
19-
),
20-
&format!(
21-
"{}{}{}",
22-
n.prefix.right.as_deref().unwrap_or_default(),
23-
n.kind.as_char(),
24-
n.name
25-
)
14+
&format!("{}{}", n.prefix.left.as_deref().unwrap_or_default(), n.op),
15+
&format!("{}{}", n.prefix.right.as_deref().unwrap_or_default(), n.op)
2616
));
2717

2818
let (extract, desc) = &n.desc;

tests/basic.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ CommentConfig *CommentConfig*
179179
#[test]
180180
fn functions() {
181181
let src = r#"
182-
local U = {}
182+
local U = { foo = {} }
183183
184184
---NOTE: Local functions are not part of the documentation
185185
---Multiply two integer and print it
@@ -232,6 +232,19 @@ fn functions() {
232232
---@param ... unknown
233233
function U.with_var_arg_end(x, ...) end
234234
235+
---Class method deep access
236+
---@return table
237+
function U.foo:bar()
238+
self.__index = self
239+
return setmetatable({}, self)
240+
end
241+
242+
---Method deep access
243+
---@return table
244+
function U.foo.baz()
245+
return U.foo:bar()
246+
end
247+
235248
return U
236249
"#;
237250

@@ -299,6 +312,20 @@ U.with_var_arg_end({x}, {...}) *U.with_var_arg_end*
299312
{...} (unknown)
300313
301314
315+
U.foo:bar() *U.foo:bar*
316+
Class method deep access
317+
318+
Returns: ~
319+
(table)
320+
321+
322+
U.foo.baz() *U.foo.baz*
323+
Method deep access
324+
325+
Returns: ~
326+
(table)
327+
328+
302329
"
303330
)
304331
}

0 commit comments

Comments
 (0)