diff --git a/internal/lsp/capabilities_test.go b/internal/lsp/capabilities_test.go new file mode 100644 index 00000000..a1962cd1 --- /dev/null +++ b/internal/lsp/capabilities_test.go @@ -0,0 +1,52 @@ +package lsp + +import ( + "context" + "testing" + + "github.com/sourcegraph/jsonrpc2" + + "github.com/open-policy-agent/regal/internal/lsp/clients" + "github.com/open-policy-agent/regal/internal/lsp/types" + "github.com/open-policy-agent/regal/internal/lsp/uri" + "github.com/open-policy-agent/regal/internal/testutil" +) + +func TestInitializeExperimentalCapabilities(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(t.Context()) + defer cancel() + + tempDir := t.TempDir() + + clientHandler := func(_ context.Context, _ *jsonrpc2.Conn, _ *jsonrpc2.Request) (any, error) { + return struct{}{}, nil + } + + _, connClient := createAndInitServer(t, ctx, tempDir, clientHandler) + + request := types.InitializeParams{ + RootURI: uri.FromPath(clients.IdentifierGeneric, tempDir), + ClientInfo: types.ClientInfo{Name: "go test"}, + } + + var response types.InitializeResult + testutil.NoErr(connClient.Call(ctx, "initialize", request, &response))(t) + + if response.Capabilities.Experimental == nil { + t.Fatal("expected experimental capabilities to be non-nil") + } + + if !response.Capabilities.Experimental.ExplorerProvider { + t.Error("expected explorerProvider to be true") + } + + if !response.Capabilities.Experimental.EvalProvider { + t.Error("expected evalProvider to be true") + } + + if !response.Capabilities.Experimental.DebugProvider { + t.Error("expected debugProvider to be true") + } +} diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 7c584e03..54207878 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -1968,6 +1968,11 @@ func (l *LanguageServer) handleInitialize(ctx context.Context, params types.Init }, Full: true, }, + Experimental: &types.ExperimentalCapabilities{ + ExplorerProvider: true, + EvalProvider: true, + DebugProvider: true, + }, }, } diff --git a/internal/lsp/types/types.go b/internal/lsp/types/types.go index 21366fa0..5bc33f35 100644 --- a/internal/lsp/types/types.go +++ b/internal/lsp/types/types.go @@ -70,26 +70,41 @@ type ( } ServerCapabilities struct { - CodeLensProvider ResolveProviderOption `json:"codeLensProvider"` - Workspace WorkspaceOptions `json:"workspace"` - DiagnosticProvider DiagnosticOptions `json:"diagnosticProvider"` - CodeActionProvider CodeActionOptions `json:"codeActionProvider"` - ExecuteCommandProvider ExecuteCommandOptions `json:"executeCommandProvider"` - TextDocumentSyncOptions TextDocumentSyncOptions `json:"textDocumentSync"` - CompletionProvider CompletionOptions `json:"completionProvider"` - InlayHintProvider ResolveProviderOption `json:"inlayHintProvider"` - DocumentLinkProvider ResolveProviderOption `json:"documentLinkProvider"` - SignatureHelpProvider SignatureHelpOptions `json:"signatureHelpProvider"` - SemanticTokensProvider SemanticTokensOptions `json:"semanticTokensProvider"` - DocumentHighlightProvider bool `json:"documentHighlightProvider"` - HoverProvider bool `json:"hoverProvider"` - DocumentFormattingProvider bool `json:"documentFormattingProvider"` - FoldingRangeProvider bool `json:"foldingRangeProvider"` - DocumentSymbolProvider bool `json:"documentSymbolProvider"` - WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider"` - DefinitionProvider bool `json:"definitionProvider"` - SelectionRangeProvider bool `json:"selectionRangeProvider"` - LinkedEditingRangeProvider bool `json:"linkedEditingRangeProvider"` + CodeLensProvider ResolveProviderOption `json:"codeLensProvider"` + Workspace WorkspaceOptions `json:"workspace"` + DiagnosticProvider DiagnosticOptions `json:"diagnosticProvider"` + CodeActionProvider CodeActionOptions `json:"codeActionProvider"` + ExecuteCommandProvider ExecuteCommandOptions `json:"executeCommandProvider"` + TextDocumentSyncOptions TextDocumentSyncOptions `json:"textDocumentSync"` + CompletionProvider CompletionOptions `json:"completionProvider"` + InlayHintProvider ResolveProviderOption `json:"inlayHintProvider"` + DocumentLinkProvider ResolveProviderOption `json:"documentLinkProvider"` + SignatureHelpProvider SignatureHelpOptions `json:"signatureHelpProvider"` + SemanticTokensProvider SemanticTokensOptions `json:"semanticTokensProvider"` + DocumentHighlightProvider bool `json:"documentHighlightProvider"` + HoverProvider bool `json:"hoverProvider"` + DocumentFormattingProvider bool `json:"documentFormattingProvider"` + FoldingRangeProvider bool `json:"foldingRangeProvider"` + DocumentSymbolProvider bool `json:"documentSymbolProvider"` + WorkspaceSymbolProvider bool `json:"workspaceSymbolProvider"` + DefinitionProvider bool `json:"definitionProvider"` + SelectionRangeProvider bool `json:"selectionRangeProvider"` + LinkedEditingRangeProvider bool `json:"linkedEditingRangeProvider"` + Experimental *ExperimentalCapabilities `json:"experimental,omitempty"` + } + + // ExperimentalCapabilities contains Regal-specific experimental LSP features + // that are not part of the standard LSP specification. + ExperimentalCapabilities struct { + // ExplorerProvider indicates whether the server supports the regal.explorer + // command and regal/showExplorerResult notification. + ExplorerProvider bool `json:"explorerProvider"` + // EvalProvider indicates whether the server supports the regal.eval + // command and regal/showEvalResult request. + EvalProvider bool `json:"evalProvider"` + // DebugProvider indicates whether the server supports the regal.debug + // command and regal/startDebugging request. + DebugProvider bool `json:"debugProvider"` } TextDocumentPositionParams struct {