Skip to content

Commit 1685bb8

Browse files
authored
Move completion handler into Rego router (#1699)
Although many completion providers have been Rego based since a long time back, these providers used their own input format, and a separate prepared query — not at all integrated with other Rego handlers. No more! All completion providers are now 100% Rego-based, and use the same Rego router entrypoint as all other Rego handlers. Since the input format now mirrors what the LSP client sends, a whole lot of tests had to be updated. Also the usual style fixes here and there.. although I tried to show some restrain :) Signed-off-by: Anders Eknert <anders@eknert.com>
1 parent 14166e9 commit 1685bb8

54 files changed

Lines changed: 624 additions & 1235 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bundle/regal/lsp/completion/location/location_test.rego

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package regal.lsp.completion.location_test
22

33
import data.regal.ast
4-
import data.regal.capabilities
5-
import data.regal.config
64

75
import data.regal.lsp.completion.location
86

@@ -70,9 +68,7 @@ another if {
7068
[{"row": 16, "col": 1}, {"x", "y", "z"}],
7169
}
7270

73-
r := location.find_locals(module.rules, loc) with input as module
74-
with input.regal.file.lines as lines
75-
with config.capabilities as capabilities.provided
71+
r := location.find_locals(module.rules, loc) with input as module with input.regal.file.lines as lines
7672

7773
r == want
7874
}

bundle/regal/lsp/completion/main.rego

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,22 @@
33
# base package for completion suggestion provider policies, and acts
44
# like a router that collects suggestions from all provider policies
55
# under regal.lsp.completion.providers
6+
# related_resources:
7+
# - https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion
8+
# schemas:
9+
# - input: schema.regal.lsp.common
10+
# - input.params: schema.regal.lsp.completion
11+
# scope: subpackages
612
package regal.lsp.completion
713

814
import data.regal.util
915

10-
# regal ignore:pointless-import
11-
import data.regal.lsp.completion.location
12-
1316
# METADATA
1417
# entrypoint: true
15-
result["response"] := items
18+
result["response"] := {
19+
"items": items,
20+
"isIncomplete": true,
21+
}
1622

