mirror of
https://github.com/golang/go
synced 2024-09-30 16:28:32 -06:00
internal/lsp: lowercase drive letters on Windows to fix file watching
This is a work-around for https://github.com/microsoft/vscode/issues/104387. We now always lowercase the drive letter on Windows. This CL also fixes a bug introduced by CL 245327, which caused URIs to be used instead of paths in the GlobPattern. We really need VS Code integration tests for this (golang/vscode-go#404). Updates golang/go#40661 Change-Id: I21be6d929288cfe41168cea34001fc2f41ac6c8b Reviewed-on: https://go-review.googlesource.com/c/tools/+/247684 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
parent
eb8585a966
commit
3986990901
@ -11,6 +11,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"golang.org/x/tools/internal/event"
|
"golang.org/x/tools/internal/event"
|
||||||
@ -46,6 +48,10 @@ func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitializ
|
|||||||
if params.RootURI != "" && !params.RootURI.SpanURI().IsFile() {
|
if params.RootURI != "" && !params.RootURI.SpanURI().IsFile() {
|
||||||
return nil, fmt.Errorf("unsupported URI scheme: %v (gopls only supports file URIs)", params.RootURI)
|
return nil, fmt.Errorf("unsupported URI scheme: %v (gopls only supports file URIs)", params.RootURI)
|
||||||
}
|
}
|
||||||
|
if params.RootURI != "" {
|
||||||
|
s.rootURI = params.RootURI.SpanURI()
|
||||||
|
}
|
||||||
|
|
||||||
for _, folder := range params.WorkspaceFolders {
|
for _, folder := range params.WorkspaceFolders {
|
||||||
uri := span.URIFromURI(folder.URI)
|
uri := span.URIFromURI(folder.URI)
|
||||||
if !uri.IsFile() {
|
if !uri.IsFile() {
|
||||||
@ -144,20 +150,6 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
|
|||||||
options := s.session.Options()
|
options := s.session.Options()
|
||||||
defer func() { s.session.SetOptions(options) }()
|
defer func() { s.session.SetOptions(options) }()
|
||||||
|
|
||||||
var registrations []protocol.Registration
|
|
||||||
if options.ConfigurationSupported && options.DynamicConfigurationSupported {
|
|
||||||
registrations = append(registrations,
|
|
||||||
protocol.Registration{
|
|
||||||
ID: "workspace/didChangeConfiguration",
|
|
||||||
Method: "workspace/didChangeConfiguration",
|
|
||||||
},
|
|
||||||
protocol.Registration{
|
|
||||||
ID: "workspace/didChangeWorkspaceFolders",
|
|
||||||
Method: "workspace/didChangeWorkspaceFolders",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this event logging may be unnecessary.
|
// TODO: this event logging may be unnecessary.
|
||||||
// The version info is included in the initialize response.
|
// The version info is included in the initialize response.
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
@ -169,9 +161,18 @@ func (s *Server) initialized(ctx context.Context, params *protocol.InitializedPa
|
|||||||
}
|
}
|
||||||
s.pendingFolders = nil
|
s.pendingFolders = nil
|
||||||
|
|
||||||
if len(registrations) > 0 {
|
if options.ConfigurationSupported && options.DynamicConfigurationSupported {
|
||||||
if err := s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
|
if err := s.client.RegisterCapability(ctx, &protocol.RegistrationParams{
|
||||||
Registrations: registrations,
|
Registrations: []protocol.Registration{
|
||||||
|
{
|
||||||
|
ID: "workspace/didChangeConfiguration",
|
||||||
|
Method: "workspace/didChangeConfiguration",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "workspace/didChangeWorkspaceFolders",
|
||||||
|
Method: "workspace/didChangeWorkspaceFolders",
|
||||||
|
},
|
||||||
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -322,10 +323,25 @@ func (s *Server) registerWatchedDirectoriesLocked(ctx context.Context, dirs map[
|
|||||||
for k := range s.watchedDirectories {
|
for k := range s.watchedDirectories {
|
||||||
delete(s.watchedDirectories, k)
|
delete(s.watchedDirectories, k)
|
||||||
}
|
}
|
||||||
var watchers []protocol.FileSystemWatcher
|
// Work-around microsoft/vscode#100870 by making sure that we are,
|
||||||
|
// at least, watching the user's entire workspace. This will still be
|
||||||
|
// applied to every folder in the workspace.
|
||||||
|
watchers := []protocol.FileSystemWatcher{{
|
||||||
|
GlobPattern: "**/*.{go,mod,sum}",
|
||||||
|
Kind: float64(protocol.WatchChange + protocol.WatchDelete + protocol.WatchCreate),
|
||||||
|
}}
|
||||||
for dir := range dirs {
|
for dir := range dirs {
|
||||||
|
filename := dir.Filename()
|
||||||
|
// If the directory is within the root URI, we're already watching it
|
||||||
|
// via the relative path above.
|
||||||
|
if isSubdirectory(s.rootURI.Filename(), filename) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// If microsoft/vscode#100870 is resolved before
|
||||||
|
// microsoft/vscode#104387, we will need a work-around for Windows
|
||||||
|
// drive letter casing.
|
||||||
watchers = append(watchers, protocol.FileSystemWatcher{
|
watchers = append(watchers, protocol.FileSystemWatcher{
|
||||||
GlobPattern: fmt.Sprintf("%s/**/*.{go,mod,sum}", dir),
|
GlobPattern: fmt.Sprintf("%s/**/*.{go,mod,sum}", filename),
|
||||||
Kind: float64(protocol.WatchChange + protocol.WatchDelete + protocol.WatchCreate),
|
Kind: float64(protocol.WatchChange + protocol.WatchDelete + protocol.WatchCreate),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -348,6 +364,11 @@ func (s *Server) registerWatchedDirectoriesLocked(ctx context.Context, dirs map[
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isSubdirectory(root, leaf string) bool {
|
||||||
|
rel, err := filepath.Rel(root, leaf)
|
||||||
|
return err == nil && !strings.HasPrefix(rel, "..")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) fetchConfig(ctx context.Context, name string, folder span.URI, o *source.Options) error {
|
func (s *Server) fetchConfig(ctx context.Context, name string, folder span.URI, o *source.Options) error {
|
||||||
if !s.session.Options().ConfigurationSupported {
|
if !s.session.Options().ConfigurationSupported {
|
||||||
return nil
|
return nil
|
||||||
|
@ -64,6 +64,9 @@ type Server struct {
|
|||||||
|
|
||||||
session source.Session
|
session source.Session
|
||||||
|
|
||||||
|
// rootURI is the root of the workspace opened in the editor (if any).
|
||||||
|
rootURI span.URI
|
||||||
|
|
||||||
// changedFiles tracks files for which there has been a textDocument/didChange.
|
// changedFiles tracks files for which there has been a textDocument/didChange.
|
||||||
changedFilesMu sync.Mutex
|
changedFilesMu sync.Mutex
|
||||||
changedFiles map[span.URI]struct{}
|
changedFiles map[span.URI]struct{}
|
||||||
|
@ -160,7 +160,7 @@ func isWindowsDrivePath(path string) bool {
|
|||||||
|
|
||||||
// isWindowsDriveURI returns true if the file URI is of the format used by
|
// isWindowsDriveURI returns true if the file URI is of the format used by
|
||||||
// Windows URIs. The url.Parse package does not specially handle Windows paths
|
// Windows URIs. The url.Parse package does not specially handle Windows paths
|
||||||
// (see golang/go#6027). We check if the URI path has a drive prefix (e.g. "/C:").
|
// (see golang/go#6027), so we check if the URI path has a drive prefix (e.g. "/C:").
|
||||||
func isWindowsDriveURIPath(uri string) bool {
|
func isWindowsDriveURIPath(uri string) bool {
|
||||||
if len(uri) < 4 {
|
if len(uri) < 4 {
|
||||||
return false
|
return false
|
||||||
|
Loading…
Reference in New Issue
Block a user