Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / 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                 gcOptimizationDetails: 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         clientPID int
70
71         // notifications generated before serverInitialized
72         notifications []*protocol.ShowMessageParams
73
74         // changedFiles tracks files for which there has been a textDocument/didChange.
75         changedFilesMu sync.Mutex
76         changedFiles   map[span.URI]struct{}
77
78         // folders is only valid between initialize and initialized, and holds the
79         // set of folders to build views for when we are ready
80         pendingFolders []protocol.WorkspaceFolder
81
82         // watchedDirectories is the set of directories that we have requested that
83         // the client watch on disk. It will be updated as the set of directories
84         // that the server should watch changes.
85         watchedDirectoriesMu   sync.Mutex
86         watchedDirectories     map[span.URI]struct{}
87         watchRegistrationCount uint64
88
89         // delivered is a cache of the diagnostics that the server has sent.
90         deliveredMu sync.Mutex
91         delivered   map[span.URI]sentDiagnostics
92
93         // gcOptimizationDetails describes the packages for which we want
94         // optimization details to be included in the diagnostics. The key is the
95         // directory of the package.
96         gcOptimizationDetailsMu sync.Mutex
97         gcOptimizationDetails   map[span.URI]struct{}
98
99         // diagnosticsSema limits the concurrency of diagnostics runs, which can be expensive.
100         diagnosticsSema chan struct{}
101
102         progress *progressTracker
103
104         // debouncer is used for debouncing diagnostics.
105         debouncer *debouncer
106 }
107
108 // sentDiagnostics is used to cache diagnostics that have been sent for a given file.
109 type sentDiagnostics struct {
110         id              source.VersionedFileIdentity
111         sorted          []*source.Diagnostic
112         includeAnalysis bool
113         snapshotID      uint64
114 }
115
116 func (s *Server) workDoneProgressCancel(ctx context.Context, params *protocol.WorkDoneProgressCancelParams) error {
117         return s.progress.cancel(ctx, params.Token)
118 }
119
120 func (s *Server) nonstandardRequest(ctx context.Context, method string, params interface{}) (interface{}, error) {
121         paramMap := params.(map[string]interface{})
122         if method == "gopls/diagnoseFiles" {
123                 for _, file := range paramMap["files"].([]interface{}) {
124                         snapshot, fh, ok, release, err := s.beginFileRequest(ctx, protocol.DocumentURI(file.(string)), source.UnknownKind)
125                         defer release()
126                         if !ok {
127                                 return nil, err
128                         }
129
130                         fileID, diagnostics, err := source.FileDiagnostics(ctx, snapshot, fh.URI())
131                         if err != nil {
132                                 return nil, err
133                         }
134                         if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
135                                 URI:         protocol.URIFromSpanURI(fh.URI()),
136                                 Diagnostics: toProtocolDiagnostics(diagnostics),
137                                 Version:     fileID.Version,
138                         }); err != nil {
139                                 return nil, err
140                         }
141                 }
142                 if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{
143                         URI: "gopls://diagnostics-done",
144                 }); err != nil {
145                         return nil, err
146                 }
147                 return struct{}{}, nil
148         }
149         return nil, notImplemented(method)
150 }
151
152 func notImplemented(method string) error {
153         return errors.Errorf("%w: %q not yet implemented", jsonrpc2.ErrMethodNotFound, method)
154 }
155
156 //go:generate helper/helper -d protocol/tsserver.go -o server_gen.go -u .