cuelang.org/go@v0.13.0/internal/golangorgx/gopls/server/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 server 6 7 import ( 8 "context" 9 "fmt" 10 "sync" 11 12 "cuelang.org/go/internal/golangorgx/gopls/cache" 13 "cuelang.org/go/internal/golangorgx/gopls/protocol" 14 "cuelang.org/go/internal/golangorgx/tools/event" 15 ) 16 17 func (s *server) DidChangeWorkspaceFolders(ctx context.Context, params *protocol.DidChangeWorkspaceFoldersParams) error { 18 // Per the comment in [server.Initialize], we only support a single 19 // WorkspaceFolder for now. More precisely, the call to Initialize must have 20 // a single WorkspaceFolder. Therefore a notification via 21 // DidChangeWorkspaceFolders must not cause that folder to change (because 22 // that is the invariant we are maintaining for now). 23 // 24 // So for now we simply error in case there is any DidChangeWorkspaceFolders 25 // notification, rather than trying to be smart and work out "has the folder 26 // change?". If this proves to be too simplistic or restrictive, then we can 27 // revisit as part of removing this constraint. 28 // 29 // When we do add such support, we need to be how/if/where logic for 30 // deduping views comes in. 31 // 32 // Ensure this logic is consistent with [server.Initialize]. 33 return fmt.Errorf("cue lsp only supports a single WorkspaceFolder for now") 34 } 35 36 // addView returns a Snapshot and a release function that must be called when 37 // the snapshot is no longer needed. 38 func (s *server) addView(ctx context.Context, name string, dir protocol.DocumentURI) (*cache.Snapshot, func(), error) { 39 s.stateMu.Lock() 40 state := s.state 41 s.stateMu.Unlock() 42 if state < serverInitialized { 43 return nil, nil, fmt.Errorf("addView called before server initialized") 44 } 45 folder, err := s.newFolder(ctx, dir, name) 46 if err != nil { 47 return nil, nil, err 48 } 49 _, snapshot, release, err := s.session.NewView(ctx, folder) 50 return snapshot, release, err 51 } 52 53 func (s *server) DidChangeConfiguration(ctx context.Context, _ *protocol.DidChangeConfigurationParams) error { 54 ctx, done := event.Start(ctx, "lsp.Server.didChangeConfiguration") 55 defer done() 56 57 var wg sync.WaitGroup 58 wg.Add(1) 59 defer wg.Done() 60 if s.Options().VerboseWorkDoneProgress { 61 work := s.progress.Start(ctx, DiagnosticWorkTitle(FromDidChangeConfiguration), "Calculating diagnostics...", nil, nil) 62 go func() { 63 wg.Wait() 64 work.End(ctx, "Done.") 65 }() 66 } 67 68 // Apply any changes to the session-level settings. 69 options, err := s.fetchFolderOptions(ctx, "") 70 if err != nil { 71 return err 72 } 73 s.SetOptions(options) 74 75 // Collect options for all workspace folders. 76 seen := make(map[protocol.DocumentURI]bool) 77 var newFolders []*cache.Folder 78 for _, view := range s.session.Views() { 79 folder := view.Folder() 80 if seen[folder.Dir] { 81 continue 82 } 83 seen[folder.Dir] = true 84 newFolder, err := s.newFolder(ctx, folder.Dir, folder.Name) 85 if err != nil { 86 return err 87 } 88 newFolders = append(newFolders, newFolder) 89 } 90 s.session.UpdateFolders(ctx, newFolders) 91 92 // The view set may have been updated above. 93 viewsToDiagnose := make(map[*cache.View][]protocol.DocumentURI) 94 for _, view := range s.session.Views() { 95 viewsToDiagnose[view] = nil 96 } 97 98 modCtx, modID := s.needsDiagnosis(ctx, viewsToDiagnose) 99 wg.Add(1) 100 go func() { 101 s.diagnoseChangedViews(modCtx, modID, viewsToDiagnose, FromDidChangeConfiguration) 102 wg.Done() 103 }() 104 105 return nil 106 }