|
1 | | -// // Package definition provides the logic for finding |
2 | | -// // definitions in Terragrunt configurations. |
3 | | -// package definition |
4 | | -// |
5 | | -// import ( |
6 | | -// "bufio" |
7 | | -// "strings" |
8 | | -// "terragrunt-ls/internal/tg/store" |
9 | | -// |
10 | | -// "go.lsp.dev/protocol" |
11 | | -// "go.uber.org/zap" |
12 | | -// ) |
13 | | -// |
14 | | -// const ( |
15 | | -// // DefinitionContextInclude is the context for an include definition. |
16 | | -// // This means that the user is trying to find the definition of an include. |
17 | | -// DefinitionContextInclude = "include" |
18 | | -// |
19 | | -// // DefinitionContextNull is the context for a null definition. |
20 | | -// // This means that the user is trying to go to the definition of nothing useful. |
21 | | -// DefinitionContextNull = "null" |
22 | | -// ) |
23 | | -// |
24 | | -// func GetDefinitionTargetWithContext(l *zap.SugaredLogger, store store.Store, position protocol.Position) (string, string) { |
25 | | -// document := store.Document |
26 | | -// |
27 | | -// scanner := bufio.NewScanner(strings.NewReader(document)) |
28 | | -// target := "" |
29 | | -// definitionContext := "" |
30 | | -// lineHit := false |
31 | | -// scannedLines := 0 |
32 | | -// |
33 | | -// for scanner.Scan() { |
34 | | -// line := scanner.Text() |
35 | | -// |
36 | | -// // Trim whitespace early to avoid |
37 | | -// // having to do it later. |
38 | | -// line = strings.TrimSpace(line) |
39 | | -// |
40 | | -// // Skip empty lines |
41 | | -// if len(line) == 0 { |
42 | | -// continue |
43 | | -// } |
44 | | -// |
45 | | -// // Skip comments |
46 | | -// if strings.HasPrefix(line, "#") || strings.HasPrefix(line, "//") { |
47 | | -// continue |
48 | | -// } |
49 | | -// |
50 | | -// // Identify configuration blocks |
51 | | -// block, labels, isBlock := isConfigBlockLine(line) |
52 | | -// if isBlock { |
53 | | -// l.Debugf("Found block: %s", block) |
54 | | -// |
55 | | -// if block == DefinitionContextInclude { |
56 | | -// definitionContext = DefinitionContextInclude |
57 | | -// |
58 | | -// // Includes can have zero labels |
59 | | -// if len(labels) > 0 { |
60 | | -// target = labels[0] |
61 | | -// } |
62 | | -// } |
63 | | -// } |
64 | | -// |
65 | | -// // Check if the current line is the one we're looking for |
66 | | -// if scannedLines == int(position.Line) { |
67 | | -// l.Debugf("Hit line %d: %s", position.Line, line) |
68 | | -// |
69 | | -// lineHit = true |
70 | | -// } |
71 | | -// |
72 | | -// // Check if we've reached the end of the block. |
73 | | -// // |
74 | | -// // End of blocks are special, as we've either discovered |
75 | | -// // the context for our definition, or we've reached |
76 | | -// // a point where we need to reset the context. |
77 | | -// // |
78 | | -// // The reason we do both checks is that we need to |
79 | | -// // account for single line block definitions. |
80 | | -// if line == "}" || (strings.HasSuffix(line, "}") && isBlock) { |
81 | | -// l.Debugf("End of block: %s, line: %d", block, scannedLines) |
82 | | -// |
83 | | -// if lineHit && definitionContext != "" { |
84 | | -// l.Debugf("Found target: %s, context: %s", target, definitionContext) |
85 | | -// |
86 | | -// return target, definitionContext |
87 | | -// } |
88 | | -// |
89 | | -// definitionContext = "" |
90 | | -// target = "" |
91 | | -// } |
92 | | -// |
93 | | -// scannedLines++ |
94 | | -// } |
95 | | -// |
96 | | -// l.Debugf("No target found at %d:%d", position.Line, position.Character) |
97 | | -// |
98 | | -// return "", DefinitionContextNull |
99 | | -// } |
100 | | -// |
101 | | -// func isConfigBlockLine(line string) (string, []string, bool) { |
102 | | -// fields := strings.Fields(line) |
103 | | -// |
104 | | -// const minConfigBlockLen = 2 |
105 | | -// |
106 | | -// if len(fields) < minConfigBlockLen { |
107 | | -// return "", nil, false |
108 | | -// } |
109 | | -// |
110 | | -// block := fields[0] |
111 | | -// labels := []string{} |
112 | | -// |
113 | | -// for _, field := range fields[1:] { |
114 | | -// if field == "=" { |
115 | | -// return "", nil, false |
116 | | -// } |
117 | | -// |
118 | | -// if field == "{" { |
119 | | -// return block, labels, true |
120 | | -// } |
121 | | -// |
122 | | -// labels = append(labels, strings.Trim(field, "\"")) |
123 | | -// } |
124 | | -// |
125 | | -// return "", nil, false |
126 | | -// } |
127 | | - |
128 | 1 | package definition_test |
129 | 2 |
|
130 | 3 | import ( |
|
0 commit comments