Skip to content

Commit 0d8e794

Browse files
authored
parser,ast: add vls info to support improvements to vls goto definition (#25492)
1 parent abfd857 commit 0d8e794

6 files changed

Lines changed: 190 additions & 5 deletions

File tree

‎vlib/v/ast/table.v‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module ast
66

77
import v.cflag
88
import v.util
9+
import v.token
910

1011
@[heap; minify]
1112
pub struct UsedFeatures {
@@ -87,6 +88,7 @@ pub mut:
8788
gostmts int // how many `go` statements there were in the parsed files.
8889
// When table.gostmts > 0, __VTHREADS__ is defined, which can be checked with `$if threads {`
8990
enum_decls map[string]EnumDecl
91+
vls_info map[string]VLSInfo
9092
module_deprecated map[string]bool
9193
module_attrs map[string][]Attr // module attributes
9294
builtin_pub_fns map[string]bool
@@ -111,6 +113,14 @@ pub mut:
111113
c_str string
112114
}
113115

116+
pub struct VLSInfo {
117+
pub mut:
118+
pos token.Pos
119+
pre_comments []Comment
120+
comments []Comment
121+
end_comments []Comment
122+
}
123+
114124
// used by vls to avoid leaks
115125
// TODO: remove manual memory management
116126
@[unsafe]
@@ -2765,3 +2775,8 @@ pub fn (mut t Table) get_veb_result_type_idx() int {
27652775
t.veb_res_idx_cache = t.find_type('veb.Result')
27662776
return t.veb_res_idx_cache
27672777
}
2778+
2779+
@[inline]
2780+
pub fn (mut t Table) register_vls_info(key string, val VLSInfo) {
2781+
t.vls_info[key] = val
2782+
}

‎vlib/v/parser/enum.v‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,24 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
253253

254254
if !already_exists {
255255
p.table.register_enum_decl(enum_decl)
256+
if p.pref.is_vls {
257+
key := 'enum_${name}'
258+
val := ast.VLSInfo{
259+
pos: typ_pos
260+
comments: enum_decl_comments
261+
}
262+
p.table.register_vls_info(key, val)
263+
for f in fields {
264+
f_key := 'enum_${name}.${f.name}'
265+
f_val := ast.VLSInfo{
266+
pos: f.pos
267+
pre_comments: f.pre_comments
268+
comments: f.comments
269+
end_comments: f.next_comments
270+
}
271+
p.table.register_vls_info(f_key, f_val)
272+
}
273+
}
256274
}
257275
return enum_decl
258276
}

‎vlib/v/parser/fn.v‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,19 @@ run them via `v file.v` instead',
753753
p.table.register_fn_generic_types(fn_decl.fkey())
754754
}
755755
p.label_names = []
756+
if p.pref.is_vls {
757+
type_str := if (is_method || is_static_type_method) && rec.typ != ast.no_type {
758+
p.table.sym(rec.typ.idx_type()).name.all_after_last('.')
759+
} else {
760+
''
761+
}
762+
key := 'fn_${p.mod}[${type_str}]${short_fn_name}'
763+
val := ast.VLSInfo{
764+
pos: fn_decl.pos
765+
comments: fn_decl.comments // TODO: we need comment just before fn decl
766+
}
767+
p.table.register_vls_info(key, val)
768+
}
756769
return fn_decl
757770
}
758771

‎vlib/v/parser/parser.v‎

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2572,14 +2572,26 @@ fn (mut p Parser) const_decl() ast.ConstDecl {
25722572
} else {
25732573
comments << p.eat_comments(same_line: true)
25742574
}
2575-
return ast.ConstDecl{
2575+
const_decl := ast.ConstDecl{
25762576
pos: start_pos.extend_with_last_line(const_pos, p.prev_tok.line_nr)
25772577
fields: fields
25782578
is_pub: is_pub
25792579
end_comments: comments
25802580
is_block: is_block
25812581
attrs: attrs
25822582
}
2583+
if p.pref.is_vls {
2584+
for f in fields {
2585+
key := 'const_${f.name}'
2586+
val := ast.VLSInfo{
2587+
pos: f.pos
2588+
comments: f.comments
2589+
end_comments: f.end_comments
2590+
}
2591+
p.table.register_vls_info(key, val)
2592+
}
2593+
}
2594+
return const_decl
25832595
}
25842596

