diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go index aff5988c..8c05f45a 100644 --- a/internal/lsp/cache/view.go +++ b/internal/lsp/cache/view.go @@ -104,7 +104,7 @@ func (v *View) parse(uri source.URI) error { } return err } - + var foundPkg bool // true if we found a package for uri for _, pkg := range pkgs { if len(pkg.Syntax) == 0 { return fmt.Errorf("no syntax trees for %s", pkg.PkgPath) @@ -118,7 +118,13 @@ func (v *View) parse(uri source.URI) error { f.token = fToken f.ast = fAST f.pkg = pkg + if fURI == uri { + foundPkg = true + } } } + if !foundPkg { + return fmt.Errorf("no package found for %v", uri) + } return nil } diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go index 49743dc0..c7149185 100644 --- a/internal/lsp/diagnostics.go +++ b/internal/lsp/diagnostics.go @@ -13,7 +13,10 @@ import ( ) func (s *server) cacheAndDiagnose(ctx context.Context, uri protocol.DocumentURI, content string) { - sourceURI := fromProtocolURI(uri) + sourceURI, err := fromProtocolURI(uri) + if err != nil { + return // handle error? + } if err := s.setContent(ctx, sourceURI, []byte(content)); err != nil { return // handle error? } diff --git a/internal/lsp/format.go b/internal/lsp/format.go index 8a238099..ec0db161 100644 --- a/internal/lsp/format.go +++ b/internal/lsp/format.go @@ -10,7 +10,11 @@ import ( // formatRange formats a document with a given range. func formatRange(ctx context.Context, v source.View, uri protocol.DocumentURI, rng *protocol.Range) ([]protocol.TextEdit, error) { - f, err := v.GetFile(ctx, fromProtocolURI(uri)) + sourceURI, err := fromProtocolURI(uri) + if err != nil { + return nil, err + } + f, err := v.GetFile(ctx, sourceURI) if err != nil { return nil, err } diff --git a/internal/lsp/imports.go b/internal/lsp/imports.go index 32f3e1ca..2f8f7c1c 100644 --- a/internal/lsp/imports.go +++ b/internal/lsp/imports.go @@ -12,7 +12,11 @@ import ( ) func organizeImports(ctx context.Context, v source.View, uri protocol.DocumentURI) ([]protocol.TextEdit, error) { - f, err := v.GetFile(ctx, fromProtocolURI(uri)) + sourceURI, err := fromProtocolURI(uri) + if err != nil { + return nil, err + } + f, err := v.GetFile(ctx, sourceURI) if err != nil { return nil, err } diff --git a/internal/lsp/position.go b/internal/lsp/position.go index 454eb31f..4b19c784 100644 --- a/internal/lsp/position.go +++ b/internal/lsp/position.go @@ -7,6 +7,7 @@ package lsp import ( "context" "go/token" + "net/url" "golang.org/x/tools/internal/lsp/cache" "golang.org/x/tools/internal/lsp/protocol" @@ -15,15 +16,23 @@ import ( // fromProtocolURI converts a protocol.DocumentURI to a source.URI. // TODO(rstambler): Add logic here to support Windows. -func fromProtocolURI(uri protocol.DocumentURI) source.URI { - return source.URI(uri) +func fromProtocolURI(uri protocol.DocumentURI) (source.URI, error) { + unescaped, err := url.PathUnescape(string(uri)) + if err != nil { + return "", err + } + return source.URI(unescaped), nil } // fromProtocolLocation converts from a protocol location to a source range. // It will return an error if the file of the location was not valid. // It uses fromProtocolRange to convert the start and end positions. func fromProtocolLocation(ctx context.Context, v *cache.View, loc protocol.Location) (source.Range, error) { - f, err := v.GetFile(ctx, fromProtocolURI(loc.URI)) + sourceURI, err := fromProtocolURI(loc.URI) + if err != nil { + return source.Range{}, err + } + f, err := v.GetFile(ctx, sourceURI) if err != nil { return source.Range{}, err } diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 98510de7..2558da21 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -75,10 +75,19 @@ func (s *server) Initialize(ctx context.Context, params *protocol.InitializePara s.snippetsSupported = params.Capabilities.TextDocument.Completion.CompletionItem.SnippetSupport s.signatureHelpEnabled = true - rootPath, err := fromProtocolURI(*params.RootURI).Filename() + var rootURI protocol.DocumentURI + if params.RootURI != nil { + rootURI = *params.RootURI + } + sourceURI, err := fromProtocolURI(rootURI) if err != nil { return nil, err } + rootPath, err := sourceURI.Filename() + if err != nil { + return nil, err + } + s.view = cache.NewView(&packages.Config{ Dir: rootPath, Mode: packages.LoadSyntax, @@ -180,12 +189,20 @@ func (s *server) DidSave(context.Context, *protocol.DidSaveTextDocumentParams) e } func (s *server) DidClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error { - s.setContent(ctx, fromProtocolURI(params.TextDocument.URI), nil) + sourceURI, err := fromProtocolURI(params.TextDocument.URI) + if err != nil { + return err + } + s.setContent(ctx, sourceURI, nil) return nil } func (s *server) Completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) { - f, err := s.view.GetFile(ctx, fromProtocolURI(params.TextDocument.URI)) + sourceURI, err := fromProtocolURI(params.TextDocument.URI) + if err != nil { + return nil, err + } + f, err := s.view.GetFile(ctx, sourceURI) if err != nil { return nil, err } @@ -209,7 +226,11 @@ func (s *server) CompletionResolve(context.Context, *protocol.CompletionItem) (* } func (s *server) Hover(ctx context.Context, params *protocol.TextDocumentPositionParams) (*protocol.Hover, error) { - f, err := s.view.GetFile(ctx, fromProtocolURI(params.TextDocument.URI)) + sourceURI, err := fromProtocolURI(params.TextDocument.URI) + if err != nil { + return nil, err + } + f, err := s.view.GetFile(ctx, sourceURI) if err != nil { return nil, err } @@ -237,7 +258,11 @@ func (s *server) Hover(ctx context.Context, params *protocol.TextDocumentPositio } func (s *server) SignatureHelp(ctx context.Context, params *protocol.TextDocumentPositionParams) (*protocol.SignatureHelp, error) { - f, err := s.view.GetFile(ctx, fromProtocolURI(params.TextDocument.URI)) + sourceURI, err := fromProtocolURI(params.TextDocument.URI) + if err != nil { + return nil, err + } + f, err := s.view.GetFile(ctx, sourceURI) if err != nil { return nil, err } @@ -254,7 +279,11 @@ func (s *server) SignatureHelp(ctx context.Context, params *protocol.TextDocumen } func (s *server) Definition(ctx context.Context, params *protocol.TextDocumentPositionParams) ([]protocol.Location, error) { - f, err := s.view.GetFile(ctx, fromProtocolURI(params.TextDocument.URI)) + sourceURI, err := fromProtocolURI(params.TextDocument.URI) + if err != nil { + return nil, err + } + f, err := s.view.GetFile(ctx, sourceURI) if err != nil { return nil, err } @@ -271,7 +300,11 @@ func (s *server) Definition(ctx context.Context, params *protocol.TextDocumentPo } func (s *server) TypeDefinition(ctx context.Context, params *protocol.TextDocumentPositionParams) ([]protocol.Location, error) { - f, err := s.view.GetFile(ctx, fromProtocolURI(params.TextDocument.URI)) + sourceURI, err := fromProtocolURI(params.TextDocument.URI) + if err != nil { + return nil, err + } + f, err := s.view.GetFile(ctx, sourceURI) if err != nil { return nil, err }