Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / server.go
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
5 // Package lsp implements LSP for gopls.
6 package lsp
7
8 import (
9         "context"
10         "fmt"
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/span"
17         errors "golang.org/x/xerrors"
18 )
19
20 const concurrentAnalyses = 1
21
22 // NewServer creates an LSP server and binds it to handle incoming client
23 // messages on on the supplied stream.
24 func NewServer(session source.Session, client protocol.Client) *Server {
25         return &Server{
26                 delivered:            make(map[span.URI]sentDiagnostics),
27                 gcOptimizatonDetails: make(map[span.URI]struct{}),
28                 watchedDirectories:   make(map[span.URI]struct{}),
29                 changedFiles:         make(map[span.URI]struct{}),
30                 session:              session,
31                 client:               client,
32                 diagnosticsSema:      make(chan struct{}, concurrentAnalyses),
33                 progress:             newProgressTracker(client),
34                 debouncer:            newDebouncer(),
35         }
36 }
37
38 type serverState int
39
40 const (
41         serverCreated      = serverState(iota)
42         serverInitializing // set once the server has received "initialize" request
43         serverInitialized  // set once the server has received "initialized" request
44         serverShutDown
45 )
46
47 func (s serverState) String() string {
48         switch s {
49         case serverCreated:
50                 return "created"
51         case serverInitializing:
52                 return "initializing"
53         case serverInitialized:
54                 return "initialized"
55         case serverShutDown:
56                 return "shutDown"
57         }
58         return fmt.Sprintf("(unknown state: %d)", int(s))
59 }
60
61 // Server implements the protocol.Server interface.
62 type Server struct {
63         client protocol.Client
64
65         stateMu sync.Mutex
66         state   serverState
67
68         session source.Session
69
70         // notifications generated before serverInitialized
71         notifications []*protocol.ShowMessageParams
72
73         // changedFiles tracks files for which there has been a textDocument/didChange.
74         changedFilesMu sync.Mutex
75         changedFiles   map[span.URI]struct{}
76
77         // folders is only valid between initialize and initialized, and holds the
78         // set of folders to build views for when we are ready
79         pendingFolders []protocol.WorkspaceFolder
80
81         // watchedDirectories is the set of directories that we have requested that
82         // the client watch on disk. It will be updated as the set of directories
83         // that the server should watch changes.
84         watchedDirectoriesMu   sync.Mutex
85         watchedDirectories     map[span.URI]struct{}
86         watchRegistrationCount uint64
87
88         // delivered is a cache of the diagnostics that the server has sent.
89         deliveredMu sync.Mutex
90         delivered   map[span.URI]sentDiagnostics
91
92         // gcOptimizationDetails describes the packages for which we want
93         // optimization details to be included in the diagnostics. The key is the
94         // directory of the package.
95         gcOptimizationDetailsMu sync.Mutex
96         gcOptimizatonDetails    map[span.URI]struct{}
97
98         // diagnosticsSema limits the concurrency of diagnostics runs, which can be expensive.
99         diagnosticsSema chan struct{}
100
101         progress *progressTracker
102
103         // debouncer is used for debouncing diagnostics.
104         debouncer *debouncer
105 }
106
107 // sentDiagnostics is used to cache diagnostics that have been sent for a given file.
108 type sentDiagnostics struct {
109         id           source.VersionedFileIdentity
110         sorted       []*source.Diagnostic
111         withAnalysis bool
112         snapshotID   uint64
113 }
114
115 func (s *Server) workDoneProgressCancel(ctx context.Context, params *protocol.WorkDoneProgressCancelParams) error {
116         return s.progress.cancel(ctx, params.Token)
117 }
118
119 func (s *Server) nonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
120         paramMap := params.(map[string]interface{})
121         if method == "gopls/diagnoseFiles" {
122                 for _, file := range paramMap["files"].([]interface{}) {
123                         snapshot, fh, ok, release, err := s.beginFileRequest(ctx, protocol.DocumentURI(file.(string)), source.UnknownKind)
124                         defer release()
125                         if !ok {
126                                 return nil, err
127                         }
128
129                         fileID, diagnostics, err := source.FileDiagnostics(ctx, snapshot, fh.URI())
130                         if err != nil {
131                                 return nil, err
132                         }
133                         if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
134                                 URI:         protocol.URIFromSpanURI(fh.URI()),
135                                 Diagnostics: toProtocolDiagnostics(diagnostics),
136                                 Version:     fileID.Version,
137                         }); err != nil {
138                                 return nil, err
139                         }
140                 }
141                 if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
142                         URI: "gopls://diagnostics-done",
143                 }); err != nil {
144                         return nil, err
145                 }
146                 return struct{}{}, nil
147         }
148         return nil, notImplemented(method)
149 }
150
151 func notImplemented(method string) error {
152         return errors.Errorf("%w: %q not yet implemented", jsonrpc2.ErrMethodNotFound, method)
153 }
154
155 //go:generate helper/helper -d protocol/tsserver.go -o server_gen.go -u .