1// Copyright 2018 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package lsp 6 7import ( 8 "context" 9 "fmt" 10 "net" 11 "sync" 12 13 "golang.org/x/tools/internal/jsonrpc2" 14 "golang.org/x/tools/internal/lsp/protocol" 15 "golang.org/x/tools/internal/lsp/source" 16 "golang.org/x/tools/internal/lsp/xlog" 17 "golang.org/x/tools/internal/span" 18) 19 20// NewClientServer 21func NewClientServer(cache source.Cache, client protocol.Client) *Server { 22 return &Server{ 23 client: client, 24 session: cache.NewSession(xlog.New(protocol.NewLogger(client))), 25 } 26} 27 28// NewServer starts an LSP server on the supplied stream, and waits until the 29// stream is closed. 30func NewServer(cache source.Cache, stream jsonrpc2.Stream) *Server { 31 s := &Server{} 32 var log xlog.Logger 33 s.Conn, s.client, log = protocol.NewServer(stream, s) 34 s.session = cache.NewSession(log) 35 return s 36} 37 38// RunServerOnPort starts an LSP server on the given port and does not exit. 39// This function exists for debugging purposes. 40func RunServerOnPort(ctx context.Context, cache source.Cache, port int, h func(s *Server)) error { 41 return RunServerOnAddress(ctx, cache, fmt.Sprintf(":%v", port), h) 42} 43 44// RunServerOnPort starts an LSP server on the given port and does not exit. 45// This function exists for debugging purposes. 46func RunServerOnAddress(ctx context.Context, cache source.Cache, addr string, h func(s *Server)) error { 47 ln, err := net.Listen("tcp", addr) 48 if err != nil { 49 return err 50 } 51 for { 52 conn, err := ln.Accept() 53 if err != nil { 54 return err 55 } 56 h(NewServer(cache, jsonrpc2.NewHeaderStream(conn, conn))) 57 } 58} 59 60func (s *Server) Run(ctx context.Context) error { 61 return s.Conn.Run(ctx) 62} 63 64type Server struct { 65 Conn *jsonrpc2.Conn 66 client protocol.Client 67 68 initializedMu sync.Mutex 69 isInitialized bool // set once the server has received "initialize" request 70 71 // Configurations. 72 // TODO(rstambler): Separate these into their own struct? 73 usePlaceholders bool 74 noDocsOnHover bool 75 useDeepCompletions bool 76 insertTextFormat protocol.InsertTextFormat 77 configurationSupported bool 78 dynamicConfigurationSupported bool 79 preferredContentFormat protocol.MarkupKind 80 disabledAnalyses map[string]struct{} 81 82 textDocumentSyncKind protocol.TextDocumentSyncKind 83 84 session source.Session 85 86 // undelivered is a cache of any diagnostics that the server 87 // failed to deliver for some reason. 88 undeliveredMu sync.Mutex 89 undelivered map[span.URI][]source.Diagnostic 90} 91 92// General 93 94func (s *Server) Initialize(ctx context.Context, params *protocol.InitializeParams) (*protocol.InitializeResult, error) { 95 return s.initialize(ctx, params) 96} 97 98func (s *Server) Initialized(ctx context.Context, params *protocol.InitializedParams) error { 99 return s.initialized(ctx, params) 100} 101 102func (s *Server) Shutdown(ctx context.Context) error { 103 return s.shutdown(ctx) 104} 105 106func (s *Server) Exit(ctx context.Context) error { 107 return s.exit(ctx) 108} 109 110// Workspace 111 112func (s *Server) DidChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error { 113 return s.changeFolders(ctx, params.Event) 114} 115 116func (s *Server) DidChangeConfiguration(context.Context, *protocol.DidChangeConfigurationParams) error { 117 return notImplemented("DidChangeConfiguration") 118} 119 120func (s *Server) DidChangeWatchedFiles(context.Context, *protocol.DidChangeWatchedFilesParams) error { 121 return notImplemented("DidChangeWatchedFiles") 122} 123 124func (s *Server) Symbol(context.Context, *protocol.WorkspaceSymbolParams) ([]protocol.SymbolInformation, error) { 125 return nil, notImplemented("Symbol") 126} 127 128func (s *Server) ExecuteCommand(context.Context, *protocol.ExecuteCommandParams) (interface{}, error) { 129 return nil, notImplemented("ExecuteCommand") 130} 131 132// Text Synchronization 133 134func (s *Server) DidOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error { 135 return s.didOpen(ctx, params) 136} 137 138func (s *Server) DidChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error { 139 return s.didChange(ctx, params) 140} 141 142func (s *Server) WillSave(context.Context, *protocol.WillSaveTextDocumentParams) error { 143 return notImplemented("WillSave") 144} 145 146func (s *Server) WillSaveWaitUntil(context.Context, *protocol.WillSaveTextDocumentParams) ([]protocol.TextEdit, error) { 147 return nil, notImplemented("WillSaveWaitUntil") 148} 149 150func (s *Server) DidSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error { 151 return s.didSave(ctx, params) 152} 153 154func (s *Server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error { 155 return s.didClose(ctx, params) 156} 157 158// Language Features 159 160func (s *Server) Completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) { 161 return s.completion(ctx, params) 162} 163 164func (s *Server) CompletionResolve(context.Context, *protocol.CompletionItem) (*protocol.CompletionItem, error) { 165 return nil, notImplemented("CompletionResolve") 166} 167 168func (s *Server) Hover(ctx context.Context, params *protocol.TextDocumentPositionParams) (*protocol.Hover, error) { 169 return s.hover(ctx, params) 170} 171 172func (s *Server) SignatureHelp(ctx context.Context, params *protocol.TextDocumentPositionParams) (*protocol.SignatureHelp, error) { 173 return s.signatureHelp(ctx, params) 174} 175 176func (s *Server) Definition(ctx context.Context, params *protocol.TextDocumentPositionParams) ([]protocol.Location, error) { 177 return s.definition(ctx, params) 178} 179 180func (s *Server) TypeDefinition(ctx context.Context, params *protocol.TextDocumentPositionParams) ([]protocol.Location, error) { 181 return s.typeDefinition(ctx, params) 182} 183 184func (s *Server) Implementation(context.Context, *protocol.TextDocumentPositionParams) ([]protocol.Location, error) { 185 return nil, notImplemented("Implementation") 186} 187 188func (s *Server) References(ctx context.Context, params *protocol.ReferenceParams) ([]protocol.Location, error) { 189 return s.references(ctx, params) 190} 191 192func (s *Server) DocumentHighlight(ctx context.Context, params *protocol.TextDocumentPositionParams) ([]protocol.DocumentHighlight, error) { 193 return s.documentHighlight(ctx, params) 194} 195 196func (s *Server) DocumentSymbol(ctx context.Context, params *protocol.DocumentSymbolParams) ([]protocol.DocumentSymbol, error) { 197 return s.documentSymbol(ctx, params) 198} 199 200func (s *Server) CodeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) { 201 return s.codeAction(ctx, params) 202} 203 204func (s *Server) CodeLens(context.Context, *protocol.CodeLensParams) ([]protocol.CodeLens, error) { 205 return nil, nil // ignore 206} 207 208func (s *Server) ResolveCodeLens(context.Context, *protocol.CodeLens) (*protocol.CodeLens, error) { 209 return nil, notImplemented("ResolveCodeLens") 210} 211 212func (s *Server) DocumentLink(ctx context.Context, params *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) { 213 return s.documentLink(ctx, params) 214} 215 216func (s *Server) ResolveDocumentLink(context.Context, *protocol.DocumentLink) (*protocol.DocumentLink, error) { 217 return nil, notImplemented("ResolveDocumentLink") 218} 219 220func (s *Server) DocumentColor(context.Context, *protocol.DocumentColorParams) ([]protocol.ColorInformation, error) { 221 return nil, notImplemented("DocumentColor") 222} 223 224func (s *Server) ColorPresentation(context.Context, *protocol.ColorPresentationParams) ([]protocol.ColorPresentation, error) { 225 return nil, notImplemented("ColorPresentation") 226} 227 228func (s *Server) Formatting(ctx context.Context, params *protocol.DocumentFormattingParams) ([]protocol.TextEdit, error) { 229 return s.formatting(ctx, params) 230} 231 232func (s *Server) RangeFormatting(ctx context.Context, params *protocol.DocumentRangeFormattingParams) ([]protocol.TextEdit, error) { 233 return nil, notImplemented("RangeFormatting") 234} 235 236func (s *Server) OnTypeFormatting(context.Context, *protocol.DocumentOnTypeFormattingParams) ([]protocol.TextEdit, error) { 237 return nil, notImplemented("OnTypeFormatting") 238} 239 240func (s *Server) Rename(ctx context.Context, params *protocol.RenameParams) (*protocol.WorkspaceEdit, error) { 241 return s.rename(ctx, params) 242} 243 244func (s *Server) Declaration(context.Context, *protocol.TextDocumentPositionParams) ([]protocol.DeclarationLink, error) { 245 return nil, notImplemented("Declaration") 246} 247 248func (s *Server) FoldingRange(context.Context, *protocol.FoldingRangeParams) ([]protocol.FoldingRange, error) { 249 return nil, notImplemented("FoldingRange") 250} 251 252func (s *Server) LogTraceNotification(context.Context, *protocol.LogTraceParams) error { 253 return notImplemented("LogtraceNotification") 254} 255 256func (s *Server) PrepareRename(context.Context, *protocol.TextDocumentPositionParams) (*protocol.Range, error) { 257 return nil, notImplemented("PrepareRename") 258} 259 260func (s *Server) Resolve(context.Context, *protocol.CompletionItem) (*protocol.CompletionItem, error) { 261 return nil, notImplemented("Resolve") 262} 263 264func (s *Server) SetTraceNotification(context.Context, *protocol.SetTraceParams) error { 265 return notImplemented("SetTraceNotification") 266} 267func notImplemented(method string) *jsonrpc2.Error { 268 return jsonrpc2.NewErrorf(jsonrpc2.CodeMethodNotFound, "method %q not yet implemented", method) 269} 270