Skip to content

Commit

Permalink
lsp/eval: Load capabilities and config into eval (#1217)
Browse files Browse the repository at this point in the history
When developing Regal rules it's useful to be able to access the
server's capabilities and configuration. This change adds these to the
rego evaluation context.

Signed-off-by: Charlie Egan <charlie@styra.com>
  • Loading branch information
charlieegan3 authored Oct 22, 2024
1 parent 0355ad7 commit 6b7e00b
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 4 deletions.
51 changes: 47 additions & 4 deletions internal/lsp/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"os"
"strings"

"github.com/anderseknert/roast/pkg/encoding"
Expand All @@ -18,6 +19,7 @@ import (
"github.com/styrainc/regal/internal/lsp/log"
"github.com/styrainc/regal/internal/lsp/uri"
"github.com/styrainc/regal/pkg/builtins"
"github.com/styrainc/regal/pkg/config"
)

func (l *LanguageServer) Eval(
Expand Down Expand Up @@ -74,7 +76,12 @@ func (l *LanguageServer) Eval(
allBundles["regal"] = rbundle.LoadedBundle
}

regoArgs := prepareRegoArgs(ast.MustParseBody(query), allBundles, printHook)
regoArgs := prepareRegoArgs(
ast.MustParseBody(query),
allBundles,
printHook,
l.getLoadedConfig(),
)

pq, err := rego.New(regoArgs...).PrepareForEval(ctx)
if err != nil {
Expand Down Expand Up @@ -138,21 +145,57 @@ func (l *LanguageServer) EvalWorkspacePath(
return EvalPathResult{Value: res, PrintOutput: hook.Output}, nil
}

func prepareRegoArgs(query ast.Body, bundles map[string]bundle.Bundle, printHook print.Hook) []func(*rego.Rego) {
func prepareRegoArgs(
query ast.Body,
bundles map[string]bundle.Bundle,
printHook print.Hook,
cfg *config.Config,
) []func(*rego.Rego) {
bundleArgs := make([]func(*rego.Rego), 0, len(bundles))
for key, b := range bundles {
bundleArgs = append(bundleArgs, rego.ParsedBundle(key, &b))
}

baseArgs := []func(*rego.Rego){
args := []func(*rego.Rego){
rego.ParsedQuery(query),
rego.Function2(builtins.RegalParseModuleMeta, builtins.RegalParseModule),
rego.Function1(builtins.RegalLastMeta, builtins.RegalLast),
rego.EnablePrintStatements(true),
rego.PrintHook(printHook),
}

return append(baseArgs, bundleArgs...)
args = append(args, bundleArgs...)

var caps *config.Capabilities
if cfg != nil && cfg.Capabilities != nil {
caps = cfg.Capabilities
} else {
caps = config.CapabilitiesForThisVersion()
}

var evalConfig config.Config
if cfg != nil {
evalConfig = *cfg
}

internalBundle := &bundle.Bundle{
Manifest: bundle.Manifest{
Roots: &[]string{"internal"},
Metadata: map[string]any{"name": "internal"},
},
Data: map[string]any{
"internal": map[string]any{
"combined_config": config.ToMap(evalConfig),
"capabilities": caps,
},
},
}

fmt.Fprintln(os.Stderr, "Loaded internal bundle")

args = append(args, rego.ParsedBundle("internal", internalBundle))

return args
}

type PrintHook struct {
Expand Down
41 changes: 41 additions & 0 deletions internal/lsp/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"io"
"os"
"slices"
"strings"
"testing"

Expand Down Expand Up @@ -60,6 +61,46 @@ func TestEvalWorkspacePath(t *testing.T) {
}
}

func TestEvalWorkspacePathInternalData(t *testing.T) {
t.Parallel()

logger := newTestLogger(t)

ls := NewLanguageServer(
context.Background(),
&LanguageServerOptions{LogWriter: logger, LogLevel: log.LevelDebug},
)

res, err := ls.EvalWorkspacePath(context.TODO(), "object.keys(data.internal)", strings.NewReader("{}"))
if err != nil {
t.Fatal(err)
}

val, ok := res.Value.([]any)
if !ok {
t.Fatalf("expected []any, got %T", res.Value)
}

valStr := make([]string, 0, len(val))

for _, v := range val {
str, ok := v.(string)
if !ok {
t.Fatalf("expected string, got %T", v)
}

valStr = append(valStr, str)
}

slices.Sort(valStr)

exp := []string{"capabilities", "combined_config"}

if !slices.Equal(valStr, exp) {
t.Fatalf("expected %v, got %v", exp, valStr)
}
}

func TestFindInput(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit 6b7e00b

Please # to comment.