Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions bundle/regal/lsp/completion/location/location_test.rego
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package regal.lsp.completion.location_test

import data.regal.ast
import data.regal.capabilities
import data.regal.config

import data.regal.lsp.completion.location

Expand Down Expand Up @@ -70,9 +68,7 @@ another if {
[{"row": 16, "col": 1}, {"x", "y", "z"}],
}

r := location.find_locals(module.rules, loc) with input as module
with input.regal.file.lines as lines
with config.capabilities as capabilities.provided
r := location.find_locals(module.rules, loc) with input as module with input.regal.file.lines as lines

r == want
}
Expand Down
22 changes: 13 additions & 9 deletions bundle/regal/lsp/completion/main.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@
# base package for completion suggestion provider policies, and acts
# like a router that collects suggestions from all provider policies
# under regal.lsp.completion.providers
# related_resources:
# - https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_completion
# schemas:
# - input: schema.regal.lsp.common
# - input.params: schema.regal.lsp.completion
# scope: subpackages
package regal.lsp.completion

import data.regal.util

# regal ignore:pointless-import
import data.regal.lsp.completion.location

# METADATA
# entrypoint: true
result["response"] := items
result["response"] := {
"items": items,
"isIncomplete": true,
}

# METADATA
# description: main entry point for completion suggestions
Expand All @@ -32,14 +38,12 @@ items contains object.union(completion, {"_regal": {"provider": provider}}) if {
# description: |
# checks if the current position is inside a comment
inside_comment if {
position := location.to_position(input.regal.context.location)

# avoid unmarshalling every comment location but only one that starts
# with the line number of the current position
line := sprintf("%d:", [position.line + 1])
line := sprintf("%d:", [input.params.position.line + 1])

some comment in data.workspace.parsed[input.regal.file.uri].comments
some comment in data.workspace.parsed[input.params.textDocument.uri].comments

startswith(comment.location, line)
util.to_location_no_text(comment.location).col <= position.character + 1
util.to_location_no_text(comment.location).col <= input.params.position.character + 1
}
16 changes: 8 additions & 8 deletions bundle/regal/lsp/completion/main_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@ test_completion_entrypoint if {
}

test_inside_comment if {
_data := {"file:///example.rego": {"comments": [
_data := {"file:///p.rego": {"comments": [
{"location": "2:1:2:10"},
{"location": "4:1:4:10"},
]}}
_input := {"regal": {
"context": {"location": {"row": 4, "col": 5}},
"file": {"uri": "file:///example.rego"},
_input := {"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 4},
}}

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

test_not_inside_comment if {
_data := {"file:///example.rego": {"comments": [
_data := {"file:///p.rego": {"comments": [
{"location": "2:1:2:10"},
{"location": "4:8:4:10"},
]}}
_input := {"regal": {
"context": {"location": {"row": 4, "col": 5}},
"file": {"uri": "file:///example.rego"},
_input := {"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 4},
}}

not completion.inside_comment with input as _input with data.workspace.parsed as _data
Expand Down
8 changes: 3 additions & 5 deletions bundle/regal/lsp/completion/providers/booleans/booleans.rego
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import data.regal.lsp.completion.location
# METADATA
# description: completion suggestions for true/false
items contains item if {
position := location.to_position(input.regal.context.location)

line := input.regal.file.lines[position.line]
line := input.regal.file.lines[input.params.position.line]
line != ""

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

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

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

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

Expand All @@ -31,7 +29,7 @@ items contains item if {
"kind": kind.constant,
"detail": "boolean value",
"textEdit": {
"range": location.word_range(word, position),
"range": location.word_range(word, input.params.position),
"newText": b,
},
}
Expand Down
60 changes: 24 additions & 36 deletions bundle/regal/lsp/completion/providers/booleans/booleans_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@ test_suggested_in_head if {

allow := f`}

regal_module := {"regal": {
"file": {
"name": "p.rego",
"lines": split(workspace["file:///p.rego"], "\n"),
regal_module := {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 2, "character": 9},
},
"context": {"location": {
"row": 3,
"col": 10,
}},
}}
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
}

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

Expand All @@ -35,16 +32,13 @@ allow if {
foo := t
}`}

regal_module := {"regal": {
"file": {
"name": "p.rego",
"lines": split(workspace["file:///p.rego"], "\n"),
regal_module := {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 9},
},
"context": {"location": {
"row": 4,
"col": 10,
}},
}}
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
}

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

Expand All @@ -62,16 +56,13 @@ allow if {
foo == t
}`}

regal_module := {"regal": {
"file": {
"name": "p.rego",
"lines": split(workspace["file:///p.rego"], "\n"),
regal_module := {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 9},
},
"context": {"location": {
"row": 4,
"col": 10,
}},
}}
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
}

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

Expand All @@ -89,16 +80,13 @@ allow if {
t
}`}

regal_module := {"regal": {
"file": {
"name": "p.rego",
"lines": split(workspace["file:///p.rego"], "\n"),
regal_module := {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 2},
},
"context": {"location": {
"row": 4,
"col": 3,
}},
}}
"regal": {"file": {"lines": split(workspace["file:///p.rego"], "\n")}},
}

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

Expand Down
7 changes: 3 additions & 4 deletions bundle/regal/lsp/completion/providers/builtins/builtins.rego
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ import data.regal.lsp.template
# METADATA
# description: suggest built-in functions matching typed ref
items contains item if {
position := location.to_position(input.regal.context.location)
line := input.regal.file.lines[position.line]
line := input.regal.file.lines[input.params.position.line]

line != ""
not startswith(line, "default ")
location.in_rule_body(line)

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

some builtin in data.workspace.builtins

Expand All @@ -29,7 +28,7 @@ items contains item if {
"label": builtin.name,
"kind": kind.function,
"detail": "built-in function",
"textEdit": {"range": location.word_range(ref, position), "newText": builtin.name},
"textEdit": {"range": location.word_range(ref, input.params.position), "newText": builtin.name},
"documentation": {"kind": "markdown", "value": template.render_for_builtin(builtin)},
}
}
78 changes: 48 additions & 30 deletions bundle/regal/lsp/completion/providers/builtins/builtins_test.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ package regal.lsp.completion.providers.builtins_test
import data.regal.lsp.completion.providers.builtins

test_simple_builtin_completion if {
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
"context": {"location": {"row": 4, "col": 11}},
"file": {"lines": [
items := builtins.items with data.workspace.builtins as _builtins with input as {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 10},
},
"regal": {"file": {"lines": [
"package p",
"",
"allow if {",
" b := c",
"}",
]},
}}
]}},
}

items == {
{
Expand Down Expand Up @@ -51,16 +54,19 @@ test_simple_builtin_completion if {
}

test_simple_builtin_completion_single_match if {
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
"context": {"location": {"row": 4, "col": 12}},
"file": {"lines": [
items := builtins.items with data.workspace.builtins as _builtins with input as {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 11},
},
"regal": {"file": {"lines": [
"package p",
"",
"allow if {",
" b := co",
"}",
]},
}}
]}},
}

items == {{
"detail": "built-in function",
Expand All @@ -81,16 +87,19 @@ test_simple_builtin_completion_single_match if {
}

test_simple_builtin_completion_single_match_longer_ref if {
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
"context": {"location": {"row": 4, "col": 18}},
"file": {"lines": [
items := builtins.items with data.workspace.builtins as _builtins with input as {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 17},
},
"regal": {"file": {"lines": [
"package p",
"",
"allow if {",
" b := crypto.h",
"}",
]},
}}
]}},
}

items == {{
"detail": "built-in function",
Expand All @@ -112,45 +121,54 @@ test_simple_builtin_completion_single_match_longer_ref if {

test_no_completion_of_deprecated_builtin if {
builtins_deprecated := [object.union(_builtins[0], {"deprecated": true})]
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {"regal": {
"context": {"location": {"row": 4, "col": 11}},
"file": {"lines": [
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 10},
},
"regal": {"file": {"lines": [
"package p",
"",
"allow if {",
" b := c",
"}",
]},
}}
]}},
}

count(items) == 0
}

test_no_completion_of_infix_builtin if {
builtins_deprecated := [object.union(_builtins[0], {"infix": "🔄"})]
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {"regal": {
"context": {"location": {"row": 4, "col": 11}},
"file": {"lines": [
items := builtins.items with data.workspace.builtins as builtins_deprecated with input as {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 3, "character": 10},
},
"regal": {"file": {"lines": [
"package p",
"",
"allow if {",
" b := c",
"}",
]},
}}
]}},
}

count(items) == 0
}

test_no_completion_in_default_rule if {
items := builtins.items with data.workspace.builtins as _builtins with input as {"regal": {
"context": {"location": {"row": 3, "col": 17}},
"file": {"lines": [
items := builtins.items with data.workspace.builtins as _builtins with input as {
"params": {
"textDocument": {"uri": "file:///p.rego"},
"position": {"line": 2, "character": 16},
},
"regal": {"file": {"lines": [
"package p",
"",
"default foo := c",
]},
}}
]}},
}

count(items) == 0
}
Expand Down
Loading
Loading