@@ -26,6 +26,7 @@ import (
2626 "github.com/open-policy-agent/regal/bundle"
2727 "github.com/open-policy-agent/regal/internal/capabilities"
2828 "github.com/open-policy-agent/regal/internal/compile"
29+ "github.com/open-policy-agent/regal/internal/explorer"
2930 rio "github.com/open-policy-agent/regal/internal/io"
3031 "github.com/open-policy-agent/regal/internal/io/files"
3132 "github.com/open-policy-agent/regal/internal/lsp/bundles"
@@ -569,6 +570,35 @@ func (l *LanguageServer) StartCommandWorker(ctx context.Context) {
569570 case <- ctx .Done ():
570571 return
571572 case params := <- l .commandRequest :
573+ // Handle regal.explorer separately as VS Code sends map arguments
574+ if params .Command == "regal.explorer" {
575+ var explorerArgs types.ExplorerCommandArgs
576+
577+ if len (params .Arguments ) > 0 {
578+ arg , ok := params .Arguments [0 ].(map [string ]any )
579+ if ! ok {
580+ l .log .Message ("expected explorer argument to be a map, got %T" , params .Arguments [0 ])
581+
582+ continue
583+ }
584+
585+ explorerArgs = types.ExplorerCommandArgs {
586+ Target : util .GetMapValue [string ](arg , "target" ),
587+ Strict : util .GetMapValue [bool ](arg , "strict" ),
588+ Annotations : util .GetMapValue [bool ](arg , "annotations" ),
589+ Print : util .GetMapValue [bool ](arg , "print" ),
590+ Format : util .GetMapValue [bool ](arg , "format" ),
591+ }
592+ }
593+
594+ if err := l .handleExplorerCommand (ctx , explorerArgs ); err != nil {
595+ l .log .Message ("failed to handle explorer command: %s" , err )
596+ }
597+
598+ continue
599+ }
600+
601+ // Handle all other commands (they use string arguments)
572602 var (
573603 editParams * types.ApplyWorkspaceEditParams
574604 args types.CommandArgs
@@ -1919,6 +1949,7 @@ func (l *LanguageServer) handleInitialize(ctx context.Context, params types.Init
19191949 Commands : []string {
19201950 "regal.debug" ,
19211951 "regal.eval" ,
1952+ "regal.explorer" ,
19221953 "regal.fix.opa-fmt" ,
19231954 "regal.fix.use-rego-v1" ,
19241955 "regal.fix.use-assignment-operator" ,
@@ -2283,6 +2314,68 @@ func (l *LanguageServer) regalContext(fileURI string, _ *rego.Requirements) *reg
22832314 }
22842315}
22852316
2317+ func (l * LanguageServer ) handleExplorerCommand (ctx context.Context , args types.ExplorerCommandArgs ) error {
2318+ if args .Target == "" {
2319+ l .log .Message ("expected command target, got empty string" )
2320+
2321+ return errors .New ("target file URI is required" )
2322+ }
2323+
2324+ contents , ok := l .cache .GetFileContents (args .Target )
2325+ if ! ok {
2326+ return fmt .Errorf ("could not get file contents for uri %q" , args .Target )
2327+ }
2328+
2329+ path := l .toRelativePath (args .Target )
2330+
2331+ compileResults := explorer .CompilerStages (
2332+ path ,
2333+ contents ,
2334+ args .Strict ,
2335+ args .Annotations ,
2336+ args .Print ,
2337+ )
2338+
2339+ stages := make ([]types.ExplorerStageResult , 0 , len (compileResults ))
2340+ hasErrors := false
2341+
2342+ for _ , cs := range compileResults {
2343+ stage := types.ExplorerStageResult {
2344+ Name : cs .Stage ,
2345+ Error : cs .Error != "" ,
2346+ }
2347+
2348+ if cs .Error != "" {
2349+ hasErrors = true
2350+ stage .Output = cs .Error
2351+ } else {
2352+ if args .Format {
2353+ stage .Output = cs .FormattedResult ()
2354+ } else if cs .Result != nil {
2355+ stage .Output = cs .Result .String ()
2356+ }
2357+ }
2358+
2359+ stages = append (stages , stage )
2360+ }
2361+
2362+ responseParams := types.ExplorerResult {
2363+ Stages : stages ,
2364+ }
2365+
2366+ if ! hasErrors {
2367+ if plan , err := explorer .Plan (ctx , path , contents , args .Print ); err == nil {
2368+ responseParams .Plan = plan
2369+ }
2370+ }
2371+
2372+ if err := l .conn .Notify (ctx , "regal/showExplorerResult" , responseParams ); err != nil {
2373+ return fmt .Errorf ("regal/showExplorerResult notification failed: %w" , err )
2374+ }
2375+
2376+ return nil
2377+ }
2378+
22862379func (l * LanguageServer ) handleEvalCommand (ctx context.Context , args types.CommandArgs ) error {
22872380 if args .Target == "" || args .Query == "" {
22882381 l .log .Message ("expected command target and query, got target %q, query %q" , args .Target , args .Query )
0 commit comments