Skip to content

Commit

Permalink
lsp: include print output in eval response
Browse files Browse the repository at this point in the history
Signed-off-by: Anders Eknert <anders@styra.com>
  • Loading branch information
anderseknert committed Aug 9, 2024
1 parent 4ba405e commit dec8ca8
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 17 deletions.
44 changes: 33 additions & 11 deletions internal/lsp/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ import (
"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/bundle"
"github.com/open-policy-agent/opa/rego"
"github.com/open-policy-agent/opa/topdown"
"github.com/open-policy-agent/opa/topdown/print"

"github.com/styrainc/regal/internal/lsp/uri"
"github.com/styrainc/regal/pkg/builtins"
)

func (l *LanguageServer) Eval(ctx context.Context, query string, input io.Reader) (rego.ResultSet, error) {
func (l *LanguageServer) Eval(
ctx context.Context,
query string,
input io.Reader,
printHook print.Hook,
) (rego.ResultSet, error) {
modules := l.cache.GetAllModules()
moduleFiles := make([]bundle.ModuleFile, 0, len(modules))

Expand All @@ -41,7 +46,7 @@ func (l *LanguageServer) Eval(ctx context.Context, query string, input io.Reader
Modules: moduleFiles,
}

regoArgs := prepareRegoArgs(ast.MustParseBody(query), bd)
regoArgs := prepareRegoArgs(ast.MustParseBody(query), bd, printHook)

pq, err := rego.New(regoArgs...).PrepareForEval(ctx)
if err != nil {
Expand All @@ -68,8 +73,9 @@ func (l *LanguageServer) Eval(ctx context.Context, query string, input io.Reader
}

type EvalPathResult struct {
Value any `json:"value"`
IsUndefined bool `json:"isUndefined"`
Value any `json:"value"`
IsUndefined bool `json:"isUndefined"`
PrintOutput map[int][]string `json:"printOutput"`
}

func FindInput(file string, workspacePath string) io.Reader {
Expand All @@ -88,33 +94,49 @@ func FindInput(file string, workspacePath string) io.Reader {
return nil
}

func (l *LanguageServer) EvalWorkspacePath(ctx context.Context, query string, input io.Reader) (EvalPathResult, error) {
func (l *LanguageServer) EvalWorkspacePath(
ctx context.Context,
query string,
input io.Reader,
) (EvalPathResult, error) {
resultQuery := "result := " + query

result, err := l.Eval(ctx, resultQuery, input)
hook := PrintHook{Output: make(map[int][]string)}

result, err := l.Eval(ctx, resultQuery, input, hook)
if err != nil {
return EvalPathResult{}, fmt.Errorf("failed evaluating query: %w", err)
}

if len(result) == 0 {
return EvalPathResult{IsUndefined: true}, nil
return EvalPathResult{IsUndefined: true, PrintOutput: hook.Output}, nil
}

res, ok := result[0].Bindings["result"]
if !ok {
return EvalPathResult{}, errors.New("expected result in bindings, didn't get it")
}

return EvalPathResult{Value: res}, nil
return EvalPathResult{Value: res, PrintOutput: hook.Output}, nil
}

func prepareRegoArgs(query ast.Body, bd bundle.Bundle) []func(*rego.Rego) {
func prepareRegoArgs(query ast.Body, bd bundle.Bundle, printHook print.Hook) []func(*rego.Rego) {
return []func(*rego.Rego){
rego.ParsedQuery(query),
rego.ParsedBundle("workspace", &bd),
rego.Function2(builtins.RegalParseModuleMeta, builtins.RegalParseModule),
rego.Function1(builtins.RegalLastMeta, builtins.RegalLast),
rego.EnablePrintStatements(true),
rego.PrintHook(topdown.NewPrintHook(os.Stderr)),
rego.PrintHook(printHook),
}
}

type PrintHook struct {
Output map[int][]string
}

func (h PrintHook) Print(ctx print.Context, msg string) error {
h.Output[ctx.Location.Row] = append(h.Output[ctx.Location.Row], msg)

return nil
}
6 changes: 0 additions & 6 deletions internal/lsp/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,6 @@ func TestEvalWorkspacePath(t *testing.T) {
t.Fatal(err)
}

empty := EvalPathResult{}

if res == empty {
t.Fatal("expected result, got nil")
}

if val, ok := res.Value.(bool); !ok || val != true {
t.Fatalf("expected true, got false")
}
Expand Down

0 comments on commit dec8ca8

Please sign in to comment.