You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
terraform/lang/langserver/server.go

257 lines
8.6 KiB

package langserver
import (
"context"
"log"
"os"
"sync"
"github.com/hashicorp/terraform/internal/jsonrpc2"
lsp "github.com/hashicorp/terraform/internal/lsp"
)
// Run starts an LSP server on the supplied stream, and waits until the
// stream is closed.
func Run(ctx context.Context, configPath string, stream jsonrpc2.Stream, opts ...interface{}) error {
s := &server{
configPath: configPath,
fs: newFilesystem(),
}
conn, client := lsp.RunServer(ctx, stream, s, opts...)
s.client = client
return conn.Wait(ctx)
}
type server struct {
configPath string
fs *filesystem
client lsp.Client
statusMu sync.Mutex
active bool
}
func notImplemented(method string) *jsonrpc2.Error {
return jsonrpc2.NewErrorf(jsonrpc2.CodeMethodNotFound, "method %q not yet implemented", method)
}
func (s *server) Initialize(context.Context, *lsp.InitializeParams) (*lsp.InitializeResult, error) {
s.statusMu.Lock()
defer s.statusMu.Unlock()
if s.active {
return nil, jsonrpc2.NewErrorf(jsonrpc2.CodeInvalidRequest, "already initialized")
}
s.active = true
log.Printf("[DEBUG] langserver: Initialize")
return &lsp.InitializeResult{
Capabilities: lsp.ServerCapabilities{
DocumentFormattingProvider: true,
TextDocumentSync: lsp.TextDocumentSyncOptions{
OpenClose: true,
// For now we want whole-file updates only, since we're not
// ready to process partial changes.
Change: float64(lsp.Incremental),
},
DefinitionProvider: true,
},
}, nil
}
func (s *server) Initialized(context.Context, *lsp.InitializedParams) error {
log.Printf("[DEBUG] langserver: Initialized")
return nil // nothing to do; this is just a notification from the client
}
func (s *server) Shutdown(context.Context) error {
s.statusMu.Lock()
defer s.statusMu.Unlock()
if !s.active {
return jsonrpc2.NewErrorf(jsonrpc2.CodeInvalidRequest, "not initialized")
}
s.active = false
return nil
}
func (s *server) Exit(context.Context) error {
os.Exit(0)
return nil
}
func (s *server) DidChangeWorkspaceFolders(context.Context, *lsp.DidChangeWorkspaceFoldersParams) error {
log.Printf("[DEBUG] langserver: DidChangeWorkspaceFolders")
return notImplemented("DidChangeWorkspaceFolders")
}
func (s *server) DidChangeConfiguration(context.Context, *lsp.DidChangeConfigurationParams) error {
log.Printf("[DEBUG] langserver: DidChangeConfiguration")
return notImplemented("DidChangeConfiguration")
}
func (s *server) DidChangeWatchedFiles(context.Context, *lsp.DidChangeWatchedFilesParams) error {
log.Printf("[DEBUG] langserver: DidChangeWatchedFiles")
return notImplemented("DidChangeWatchedFiles")
}
func (s *server) Symbols(context.Context, *lsp.WorkspaceSymbolParams) ([]lsp.SymbolInformation, error) {
log.Printf("[DEBUG] langserver: Symbols")
return nil, notImplemented("Symbols")
}
func (s *server) ExecuteCommand(context.Context, *lsp.ExecuteCommandParams) (interface{}, error) {
log.Printf("[DEBUG] langserver: ExecuteCommand")
return nil, notImplemented("ExecuteCommand")
}
func (s *server) DidOpen(ctx context.Context, req *lsp.DidOpenTextDocumentParams) error {
log.Printf("[DEBUG] langserver: DidOpen")
u := uri(req.TextDocument.URI)
return s.fs.Open(u, []byte(req.TextDocument.Text))
}
func (s *server) DidChange(ctx context.Context, req *lsp.DidChangeTextDocumentParams) error {
log.Printf("[DEBUG] langserver: DidChange")
u := uri(req.TextDocument.URI)
return s.fs.Change(u, req.ContentChanges)
}
func (s *server) WillSave(context.Context, *lsp.WillSaveTextDocumentParams) error {
log.Printf("[DEBUG] langserver: WillSave")
return notImplemented("WillSave")
}
func (s *server) WillSaveWaitUntil(context.Context, *lsp.WillSaveTextDocumentParams) ([]lsp.TextEdit, error) {
log.Printf("[DEBUG] langserver: WillSaveWaitUntil")
return nil, notImplemented("WillSaveWaitUntil")
}
func (s *server) DidSave(context.Context, *lsp.DidSaveTextDocumentParams) error {
log.Printf("[DEBUG] langserver: DidSave")
return notImplemented("DidSave")
}
func (s *server) DidClose(ctx context.Context, req *lsp.DidCloseTextDocumentParams) error {
log.Printf("[DEBUG] langserver: DidClose")
u := uri(req.TextDocument.URI)
return s.fs.Close(u)
}
func (s *server) Completion(context.Context, *lsp.CompletionParams) (*lsp.CompletionList, error) {
log.Printf("[DEBUG] langserver: Completion")
return nil, notImplemented("Completion")
}
func (s *server) CompletionResolve(context.Context, *lsp.CompletionItem) (*lsp.CompletionItem, error) {
log.Printf("[DEBUG] langserver: CompletionResolve")
return nil, notImplemented("CompletionResolve")
}
func (s *server) Hover(context.Context, *lsp.TextDocumentPositionParams) (*lsp.Hover, error) {
log.Printf("[DEBUG] langserver: Hover")
return nil, notImplemented("Hover")
}
func (s *server) SignatureHelp(context.Context, *lsp.TextDocumentPositionParams) (*lsp.SignatureHelp, error) {
log.Printf("[DEBUG] langserver: SignatureHelp")
return nil, notImplemented("SignatureHelp")
}
func (s *server) Definition(ctx context.Context, req *lsp.TextDocumentPositionParams) ([]lsp.Location, error) {
log.Printf("[DEBUG] langserver: Definition")
u := uri(req.TextDocument.URI)
ref := s.fs.ResolveRefAtPos(u, req.Position)
if ref == nil {
return nil, nil
}
loc := s.fs.FindDefinition(u, ref)
if loc.URI == "" {
return nil, nil
}
return []lsp.Location{loc}, nil
}
func (s *server) TypeDefinition(context.Context, *lsp.TextDocumentPositionParams) ([]lsp.Location, error) {
log.Printf("[DEBUG] langserver: TypeDefinition")
return nil, notImplemented("TypeDefinition")
}
func (s *server) Implementation(context.Context, *lsp.TextDocumentPositionParams) ([]lsp.Location, error) {
log.Printf("[DEBUG] langserver: Implementation")
return nil, notImplemented("Implementation")
}
func (s *server) References(context.Context, *lsp.ReferenceParams) ([]lsp.Location, error) {
log.Printf("[DEBUG] langserver: References")
return nil, notImplemented("References")
}
func (s *server) DocumentHighlight(context.Context, *lsp.TextDocumentPositionParams) ([]lsp.DocumentHighlight, error) {
log.Printf("[DEBUG] langserver: DocumentHighlight")
return nil, notImplemented("DocumentHighlight")
}
func (s *server) DocumentSymbol(context.Context, *lsp.DocumentSymbolParams) ([]lsp.DocumentSymbol, error) {
log.Printf("[DEBUG] langserver: DocumentSymbol")
return nil, notImplemented("DocumentSymbol")
}
func (s *server) CodeAction(context.Context, *lsp.CodeActionParams) ([]lsp.CodeAction, error) {
log.Printf("[DEBUG] langserver: CodeAction")
return nil, notImplemented("CodeAction")
}
func (s *server) CodeLens(context.Context, *lsp.CodeLensParams) ([]lsp.CodeLens, error) {
log.Printf("[DEBUG] langserver: CodeLens")
return nil, notImplemented("CodeLens")
}
func (s *server) CodeLensResolve(context.Context, *lsp.CodeLens) (*lsp.CodeLens, error) {
log.Printf("[DEBUG] langserver: CodeLensResolve")
return nil, notImplemented("CodeLensResolve")
}
func (s *server) DocumentLink(context.Context, *lsp.DocumentLinkParams) ([]lsp.DocumentLink, error) {
return nil, nil // Ignore; we don't recognize links in any document
}
func (s *server) DocumentLinkResolve(context.Context, *lsp.DocumentLink) (*lsp.DocumentLink, error) {
log.Printf("[DEBUG] langserver: DocumentLinkResolve")
return nil, notImplemented("DocumentLinkResolve")
}
func (s *server) DocumentColor(context.Context, *lsp.DocumentColorParams) ([]lsp.ColorInformation, error) {
log.Printf("[DEBUG] langserver: DocumentColor")
return nil, notImplemented("DocumentColor")
}
func (s *server) ColorPresentation(context.Context, *lsp.ColorPresentationParams) ([]lsp.ColorPresentation, error) {
log.Printf("[DEBUG] langserver: ColorPresentation")
return nil, notImplemented("ColorPresentation")
}
func (s *server) Formatting(ctx context.Context, req *lsp.DocumentFormattingParams) ([]lsp.TextEdit, error) {
log.Printf("[DEBUG] langserver: Formatting")
u := uri(req.TextDocument.URI)
return s.fs.Format(u)
}
func (s *server) RangeFormatting(context.Context, *lsp.DocumentRangeFormattingParams) ([]lsp.TextEdit, error) {
log.Printf("[DEBUG] langserver: RangeFormatting")
return nil, notImplemented("RangeFormatting")
}
func (s *server) OnTypeFormatting(context.Context, *lsp.DocumentOnTypeFormattingParams) ([]lsp.TextEdit, error) {
log.Printf("[DEBUG] langserver: OnTypeFormatting")
return nil, notImplemented("OnTypeFormatting")
}
func (s *server) Rename(context.Context, *lsp.RenameParams) ([]lsp.WorkspaceEdit, error) {
log.Printf("[DEBUG] langserver: Rename")
return nil, notImplemented("Rename")
}
func (s *server) FoldingRanges(context.Context, *lsp.FoldingRangeRequestParam) ([]lsp.FoldingRange, error) {
log.Printf("[DEBUG] langserver: FoldingRanges")
return nil, notImplemented("FoldingRanges")
}