25852597
fn (mut p Parser) return_stmt() ast.Return {
@@ -2732,14 +2744,29 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
27322744
if is_block {
27332745
p.check(.rpar)
27342746
}
2735-
return ast.GlobalDecl{
2747+
global_decl := ast.GlobalDecl{
27362748
pos: start_pos.extend(p.prev_tok.pos())
27372749
mod: p.mod
27382750
fields: fields
27392751
end_comments: comments
27402752
is_block: is_block
27412753
attrs: attrs
27422754
}
2755+
if p.pref.is_vls {
2756+
for f in fields {
2757+
mut key := 'global_${f.name}'
2758+
val := ast.VLSInfo{
2759+
pos: global_decl.pos
2760+
comments: f.comments
2761+
}
2762+
p.table.register_vls_info(key, val)
2763+
2764+
// register another `module specific global`
2765+
key = 'global_${p.prepend_mod(f.name)}'
2766+
p.table.register_vls_info(key, val)
2767+
}
2768+
}
2769+
return global_decl
27432770
}
27442771

27452772
fn source_name(name string) string {
@@ -2802,7 +2829,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
28022829
type_pos = type_pos.extend(p.tok.pos())
28032830
comments = p.eat_comments(same_line: true)
28042831
p.attrs = []
2805-
return ast.FnTypeDecl{
2832+
fn_type_decl := ast.FnTypeDecl{
28062833
name: fn_name
28072834
mod: p.mod
28082835
is_pub: is_pub
@@ -2814,6 +2841,15 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
28142841
attrs: attrs
28152842
is_markused: attrs.contains('markused')
28162843
}
2844+
if p.pref.is_vls {
2845+
key := 'fntype_${fn_name}'
2846+
val := ast.VLSInfo{
2847+
pos: decl_pos
2848+
comments: comments
2849+
}
2850+
p.table.register_vls_info(key, val)
2851+
}
2852+
return fn_type_decl
28172853
}
28182854
sum_variants << p.parse_sum_type_variants()
28192855
// type SumType = Aaa | Bbb | Ccc
@@ -2862,6 +2898,13 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
28622898
is_markused: attrs.contains('markused')
28632899
}
28642900
p.table.register_sumtype(node)
2901+
if p.pref.is_vls {
2902+
key := 'sumtype_${p.prepend_mod(name)}'
2903+
val := ast.VLSInfo{
2904+
pos: node.pos
2905+
}
2906+
p.table.register_vls_info(key, val)
2907+
}
28652908
return node
28662909
}
28672910
// type MyType = int
@@ -2905,7 +2948,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
29052948
}
29062949
comments = sum_variants[0].end_comments.clone()
29072950
p.attrs = []
2908-
return ast.AliasTypeDecl{
2951+
alias_type_decl := ast.AliasTypeDecl{
29092952
name: name
29102953
is_pub: is_pub
29112954
typ: idx
@@ -2916,6 +2959,15 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
29162959
is_markused: attrs.contains('markused')
29172960
attrs: attrs
29182961
}
2962+
if p.pref.is_vls {
2963+
key := 'aliastype_${p.prepend_mod(name)}'
2964+
val := ast.VLSInfo{
2965+
pos: alias_type_decl.pos
2966+
comments: comments
2967+
}
2968+
p.table.register_vls_info(key, val)
2969+
}
2970+
return alias_type_decl
29192971
}
29202972

29212973
fn (mut p Parser) assoc() ast.Assoc {

‎vlib/v/parser/struct.v‎

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
466466
return ast.StructDecl{}
467467
}
468468
p.expr_mod = ''
469-
return ast.StructDecl{
469+
struct_decl := ast.StructDecl{
470470
name: name
471471
scoped_name: scoped_name
472472
is_pub: is_pub
@@ -489,6 +489,24 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
489489
is_implements: is_implements
490490
implements_types: implements_types
491491
}
492+
if p.pref.is_vls {
493+
key := 'struct_${name}'
494+
val := ast.VLSInfo{
495+
pos: struct_decl.pos
496+
pre_comments: pre_comments
497+
}
498+
p.table.register_vls_info(key, val)
499+
for f in ast_fields {
500+
f_key := 'struct_${name}.${f.name}'
501+
f_val := ast.VLSInfo{
502+
pos: f.pos
503+
pre_comments: f.pre_comments
504+
comments: f.comments
505+
}
506+
p.table.register_vls_info(f_key, f_val)
507+
}
508+
}
509+
return struct_decl
492510
}
493511

494512
fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind, is_option bool) ast.StructInit {
@@ -879,5 +897,21 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
879897
name_pos: name_pos
880898
}
881899
p.table.register_interface(res)
900+
if p.pref.is_vls {
901+
key := 'interface_${interface_name}'
902+
val := ast.VLSInfo{
903+
pos: pos
904+
pre_comments: pre_comments
905+
}
906+
p.table.register_vls_info(key, val)
907+
for f in fields {
908+
f_key := 'interface_${interface_name}.${f.name}'
909+
f_val := ast.VLSInfo{
910+
pos: f.pos
911+
comments: f.comments
912+
}
913+
p.table.register_vls_info(f_key, f_val)
914+
}
915+
}
882916
return res
883917
}

‎vlib/v/parser/v_parser_test.v‎

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,56 @@ fn test_parse_with_stdout() {
314314
println(@LOCATION)
315315
parse(.stdout)!
316316
}
317+
318+
fn test_parse_vls_info() {
319+
println(@LOCATION)
320+
source_text := '
321+
const my_const = 123
322+
struct MyS {
323+
a int
324+
}
325+
interface MyInterface {
326+
method() string
327+
}
328+
__global my_global = 456
329+
type MyAlias = u8
330+
type MySum = u8 | u16
331+
type MyFnType = fn (msg &char, arg usize)
332+
333+
fn (mut k MyS) add(val int) {
334+
k.a += val
335+
}
336+
337+
fn foo() int {
338+
f := 23
339+
return 10+4+f
340+
}
341+
fn ff(x int) {}
342+
343+
fn main() {
344+
ff(12 + 3)
345+
x := 10
346+
bar(5+7)
347+
ff(8+x)
348+
}
349+
'
350+
mut table := ast.new_table()
351+
vpref := &pref.Preferences{
352+
enable_globals: true
353+
is_vls: true
354+
}
355+
mut prog := parse_text(source_text, '', mut table, .skip_comments, vpref)
356+
mut checker_ := checker.new_checker(table, vpref)
357+
checker_.check(mut prog)
358+
359+
assert 'const_main.my_const' in table.vls_info
360+
assert 'struct_main.MyS' in table.vls_info
361+
assert 'interface_main.MyInterface' in table.vls_info
362+
assert 'fn_main[MyS]add' in table.vls_info // MyS method
363+
assert 'fn_main[]foo' in table.vls_info
364+
assert 'global_main.my_global' in table.vls_info // module specific global
365+
assert 'global_my_global' in table.vls_info
366+
assert 'aliastype_main.MyAlias' in table.vls_info
367+
assert 'sumtype_main.MySum' in table.vls_info
368+
assert 'fntype_main.MyFnType' in table.vls_info
369+
}

0 commit comments

Comments
 (0)