1723
# METADATA
1824
# description: main entry point for completion suggestions
@@ -32,14 +38,12 @@ items contains object.union(completion, {"_regal": {"provider": provider}}) if {
3238
# description: |
3339
# checks if the current position is inside a comment
3440
inside_comment if {
35-
position := location.to_position(input.regal.context.location)
36-
3741
# avoid unmarshalling every comment location but only one that starts
3842
# with the line number of the current position
39-
line := sprintf("%d:", [position.line + 1])
43+
line := sprintf("%d:", [input.params.position.line + 1])
4044

41-
some comment in data.workspace.parsed[input.regal.file.uri].comments
45+
some comment in data.workspace.parsed[input.params.textDocument.uri].comments
4246

4347
startswith(comment.location, line)
44-
util.to_location_no_text(comment.location).col <= position.character + 1
48+
util.to_location_no_text(comment.location).col <= input.params.position.character + 1
4549
}

bundle/regal/lsp/completion/main_test.rego

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,26 @@ test_completion_entrypoint if {
99
}
1010

1111
test_inside_comment if {
12-
_data := {"file:///example.rego": {"comments": [
12+
_data := {"file:///p.rego": {"comments": [
1313
{"location": "2:1:2:10"},
1414
{"location": "4:1:4:10"},
1515
]}}
16-
_input := {"regal": {
17-
"context": {"location": {"row": 4, "col": 5}},
18-
"file": {"uri": "file:///example.rego"},
16+
_input := {"params": {
17+
"textDocument": {"uri": "file:///p.rego"},
18+
"position": {"line": 3, "character": 4},
1919
}}
2020

2121
completion.inside_comment with input as _input with data.workspace.parsed as _data
2222
}
2323

2424
test_not_inside_comment if {
25-
_data := {"file:///example.rego": {"comments": [
25+
_data := {"file:///p.rego": {"comments": [
2626
{"location": "2:1:2:10"},
2727
{"location": "4:8:4:10"},
2828
]}}
29-
_input := {"regal": {
30-
"context": {"location": {"row": 4, "col": 5}},
31-
"file": {"uri": "file:///example.rego"},
29+
_input := {"params": {
30+
"textDocument": {"uri": "file:///p.rego"},
31+
"position": {"line": 3, "character": 4},
3232
}}
3333

3434
not completion.inside_comment with input as _input with data.workspace.parsed as _data

bundle/regal/lsp/completion/providers/booleans/booleans.rego

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import data.regal.lsp.completion.location
88
# METADATA
99
# description: completion suggestions for true/false
1010
items contains item if {
11-
position := location.to_position(input.regal.context.location)
12-
13-
line := input.regal.file.lines[position.line]
11+
line := input.regal.file.lines[input.params.position.line]
1412
line != ""
1513

1614
words := regex.split(`\s+`, line)
@@ -20,7 +18,7 @@ items contains item if {
2018

2119
previous_word in {"==", ":="}
2220

23-
word := location.word_at(line, input.regal.context.location.col)
21+
word := location.word_at(line, input.params.position.character + 1)
2422

2523
some b in ["true", "false"]
2624

@@ -31,7 +29,7 @@ items contains item if {
3129
"kind": kind.constant,
3230
"detail": "boolean value",
3331
"textEdit": {
34-
"range": location.word_range(word, position),
32+
"range": location.word_range(word, input.params.position),
3533
"newText": b,
3634
},
3735
}

bundle/regal/lsp/completion/providers/booleans/booleans_test.rego

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,13 @@ test_suggested_in_head if {
88
99
allow := f`}
1010

11-
regal_module := {"regal": {
12-
"file": {
13-
"name": "p.rego",
14-
"lines": split(workspace["file:///p.rego"], "\n"),
11+
regal_module := {
12+
"params": {
13+
"textDocument": {"uri": "file:///p.rego"},
14+
"position": {"line": 2, "character": 9},
1515
},
16-
"context": {"location": {
17-
"row": 3,
18-
"col": 10,
19-
}},
20-
}}
16+
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
17+
}
2118

2219
items := provider.items with input as regal_module with data.workspace.parsed as utils.parsed_modules(workspace)
2320

@@ -35,16 +32,13 @@ allow if {
3532
foo := t
3633
}`}
3734

38-
regal_module := {"regal": {
39-
"file": {
40-
"name": "p.rego",
41-
"lines": split(workspace["file:///p.rego"], "\n"),
35+
regal_module := {
36+
"params": {
37+
"textDocument": {"uri": "file:///p.rego"},
38+
"position": {"line": 3, "character": 9},
4239
},
43-
"context": {"location": {
44-
"row": 4,
45-
"col": 10,
46-
}},
47-
}}
40+
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
41+
}
4842

4943
items := provider.items with input as regal_module with data.workspace.parsed as utils.parsed_modules(workspace)
5044

@@ -62,16 +56,13 @@ allow if {
6256
foo == t
6357
}`}
6458

65-
regal_module := {"regal": {
66-
"file": {
67-
"name": "p.rego",
68-
"lines": split(workspace["file:///p.rego"], "\n"),
59+
regal_module := {
60+
"params": {
61+
"textDocument": {"uri": "file:///p.rego"},
62+
"position": {"line": 3, "character": 9},
6963
},
70-
"context": {"location": {
71-
"row": 4,
72-
"col": 10,
73-
}},
74-
}}
64+
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
65+
}
7566

7667
items := provider.items with input as regal_module with data.workspace.parsed as utils.parsed_modules(workspace)
7768

@@ -89,16 +80,13 @@ allow if {
8980
t
9081
}`}
9182

92-
regal_module := {"regal": {
93-
"file": {
94-
"name": "p.rego",
95-
"lines": split(workspace["file:///p.rego"], "\n"),
83+
regal_module := {
84+
"params": {
85+
"textDocument": {"uri": "file:///p.rego"},
86+
"position": {"line": 3, "character": 2},
9687
},
97-
"context": {"location": {
98-
"row": 4,
99-
"col": 3,
100-
}},
101-
}}
88+
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
89+
}
10290

10391
items := provider.items with input as regal_module with data.workspace.parsed as utils.parsed_modules(workspace)
10492

bundle/regal/lsp/completion/providers/builtins/builtins.rego

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@ import data.regal.lsp.template
99
# METADATA
1010
# description: suggest built-in functions matching typed ref
1111
items contains item if {
12-
position := location.to_position(input.regal.context.location)
13-
line := input.regal.file.lines[position.line]
12+
line := input.regal.file.lines[input.params.position.line]
1413

1514
line != ""
1615
not startswith(line, "default ")
1716
location.in_rule_body(line)
1817

19-
ref := location.ref_at(line, input.regal.context.location.col)
18+
ref := location.ref_at(line, input.params.position.character + 1)
2019

2120
some builtin in data.workspace.builtins
2221

@@ -29,7 +28,7 @@ items contains item if {
2928
"label": builtin.name,
3029
"kind": kind.function,
3130
"detail": "built-in function",
32-
"textEdit": {"range": location.word_range(ref, position), "newText": builtin.name},
31+
"textEdit": {"range": location.word_range(ref, input.params.position), "newText": builtin.name},
3332
"documentation": {"kind": "markdown", "value": template.render_for_builtin(builtin)},
3433
}
3534
}

bundle/regal/lsp/completion/providers/builtins/builtins_test.rego

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,19 @@ package regal.lsp.completion.providers.builtins_test
33
import data.regal.lsp.completion.providers.builtins
44

55
test_simple_builtin_completion if {
6-
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
7-
"context": {"location": {"row": 4, "col": 11}},
8-
"file": {"lines": [
6+
items := builtins.items with data.workspace.builtins as _builtins with input as {
7+
"params": {
8+
"textDocument": {"uri": "file:///p.rego"},
9+
"position": {"line": 3, "character": 10},
10+
},
11+
"regal": {"file": {"lines": [
912
"package p",
1013
"",
1114
"allow if {",
1215
" b := c",
1316
"}",
14-
]},
15-
}}
17+
]}},
18+
}
1619

1720
items == {
1821
{
@@ -51,16 +54,19 @@ test_simple_builtin_completion if {
5154
}
5255

5356
test_simple_builtin_completion_single_match if {
54-
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
55-
"context": {"location": {"row": 4, "col": 12}},
56-
"file": {"lines": [
57+
items := builtins.items with data.workspace.builtins as _builtins with input as {
58+
"params": {
59+
"textDocument": {"uri": "file:///p.rego"},
60+
"position": {"line": 3, "character": 11},
61+
},
62+
"regal": {"file": {"lines": [
5763
"package p",
5864
"",
5965
"allow if {",
6066
" b := co",
6167
"}",
62-
]},
63-
}}
68+
]}},
69+
}
6470

6571
items == {{
6672
"detail": "built-in function",
@@ -81,16 +87,19 @@ test_simple_builtin_completion_single_match if {
8187
}
8288

8389
test_simple_builtin_completion_single_match_longer_ref if {
84-
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
85-
"context": {"location": {"row": 4, "col": 18}},
86-
"file": {"lines": [
90+
items := builtins.items with data.workspace.builtins as _builtins with input as {
91+
"params": {
92+
"textDocument": {"uri": "file:///p.rego"},
93+
"position": {"line": 3, "character": 17},
94+
},
95+
"regal": {"file": {"lines": [
8796
"package p",
8897
"",
8998
"allow if {",
9099
" b := crypto.h",
91100
"}",
92-
]},
93-
}}
101+
]}},
102+
}
94103

95104
items == {{
96105
"detail": "built-in function",
@@ -112,45 +121,54 @@ test_simple_builtin_completion_single_match_longer_ref if {
112121

113122
test_no_completion_of_deprecated_builtin if {
114123
builtins_deprecated := [object.union(_builtins[0], {"deprecated": true})]
115-
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {"regal": {
116-
"context": {"location": {"row": 4, "col": 11}},
117-
"file": {"lines": [
124+
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {
125+
"params": {
126+
"textDocument": {"uri": "file:///p.rego"},
127+
"position": {"line": 3, "character": 10},
128+
},
129+
"regal": {"file": {"lines": [
118130
"package p",
119131
"",
120132
"allow if {",
121133
" b := c",
122134
"}",
123-
]},
124-
}}
135+
]}},
136+
}
125137

126138
count(items) == 0
127139
}
128140

129141
test_no_completion_of_infix_builtin if {
130142
builtins_deprecated := [object.union(_builtins[0], {"infix": "🔄"})]
131-
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {"regal": {
132-
"context": {"location": {"row": 4, "col": 11}},
133-
"file": {"lines": [
143+
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {
144+
"params": {
145+
"textDocument": {"uri": "file:///p.rego"},
146+
"position": {"line": 3, "character": 10},
147+
},
148+
"regal": {"file": {"lines": [
134149
"package p",
135150
"",
136151
"allow if {",
137152
" b := c",
138153
"}",
139-
]},
140-
}}
154+
]}},
155+
}
141156

142157
count(items) == 0
143158
}
144159

145160
test_no_completion_in_default_rule if {
146-
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
147-
"context": {"location": {"row": 3, "col": 17}},
148-
"file": {"lines": [
161+
items := builtins.items with data.workspace.builtins as _builtins with input as {
162+
"params": {
163+
"textDocument": {"uri": "file:///p.rego"},
164+
"position": {"line": 2, "character": 16},
165+
},
166+
"regal": {"file": {"lines": [
149167
"package p",
150168
"",
151169
"default foo := c",
152-
]},
153-
}}
170+
]}},
171+
}
154172

155173
count(items) == 0
156174
}

0 commit comments

Comments
 (0)