github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/internal/lsp/workspace.go (about) 1 // Copyright 2019 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 6 7 import ( 8 "context" 9 10 "github.com/jhump/golang-x-tools/internal/lsp/protocol" 11 "github.com/jhump/golang-x-tools/internal/lsp/source" 12 "github.com/jhump/golang-x-tools/internal/span" 13 errors "golang.org/x/xerrors" 14 ) 15 16 func (s *Server) didChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error { 17 event := params.Event 18 for _, folder := range event.Removed { 19 view := s.session.View(folder.Name) 20 if view != nil { 21 view.Shutdown(ctx) 22 } else { 23 return errors.Errorf("view %s for %v not found", folder.Name, folder.URI) 24 } 25 } 26 return s.addFolders(ctx, event.Added) 27 } 28 29 var wsIndex int64 30 31 func (s *Server) addView(ctx context.Context, name string, uri span.URI) (source.Snapshot, func(), error) { 32 s.stateMu.Lock() 33 state := s.state 34 s.stateMu.Unlock() 35 if state < serverInitialized { 36 return nil, func() {}, errors.Errorf("addView called before server initialized") 37 } 38 options := s.session.Options().Clone() 39 if err := s.fetchConfig(ctx, name, uri, options); err != nil { 40 return nil, func() {}, err 41 } 42 _, snapshot, release, err := s.session.NewView(ctx, name, uri, options) 43 return snapshot, release, err 44 } 45 46 func (s *Server) didChangeConfiguration(ctx context.Context, _ *protocol.DidChangeConfigurationParams) error { 47 // Apply any changes to the session-level settings. 48 options := s.session.Options().Clone() 49 semanticTokensRegistered := options.SemanticTokens 50 if err := s.fetchConfig(ctx, "", "", options); err != nil { 51 return err 52 } 53 s.session.SetOptions(options) 54 55 // Go through each view, getting and updating its configuration. 56 for _, view := range s.session.Views() { 57 options := s.session.Options().Clone() 58 if err := s.fetchConfig(ctx, view.Name(), view.Folder(), options); err != nil { 59 return err 60 } 61 view, err := view.SetOptions(ctx, options) 62 if err != nil { 63 return err 64 } 65 go func() { 66 snapshot, release := view.Snapshot(ctx) 67 defer release() 68 s.diagnoseDetached(snapshot) 69 }() 70 } 71 72 registration := semanticTokenRegistration(options.SemanticTypes, options.SemanticMods) 73 // Update any session-specific registrations or unregistrations. 74 if !semanticTokensRegistered && options.SemanticTokens { 75 if err := s.client.RegisterCapability(ctx, &protocol.RegistrationParams{ 76 Registrations: []protocol.Registration{registration}, 77 }); err != nil { 78 return err 79 } 80 } else if semanticTokensRegistered && !options.SemanticTokens { 81 if err := s.client.UnregisterCapability(ctx, &protocol.UnregistrationParams{ 82 Unregisterations: []protocol.Unregistration{ 83 { 84 ID: registration.ID, 85 Method: registration.Method, 86 }, 87 }, 88 }); err != nil { 89 return err 90 } 91 } 92 return nil 93 } 94 95 func semanticTokenRegistration(tokenTypes, tokenModifiers []string) protocol.Registration { 96 return protocol.Registration{ 97 ID: "textDocument/semanticTokens", 98 Method: "textDocument/semanticTokens", 99 RegisterOptions: &protocol.SemanticTokensOptions{ 100 Legend: protocol.SemanticTokensLegend{ 101 // TODO(pjw): trim these to what we use (and an unused one 102 // at position 0 of TokTypes, to catch typos) 103 TokenTypes: tokenTypes, 104 TokenModifiers: tokenModifiers, 105 }, 106 Full: true, 107 Range: true, 108 }, 109 } 110 }