z_mirror/luapls

git clone https://git.raiguard.me/z_mirror/luapls

Caleb HeuerMove semantic children logic to ast node methods9e06851

main
1.7 KiB73 linesraw
1package lsp
2
3import (
4	"encoding/json"
5
6	"github.com/raiguard/luapls/lua/ast"
7	"github.com/raiguard/luapls/lua/token"
8)
9
10func toJSON(v any) string {
11	res, err := json.Marshal(v)
12	if err != nil {
13		return "<ERROR>"
14	}
15	return string(res)
16}
17
18// getLocals returns a list of all local variables contained in node for the given pos.
19func getLocals(node ast.Node, pos token.Pos, includeSelf bool) map[string]*ast.Identifier {
20	locals := map[string]*ast.Identifier{}
21
22	ast.WalkSemantic(node, func(node ast.Node) bool {
23		isAfter := node.Pos() > pos && pos < node.End()
24		if isAfter {
25			return false
26		}
27		isBefore := node.Pos() <= pos && pos > node.End()
28		isInside := node.Pos() <= pos && pos < node.End()
29		switch node := node.(type) {
30		case *ast.ForInStatement:
31			if isInside {
32				for _, ident := range node.Names.Pairs {
33					locals[ident.Node.Token.Literal] = ident.Node
34				}
35			}
36		case *ast.ForStatement:
37			if isInside {
38				if node.Name != nil {
39					locals[node.Name.Token.Literal] = node.Name
40				}
41			}
42		case *ast.FunctionExpression:
43			if isInside {
44				for _, ident := range node.Params.Pairs {
45					locals[ident.Node.Token.Literal] = ident.Node
46				}
47			}
48		case *ast.FunctionStatement:
49			if isInside {
50				for _, ident := range node.Params.Pairs {
51					locals[ident.Node.Token.Literal] = ident.Node
52				}
53			}
54			if isBefore || includeSelf {
55				if ident, ok := node.Name.(*ast.Identifier); ok {
56					locals[ident.Token.Literal] = ident
57				}
58			}
59		case *ast.LocalStatement:
60			if isBefore || includeSelf {
61				for _, ident := range node.Names.Pairs {
62					locals[ident.Node.Token.Literal] = ident.Node
63				}
64			}
65		default:
66			return isInside
67		}
68
69		return true
70	})
71
72	return locals
73}