1// Copyright 2025 CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cache
16
17import (
18 "fmt"
19
20 "cuelang.org/go/internal/golangorgx/gopls/protocol"
21 "cuelang.org/go/internal/golangorgx/gopls/settings"
22)
23
24// A WorkspaceFolder corresponds to an LSP Workspace Folder. A single
25// workspace is configured with one or more workspace folders. Each
26// folder can have its own options, for which the server can query the
27// editor/client.
28type WorkspaceFolder struct {
29 dir protocol.DocumentURI
30 name string // decorative name for UI; not necessarily unique
31 options *settings.Options
32}
33
34// NewWorkspaceFolder creates a new workspace folder. The name is
35// entirely decorative and does not have any semantics attached to it.
36func NewWorkspaceFolder(dir protocol.DocumentURI, name string) (*WorkspaceFolder, error) {
37 dirPath := dir.Path()
38 err := checkPathValid(dirPath)
39 if err != nil {
40 return nil, fmt.Errorf("invalid workspace folder path %v: %w; check that the spelling of the configured workspace folder path agrees with the spelling reported by the operating system", dirPath, err)
41 }
42
43 return &WorkspaceFolder{
44 dir: dir,
45 name: name,
46 }, nil
47}
48
49// UpdateOptions sets the folders options to opts. The caller should
50// not modify the contents of opts after calling this method.
51func (wf *WorkspaceFolder) UpdateOptions(opts *settings.Options) {
52 wf.options = opts
53}
54
55// FileWatchingGlobPatterns adds a pattern for watching the folder to
56// the given patterns map and reports whether this folder requires
57// subdirectories to be watched explicitly.
58func (wf *WorkspaceFolder) FileWatchingGlobPatterns(patterns map[protocol.RelativePattern]struct{}) bool {
59 const watchCueFiles = "**/*.cue"
60
61 patterns[protocol.RelativePattern{
62 BaseURI: wf.dir,
63 Pattern: watchCueFiles,
64 }] = struct{}{}
65
66 return wf.watchSubdirs()
67}
68
69func (s *WorkspaceFolder) watchSubdirs() bool {
70 options := s.options
71 switch p := options.SubdirWatchPatterns; p {
72 case settings.SubdirWatchPatternsOn:
73 return true
74 case settings.SubdirWatchPatternsOff:
75 return false
76 case settings.SubdirWatchPatternsAuto:
77 // See the documentation of
78 // [settings.InternalOptions.SubdirWatchPatterns] for an
79 // explanation of why VS Code gets a different default value
80 // here.
81 //
82 // Unfortunately, there is no authoritative list of client names, nor any
83 // requirements that client names do not change. We should update the VS
84 // Code extension to set a default value of "subdirWatchPatterns" to "on",
85 // so that this workaround is only temporary.
86 const vscodeName = "Visual Studio Code"
87 if options.ClientInfo != nil && options.ClientInfo.Name == vscodeName {
88 return true
89 }
90 return false
91 default:
92 return false
93 }
94}