diff --git a/gopls/integration/replay/main.go b/gopls/integration/replay/main.go index cd30dd6279..1bd69ac046 100644 --- a/gopls/integration/replay/main.go +++ b/gopls/integration/replay/main.go @@ -68,7 +68,7 @@ func main() { log.Printf("new %d, hist:%s", len(newMsgs), seen.Histogram) ok := make(map[string]int) - f := func(x []*parse.Logmsg, label string, diags map[string][]p.Diagnostic) { + f := func(x []*parse.Logmsg, label string, diags map[p.DocumentURI][]p.Diagnostic) { counts := make(map[parse.MsgType]int) for _, l := range x { if l.Method == "window/logMessage" { @@ -102,9 +102,9 @@ func main() { } log.Printf("%s: %s", label, msg) } - mdiags := make(map[string][]p.Diagnostic) + mdiags := make(map[p.DocumentURI][]p.Diagnostic) f(msgs, "old", mdiags) - vdiags := make(map[string][]p.Diagnostic) + vdiags := make(map[p.DocumentURI][]p.Diagnostic) f(newMsgs, "new", vdiags) buf := []string{} for k := range ok { diff --git a/internal/lsp/cache/errors.go b/internal/lsp/cache/errors.go index 787a43111a..16ddd502f5 100644 --- a/internal/lsp/cache/errors.go +++ b/internal/lsp/cache/errors.go @@ -177,7 +177,7 @@ func toSourceErrorKind(kind packages.ErrorKind) source.ErrorKind { func typeErrorRange(ctx context.Context, fset *token.FileSet, pkg *pkg, pos token.Pos) (span.Span, error) { posn := fset.Position(pos) - ph, _, err := source.FindFileInPackage(pkg, span.FileURI(posn.Filename)) + ph, _, err := source.FindFileInPackage(pkg, span.URIFromPath(posn.Filename)) if err != nil { return span.Span{}, err } @@ -213,7 +213,7 @@ func typeErrorRange(ctx context.Context, fset *token.FileSet, pkg *pkg, pos toke } func scannerErrorRange(ctx context.Context, fset *token.FileSet, pkg *pkg, posn token.Position) (span.Span, error) { - ph, _, err := source.FindFileInPackage(pkg, span.FileURI(posn.Filename)) + ph, _, err := source.FindFileInPackage(pkg, span.URIFromPath(posn.Filename)) if err != nil { return span.Span{}, err } diff --git a/internal/lsp/cache/load.go b/internal/lsp/cache/load.go index 24c11519ed..43b24fc9bc 100644 --- a/internal/lsp/cache/load.go +++ b/internal/lsp/cache/load.go @@ -147,12 +147,12 @@ func (s *snapshot) setMetadata(ctx context.Context, pkgPath packagePath, pkg *pa } for _, filename := range pkg.CompiledGoFiles { - uri := span.FileURI(filename) + uri := span.URIFromPath(filename) m.compiledGoFiles = append(m.compiledGoFiles, uri) s.addID(uri, m.id) } for _, filename := range pkg.GoFiles { - uri := span.FileURI(filename) + uri := span.URIFromPath(filename) m.goFiles = append(m.goFiles, uri) s.addID(uri, m.id) } diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go index 21066992b7..e0b5ac830d 100644 --- a/internal/lsp/cache/view.go +++ b/internal/lsp/cache/view.go @@ -236,7 +236,7 @@ func (v *view) buildBuiltinPackage(ctx context.Context, goFiles []string) error if len(goFiles) != 1 { return errors.Errorf("only expected 1 file, got %v", len(goFiles)) } - uri := span.FileURI(goFiles[0]) + uri := span.URIFromPath(goFiles[0]) v.addIgnoredFile(uri) // to avoid showing diagnostics for builtin.go // Get the FileHandle through the cache to avoid adding it to the snapshot @@ -585,7 +585,7 @@ func (v *view) setBuildInformation(ctx context.Context, folder span.URI, env []s if modFile == os.DevNull { return nil } - v.realMod = span.FileURI(modFile) + v.realMod = span.URIFromPath(modFile) // Now that we have set all required fields, // check if the view has a valid build configuration. @@ -618,7 +618,7 @@ func (v *view) setBuildInformation(ctx context.Context, folder span.URI, env []s if _, err := io.Copy(tempModFile, origFile); err != nil { return err } - v.tempMod = span.FileURI(tempModFile.Name()) + v.tempMod = span.URIFromPath(tempModFile.Name()) // Copy go.sum file as well (if there is one). sumFile := filepath.Join(filepath.Dir(modFile), "go.sum") diff --git a/internal/lsp/cmd/capabilities_test.go b/internal/lsp/cmd/capabilities_test.go index ee7ab58056..a77da87fd7 100644 --- a/internal/lsp/cmd/capabilities_test.go +++ b/internal/lsp/cmd/capabilities_test.go @@ -10,7 +10,6 @@ import ( "golang.org/x/tools/internal/lsp" "golang.org/x/tools/internal/lsp/cache" "golang.org/x/tools/internal/lsp/protocol" - "golang.org/x/tools/internal/span" errors "golang.org/x/xerrors" ) @@ -36,7 +35,7 @@ func TestCapabilities(t *testing.T) { defer c.terminate(ctx) params := &protocol.ParamInitialize{} - params.RootURI = string(span.FileURI(c.Client.app.wd)) + params.RootURI = protocol.URIFromPath(c.Client.app.wd) params.Capabilities.Workspace.Configuration = true // Send an initialize request to the server. @@ -55,7 +54,7 @@ func TestCapabilities(t *testing.T) { } // Open the file on the server side. - uri := protocol.NewURI(span.FileURI(tmpFile)) + uri := protocol.URIFromPath(tmpFile) if err := c.Server.DidOpen(ctx, &protocol.DidOpenTextDocumentParams{ TextDocument: protocol.TextDocumentItem{ URI: uri, diff --git a/internal/lsp/cmd/check.go b/internal/lsp/cmd/check.go index 33310535f1..7d22db8d3b 100644 --- a/internal/lsp/cmd/check.go +++ b/internal/lsp/cmd/check.go @@ -48,7 +48,7 @@ func (c *check) Run(ctx context.Context, args ...string) error { } defer conn.terminate(ctx) for _, arg := range args { - uri := span.FileURI(arg) + uri := span.URIFromPath(arg) uris = append(uris, uri) file := conn.AddFile(ctx, uri) if file.err != nil { diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go index e442c8d66c..daf9091741 100644 --- a/internal/lsp/cmd/cmd.go +++ b/internal/lsp/cmd/cmd.go @@ -237,7 +237,7 @@ func (app *Application) connectRemote(ctx context.Context, remote string) (*conn func (c *connection) initialize(ctx context.Context, options func(*source.Options)) error { params := &protocol.ParamInitialize{} - params.RootURI = string(span.FileURI(c.Client.app.wd)) + params.RootURI = protocol.URIFromPath(c.Client.app.wd) params.Capabilities.Workspace.Configuration = true // Make sure to respect configured options when sending initialize request. @@ -373,8 +373,7 @@ func (c *cmdClient) PublishDiagnostics(ctx context.Context, p *protocol.PublishD c.filesMu.Lock() defer c.filesMu.Unlock() - uri := span.NewURI(p.URI) - file := c.getFile(ctx, uri) + file := c.getFile(ctx, p.URI.SpanURI()) file.diagnostics = p.Diagnostics return nil } @@ -424,7 +423,7 @@ func (c *connection) AddFile(ctx context.Context, uri span.URI) *cmdFile { file.added = true p := &protocol.DidOpenTextDocumentParams{ TextDocument: protocol.TextDocumentItem{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), LanguageID: source.DetectLanguage("", file.uri.Filename()).String(), Version: 1, Text: string(file.mapper.Content), diff --git a/internal/lsp/cmd/definition.go b/internal/lsp/cmd/definition.go index 1845605b41..6a9f2b5458 100644 --- a/internal/lsp/cmd/definition.go +++ b/internal/lsp/cmd/definition.go @@ -109,7 +109,7 @@ func (d *definition) Run(ctx context.Context, args ...string) error { if hover == nil { return errors.Errorf("%v: not an identifier", from) } - file = conn.AddFile(ctx, span.NewURI(locs[0].URI)) + file = conn.AddFile(ctx, locs[0].URI.SpanURI()) if file.err != nil { return errors.Errorf("%v: %v", from, file.err) } diff --git a/internal/lsp/cmd/folding_range.go b/internal/lsp/cmd/folding_range.go index d6e3b73277..f655f30ce0 100644 --- a/internal/lsp/cmd/folding_range.go +++ b/internal/lsp/cmd/folding_range.go @@ -50,7 +50,7 @@ func (r *foldingRanges) Run(ctx context.Context, args ...string) error { p := protocol.FoldingRangeParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(from.URI()), + URI: protocol.URIFromSpanURI(from.URI()), }, } diff --git a/internal/lsp/cmd/implementation.go b/internal/lsp/cmd/implementation.go index 98a6b8abbe..91c4d590f4 100644 --- a/internal/lsp/cmd/implementation.go +++ b/internal/lsp/cmd/implementation.go @@ -72,7 +72,7 @@ func (i *implementation) Run(ctx context.Context, args ...string) error { var spans []string for _, impl := range implementations { - f := conn.AddFile(ctx, span.NewURI(impl.URI)) + f := conn.AddFile(ctx, impl.URI.SpanURI()) span, err := f.mapper.Span(impl) if err != nil { return err diff --git a/internal/lsp/cmd/imports.go b/internal/lsp/cmd/imports.go index 2127e25ab8..407509b875 100644 --- a/internal/lsp/cmd/imports.go +++ b/internal/lsp/cmd/imports.go @@ -62,7 +62,7 @@ func (t *imports) Run(ctx context.Context, args ...string) error { } actions, err := conn.CodeAction(ctx, &protocol.CodeActionParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, }) if err != nil { @@ -74,7 +74,7 @@ func (t *imports) Run(ctx context.Context, args ...string) error { continue } for _, c := range a.Edit.DocumentChanges { - if c.TextDocument.URI == string(uri) { + if c.TextDocument.URI.SpanURI() == uri { edits = append(edits, c.Edits...) } } diff --git a/internal/lsp/cmd/links.go b/internal/lsp/cmd/links.go index a93ae8fdb9..1d5a669214 100644 --- a/internal/lsp/cmd/links.go +++ b/internal/lsp/cmd/links.go @@ -59,7 +59,7 @@ func (l *links) Run(ctx context.Context, args ...string) error { } results, err := conn.DocumentLink(ctx, &protocol.DocumentLinkParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, }) if err != nil { diff --git a/internal/lsp/cmd/references.go b/internal/lsp/cmd/references.go index cc85e799a5..573348d4bb 100644 --- a/internal/lsp/cmd/references.go +++ b/internal/lsp/cmd/references.go @@ -73,7 +73,7 @@ func (r *references) Run(ctx context.Context, args ...string) error { } var spans []string for _, l := range locations { - f := conn.AddFile(ctx, span.NewURI(l.URI)) + f := conn.AddFile(ctx, l.URI.SpanURI()) // convert location to span for user-friendly 1-indexed line // and column numbers span, err := f.mapper.Span(l) diff --git a/internal/lsp/cmd/rename.go b/internal/lsp/cmd/rename.go index e09cbced0a..33121aac57 100644 --- a/internal/lsp/cmd/rename.go +++ b/internal/lsp/cmd/rename.go @@ -81,15 +81,15 @@ func (r *rename) Run(ctx context.Context, args ...string) error { var orderedURIs []string edits := map[span.URI][]protocol.TextEdit{} for _, c := range edit.DocumentChanges { - uri := span.NewURI(c.TextDocument.URI) + uri := c.TextDocument.URI.SpanURI() edits[uri] = append(edits[uri], c.Edits...) - orderedURIs = append(orderedURIs, c.TextDocument.URI) + orderedURIs = append(orderedURIs, string(uri)) } sort.Strings(orderedURIs) changeCount := len(orderedURIs) for _, u := range orderedURIs { - uri := span.NewURI(u) + uri := span.URIFromURI(u) cmdFile := conn.AddFile(ctx, uri) filename := cmdFile.uri.Filename() diff --git a/internal/lsp/cmd/signature.go b/internal/lsp/cmd/signature.go index 7cc91cd5f7..2cec976efa 100644 --- a/internal/lsp/cmd/signature.go +++ b/internal/lsp/cmd/signature.go @@ -59,7 +59,7 @@ func (r *signature) Run(ctx context.Context, args ...string) error { tdpp := protocol.TextDocumentPositionParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(from.URI()), + URI: protocol.URIFromSpanURI(from.URI()), }, Position: loc.Range.Start, } diff --git a/internal/lsp/cmd/suggested_fix.go b/internal/lsp/cmd/suggested_fix.go index 19a53dc312..b92cb257a1 100644 --- a/internal/lsp/cmd/suggested_fix.go +++ b/internal/lsp/cmd/suggested_fix.go @@ -70,7 +70,7 @@ func (s *suggestedfix) Run(ctx context.Context, args ...string) error { p := protocol.CodeActionParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, Context: protocol.CodeActionContext{ Only: []protocol.CodeActionKind{protocol.QuickFix}, @@ -87,7 +87,7 @@ func (s *suggestedfix) Run(ctx context.Context, args ...string) error { continue } for _, c := range a.Edit.DocumentChanges { - if c.TextDocument.URI == string(uri) { + if c.TextDocument.URI.SpanURI() == uri { edits = append(edits, c.Edits...) } } diff --git a/internal/lsp/cmd/symbols.go b/internal/lsp/cmd/symbols.go index 41cc0f7513..eb3aa02b13 100644 --- a/internal/lsp/cmd/symbols.go +++ b/internal/lsp/cmd/symbols.go @@ -44,7 +44,7 @@ func (r *symbols) Run(ctx context.Context, args ...string) error { from := span.Parse(args[0]) p := protocol.DocumentSymbolParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: string(from.URI()), + URI: protocol.URIFromSpanURI(from.URI()), }, } diff --git a/internal/lsp/code_action.go b/internal/lsp/code_action.go index e7fe033ef0..ea2274a994 100644 --- a/internal/lsp/code_action.go +++ b/internal/lsp/code_action.go @@ -15,13 +15,12 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/lsp/telemetry" - "golang.org/x/tools/internal/span" "golang.org/x/tools/internal/telemetry/log" errors "golang.org/x/xerrors" ) func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionParams) ([]protocol.CodeAction, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -257,7 +256,7 @@ func documentChanges(fh source.FileHandle, edits []protocol.TextEdit) []protocol TextDocument: protocol.VersionedTextDocumentIdentifier{ Version: fh.Identity().Version, TextDocumentIdentifier: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(fh.Identity().URI), + URI: protocol.URIFromSpanURI(fh.Identity().URI), }, }, Edits: edits, diff --git a/internal/lsp/command.go b/internal/lsp/command.go index 204849b85b..a5bccfcb22 100644 --- a/internal/lsp/command.go +++ b/internal/lsp/command.go @@ -16,7 +16,7 @@ func (s *Server) executeCommand(ctx context.Context, params *protocol.ExecuteCom return nil, errors.Errorf("expected one file URI for call to `go mod tidy`, got %v", params.Arguments) } // Confirm that this action is being taken on a go.mod file. - uri := span.NewURI(params.Arguments[0].(string)) + uri := span.URIFromURI(params.Arguments[0].(string)) view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -37,7 +37,7 @@ func (s *Server) executeCommand(ctx context.Context, params *protocol.ExecuteCom if len(params.Arguments) < 2 { return nil, errors.Errorf("expected one file URI and one dependency for call to `go get`, got %v", params.Arguments) } - uri := span.NewURI(params.Arguments[0].(string)) + uri := span.URIFromURI(params.Arguments[0].(string)) view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index 4ea01b6b86..a4306831d1 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -11,13 +11,12 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" "golang.org/x/tools/internal/telemetry/log" "golang.org/x/tools/internal/telemetry/tag" ) func (s *Server) completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/completion_test.go b/internal/lsp/completion_test.go index 949ad2f0b2..93ecb27b07 100644 --- a/internal/lsp/completion_test.go +++ b/internal/lsp/completion_test.go @@ -137,7 +137,7 @@ func (r *runner) callCompletion(t *testing.T, src span.Span, options func(*sourc list, err := r.server.Completion(r.ctx, &protocol.CompletionParams{ TextDocumentPositionParams: protocol.TextDocumentPositionParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(src.URI()), + URI: protocol.URIFromSpanURI(src.URI()), }, Position: protocol.Position{ Line: float64(src.Start().Line() - 1), diff --git a/internal/lsp/definition.go b/internal/lsp/definition.go index bb8fb9005a..60087280a3 100644 --- a/internal/lsp/definition.go +++ b/internal/lsp/definition.go @@ -9,11 +9,10 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" ) func (s *Server) definition(ctx context.Context, params *protocol.DefinitionParams) ([]protocol.Location, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -36,14 +35,14 @@ func (s *Server) definition(ctx context.Context, params *protocol.DefinitionPara } return []protocol.Location{ { - URI: protocol.NewURI(ident.Declaration.URI()), + URI: protocol.URIFromSpanURI(ident.Declaration.URI()), Range: decRange, }, }, nil } func (s *Server) typeDefinition(ctx context.Context, params *protocol.TypeDefinitionParams) ([]protocol.Location, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -66,7 +65,7 @@ func (s *Server) typeDefinition(ctx context.Context, params *protocol.TypeDefini } return []protocol.Location{ { - URI: protocol.NewURI(ident.Type.URI()), + URI: protocol.URIFromSpanURI(ident.Type.URI()), Range: identRange, }, }, nil diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go index 411344f3da..db8eeb59cd 100644 --- a/internal/lsp/diagnostics.go +++ b/internal/lsp/diagnostics.go @@ -178,7 +178,7 @@ func (s *Server) publishReports(ctx context.Context, snapshot source.Snapshot, r if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{ Diagnostics: toProtocolDiagnostics(diagnostics), - URI: protocol.NewURI(key.id.URI), + URI: protocol.URIFromSpanURI(key.id.URI), Version: key.id.Version, }); err != nil { if ctx.Err() == nil { @@ -212,7 +212,7 @@ func toProtocolDiagnostics(diagnostics []source.Diagnostic) []protocol.Diagnosti for _, rel := range diag.Related { related = append(related, protocol.DiagnosticRelatedInformation{ Location: protocol.Location{ - URI: protocol.NewURI(rel.URI), + URI: protocol.URIFromSpanURI(rel.URI), Range: rel.Range, }, Message: rel.Message, diff --git a/internal/lsp/diff/difftest/difftest.go b/internal/lsp/diff/difftest/difftest.go index 297515f9ec..513a925ebd 100644 --- a/internal/lsp/diff/difftest/difftest.go +++ b/internal/lsp/diff/difftest/difftest.go @@ -222,7 +222,7 @@ func DiffTest(t *testing.T, compute diff.ComputeEdits) { for _, test := range TestCases { t.Run(test.Name, func(t *testing.T) { t.Helper() - edits := compute(span.FileURI("/"+test.Name), test.In, test.Out) + edits := compute(span.URIFromPath("/"+test.Name), test.In, test.Out) got := diff.ApplyEdits(test.In, edits) unified := fmt.Sprint(diff.ToUnified(FileA, FileB, test.In, edits)) if got != test.Out { diff --git a/internal/lsp/fake/workspace.go b/internal/lsp/fake/workspace.go index fa8a4749fb..b5401630e5 100644 --- a/internal/lsp/fake/workspace.go +++ b/internal/lsp/fake/workspace.go @@ -101,16 +101,16 @@ func (w *Workspace) URI(path string) protocol.DocumentURI { // URIToPath converts a uri to a workspace-relative path (or an absolute path, // if the uri is outside of the workspace). func (w *Workspace) URIToPath(uri protocol.DocumentURI) string { - root := w.RootURI() + "/" - if strings.HasPrefix(uri, root) { - return strings.TrimPrefix(uri, root) + root := w.RootURI().SpanURI().Filename() + path := uri.SpanURI().Filename() + if rel, err := filepath.Rel(root, path); err == nil && !strings.HasPrefix(rel, "..") { + return filepath.ToSlash(rel) } - filename := span.NewURI(string(uri)).Filename() - return filepath.ToSlash(filename) + return filepath.ToSlash(path) } func toURI(fp string) protocol.DocumentURI { - return protocol.DocumentURI(span.FileURI(fp)) + return protocol.DocumentURI(span.URIFromPath(fp)) } // ReadFile reads a text file specified by a workspace-relative path. diff --git a/internal/lsp/folding_range.go b/internal/lsp/folding_range.go index 19b28ebfaa..69c9f68948 100644 --- a/internal/lsp/folding_range.go +++ b/internal/lsp/folding_range.go @@ -5,11 +5,10 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" ) func (s *Server) foldingRange(ctx context.Context, params *protocol.FoldingRangeParams) ([]protocol.FoldingRange, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/format.go b/internal/lsp/format.go index f3abeb1a6c..1f70ba7219 100644 --- a/internal/lsp/format.go +++ b/internal/lsp/format.go @@ -9,11 +9,10 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" ) func (s *Server) formatting(ctx context.Context, params *protocol.DocumentFormattingParams) ([]protocol.TextEdit, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/general.go b/internal/lsp/general.go index 0136392f0d..c476d56c00 100644 --- a/internal/lsp/general.go +++ b/internal/lsp/general.go @@ -42,8 +42,8 @@ func (s *Server) initialize(ctx context.Context, params *protocol.ParamInitializ if len(s.pendingFolders) == 0 { if params.RootURI != "" { s.pendingFolders = []protocol.WorkspaceFolder{{ - URI: params.RootURI, - Name: path.Base(params.RootURI), + URI: string(params.RootURI), + Name: path.Base(params.RootURI.SpanURI().Filename()), }} } else { // No folders and no root--we are in single file mode. @@ -165,8 +165,8 @@ func (s *Server) addFolders(ctx context.Context, folders []protocol.WorkspaceFol viewErrors := make(map[span.URI]error) for _, folder := range folders { - uri := span.NewURI(folder.URI) - _, snapshot, err := s.addView(ctx, folder.Name, span.NewURI(folder.URI)) + uri := span.URIFromURI(folder.URI) + _, snapshot, err := s.addView(ctx, folder.Name, uri) if err != nil { viewErrors[uri] = err continue @@ -192,10 +192,10 @@ func (s *Server) fetchConfig(ctx context.Context, name string, folder span.URI, v := protocol.ParamConfiguration{ ConfigurationParams: protocol.ConfigurationParams{ Items: []protocol.ConfigurationItem{{ - ScopeURI: protocol.NewURI(folder), + ScopeURI: string(folder), Section: "gopls", }, { - ScopeURI: protocol.NewURI(folder), + ScopeURI: string(folder), Section: fmt.Sprintf("gopls-%s", name), }}, }, diff --git a/internal/lsp/highlight.go b/internal/lsp/highlight.go index 45e374bd43..c2f50712a9 100644 --- a/internal/lsp/highlight.go +++ b/internal/lsp/highlight.go @@ -10,12 +10,11 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/lsp/telemetry" - "golang.org/x/tools/internal/span" "golang.org/x/tools/internal/telemetry/log" ) func (s *Server) documentHighlight(ctx context.Context, params *protocol.DocumentHighlightParams) ([]protocol.DocumentHighlight, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/hover.go b/internal/lsp/hover.go index 3305189887..4ec04a5ddf 100644 --- a/internal/lsp/hover.go +++ b/internal/lsp/hover.go @@ -9,11 +9,10 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" ) func (s *Server) hover(ctx context.Context, params *protocol.HoverParams) (*protocol.Hover, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/implementation.go b/internal/lsp/implementation.go index bae2832d84..4fb0219952 100644 --- a/internal/lsp/implementation.go +++ b/internal/lsp/implementation.go @@ -9,11 +9,10 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" ) func (s *Server) implementation(ctx context.Context, params *protocol.ImplementationParams) ([]protocol.Location, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/link.go b/internal/lsp/link.go index 30e5a9ca5f..c457d7eb05 100644 --- a/internal/lsp/link.go +++ b/internal/lsp/link.go @@ -21,7 +21,7 @@ import ( ) func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLinkParams) ([]protocol.DocumentLink, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index 651592b26f..a893834575 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -54,7 +54,7 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) { options := tests.DefaultOptions() session.SetOptions(options) options.Env = datum.Config.Env - v, _, err := session.NewView(ctx, datum.Config.Dir, span.FileURI(datum.Config.Dir), options) + v, _, err := session.NewView(ctx, datum.Config.Dir, span.URIFromPath(datum.Config.Dir), options) if err != nil { t.Fatal(err) } @@ -74,7 +74,7 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) { continue } modifications = append(modifications, source.FileModification{ - URI: span.FileURI(filename), + URI: span.URIFromPath(filename), Action: source.Open, Version: -1, Text: content, @@ -158,7 +158,7 @@ func (r *runner) FoldingRanges(t *testing.T, spn span.Span) { } ranges, err := r.server.FoldingRange(r.ctx, &protocol.FoldingRangeParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, }) if err != nil { @@ -176,7 +176,7 @@ func (r *runner) FoldingRanges(t *testing.T, spn span.Span) { } ranges, err = r.server.FoldingRange(r.ctx, &protocol.FoldingRangeParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, }) if err != nil { @@ -310,7 +310,7 @@ func (r *runner) Format(t *testing.T, spn span.Span) { edits, err := r.server.Formatting(r.ctx, &protocol.DocumentFormattingParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, }) if err != nil { @@ -338,7 +338,7 @@ func (r *runner) Import(t *testing.T, spn span.Span) { filename := uri.Filename() actions, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, }) if err != nil { @@ -402,7 +402,7 @@ func (r *runner) SuggestedFix(t *testing.T, spn span.Span) { } actions, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, Context: protocol.CodeActionContext{ Only: []protocol.CodeActionKind{protocol.QuickFix}, @@ -482,7 +482,7 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) { } if !d.OnlyHover { didSomething = true - locURI := span.NewURI(locs[0].URI) + locURI := locs[0].URI.SpanURI() lm, err := r.data.Mapper(locURI) if err != nil { t.Fatal(err) @@ -525,7 +525,7 @@ func (r *runner) Implementation(t *testing.T, spn span.Span, impls []span.Span) var results []span.Span for i := range locs { - locURI := span.NewURI(locs[i].URI) + locURI := locs[i].URI.SpanURI() lm, err := r.data.Mapper(locURI) if err != nil { t.Fatal(err) @@ -663,7 +663,7 @@ func (r *runner) Rename(t *testing.T, spn span.Span, newText string) { wedit, err := r.server.Rename(r.ctx, &protocol.RenameParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, Position: loc.Range.Start, NewName: newText, @@ -692,7 +692,7 @@ func (r *runner) Rename(t *testing.T, spn span.Span, newText string) { if i != 0 { got += "\n" } - uri := span.NewURI(orderedURIs[i]) + uri := span.URIFromURI(orderedURIs[i]) if len(res) > 1 { got += filepath.Base(uri.Filename()) + ":\n" } @@ -753,7 +753,7 @@ func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.Prepare func applyWorkspaceEdits(r *runner, wedit protocol.WorkspaceEdit) (map[span.URI]string, error) { res := map[span.URI]string{} for _, docEdits := range wedit.DocumentChanges { - uri := span.NewURI(docEdits.TextDocument.URI) + uri := docEdits.TextDocument.URI.SpanURI() m, err := r.data.Mapper(uri) if err != nil { return nil, err @@ -786,7 +786,7 @@ func applyEdits(contents string, edits []diff.TextEdit) string { func (r *runner) Symbols(t *testing.T, uri span.URI, expectedSymbols []protocol.DocumentSymbol) { params := &protocol.DocumentSymbolParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: string(uri), + URI: protocol.URIFromSpanURI(uri), }, } symbols, err := r.server.DocumentSymbol(r.ctx, params) @@ -881,7 +881,7 @@ func (r *runner) SignatureHelp(t *testing.T, spn span.Span, want *protocol.Signa } tdpp := protocol.TextDocumentPositionParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(spn.URI()), + URI: protocol.URIFromSpanURI(spn.URI()), }, Position: loc.Range.Start, } @@ -917,7 +917,7 @@ func (r *runner) Link(t *testing.T, uri span.URI, wantLinks []tests.Link) { } got, err := r.server.DocumentLink(r.ctx, &protocol.DocumentLinkParams{ TextDocument: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), }, }) if err != nil { @@ -955,7 +955,7 @@ func TestBytesOffset(t *testing.T) { fset := token.NewFileSet() f := fset.AddFile(fname, -1, len(test.text)) f.SetLinesForContent([]byte(test.text)) - uri := span.FileURI(fname) + uri := span.URIFromPath(fname) converter := span.NewContentConverter(fname, []byte(test.text)) mapper := &protocol.ColumnMapper{ URI: uri, diff --git a/internal/lsp/mod/diagnostics.go b/internal/lsp/mod/diagnostics.go index 647bab3b0c..401f9ef1f4 100644 --- a/internal/lsp/mod/diagnostics.go +++ b/internal/lsp/mod/diagnostics.go @@ -105,7 +105,7 @@ func SuggestedFixes(ctx context.Context, snapshot source.Snapshot, realfh source TextDocument: protocol.VersionedTextDocumentIdentifier{ Version: fh.Identity().Version, TextDocumentIdentifier: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(fh.Identity().URI), + URI: protocol.URIFromSpanURI(fh.Identity().URI), }, }, Edits: edits, @@ -188,7 +188,7 @@ func SuggestedGoFixes(ctx context.Context, snapshot source.Snapshot, gofh source TextDocument: protocol.VersionedTextDocumentIdentifier{ Version: realfh.Identity().Version, TextDocumentIdentifier: protocol.TextDocumentIdentifier{ - URI: protocol.NewURI(realfh.Identity().URI), + URI: protocol.URIFromSpanURI(realfh.Identity().URI), }, }, Edits: edits, diff --git a/internal/lsp/mod/mod_test.go b/internal/lsp/mod/mod_test.go index 8f78207145..491cb68e12 100644 --- a/internal/lsp/mod/mod_test.go +++ b/internal/lsp/mod/mod_test.go @@ -41,7 +41,7 @@ func TestModfileRemainsUnchanged(t *testing.T) { if err != nil { t.Fatal(err) } - _, snapshot, err := session.NewView(ctx, "diagnostics_test", span.FileURI(folder), options) + _, snapshot, err := session.NewView(ctx, "diagnostics_test", span.URIFromPath(folder), options) if err != nil { t.Fatal(err) } diff --git a/internal/lsp/protocol/span.go b/internal/lsp/protocol/span.go index 5c9c4d107d..8363d5cbe9 100644 --- a/internal/lsp/protocol/span.go +++ b/internal/lsp/protocol/span.go @@ -19,8 +19,16 @@ type ColumnMapper struct { Content []byte } -func NewURI(uri span.URI) string { - return string(uri) +func URIFromSpanURI(uri span.URI) DocumentURI { + return DocumentURI(uri) +} + +func URIFromPath(path string) DocumentURI { + return URIFromSpanURI(span.URIFromPath(path)) +} + +func (u DocumentURI) SpanURI() span.URI { + return span.URIFromURI(string(u)) } func (m *ColumnMapper) Location(s span.Span) (Location, error) { @@ -28,7 +36,7 @@ func (m *ColumnMapper) Location(s span.Span) (Location, error) { if err != nil { return Location{}, err } - return Location{URI: NewURI(s.URI()), Range: rng}, nil + return Location{URI: URIFromSpanURI(s.URI()), Range: rng}, nil } func (m *ColumnMapper) Range(s span.Span) (Range, error) { diff --git a/internal/lsp/protocol/tsclient.go b/internal/lsp/protocol/tsclient.go index ab2abc9bb7..53327edd85 100644 --- a/internal/lsp/protocol/tsclient.go +++ b/internal/lsp/protocol/tsclient.go @@ -3,7 +3,7 @@ package protocol // Package protocol contains data types and code for LSP jsonrpcs // generated automatically from vscode-languageserver-node // commit: 7b90c29d0cb5cd7b9c41084f6cb3781a955adeba -// last fetched Thu Jan 23 2020 11:10:31 GMT-0500 (Eastern Standard Time) +// last fetched Wed Feb 12 2020 17:16:47 GMT-0500 (Eastern Standard Time) // Code generated (see typescript/README.md) DO NOT EDIT. diff --git a/internal/lsp/protocol/tsprotocol.go b/internal/lsp/protocol/tsprotocol.go index e8be3648e7..f5b66fedf9 100644 --- a/internal/lsp/protocol/tsprotocol.go +++ b/internal/lsp/protocol/tsprotocol.go @@ -1,7 +1,7 @@ // Package protocol contains data types and code for LSP jsonrpcs // generated automatically from vscode-languageserver-node // commit: 7b90c29d0cb5cd7b9c41084f6cb3781a955adeba -// last fetched Thu Jan 23 2020 11:10:31 GMT-0500 (Eastern Standard Time) +// last fetched Wed Feb 12 2020 17:16:47 GMT-0500 (Eastern Standard Time) package protocol // Code generated (see typescript/README.md) DO NOT EDIT. @@ -1532,7 +1532,7 @@ type DocumentSymbolParams struct { /** * A tagging type for string properties that are actually URIs. */ -type DocumentURI = string +type DocumentURI string /** * The client capabilities of a [ExecuteCommandRequest](#ExecuteCommandRequest). diff --git a/internal/lsp/protocol/tsserver.go b/internal/lsp/protocol/tsserver.go index 64b211463a..785344927d 100644 --- a/internal/lsp/protocol/tsserver.go +++ b/internal/lsp/protocol/tsserver.go @@ -3,7 +3,7 @@ package protocol // Package protocol contains data types and code for LSP jsonrpcs // generated automatically from vscode-languageserver-node // commit: 7b90c29d0cb5cd7b9c41084f6cb3781a955adeba -// last fetched Thu Jan 23 2020 11:10:31 GMT-0500 (Eastern Standard Time) +// last fetched Wed Feb 12 2020 17:16:47 GMT-0500 (Eastern Standard Time) // Code generated (see typescript/README.md) DO NOT EDIT. diff --git a/internal/lsp/protocol/typescript/code.ts b/internal/lsp/protocol/typescript/code.ts index 38d52d4e82..fe35d80a77 100644 --- a/internal/lsp/protocol/typescript/code.ts +++ b/internal/lsp/protocol/typescript/code.ts @@ -601,7 +601,8 @@ function goTypeAlias(d: Data, nm: string) { } typesOut.push(getComments(d.me)) // d.alias doesn't seem to have comments - typesOut.push(`type ${goName(nm)} = ${goType(d.alias, nm)}\n`) + let aliasStr = goName(nm) == "DocumentURI" ? " " : " = " + typesOut.push(`type ${goName(nm)}${aliasStr}${goType(d.alias, nm)}\n`) } // return a go type and maybe an assocated javascript tag diff --git a/internal/lsp/references.go b/internal/lsp/references.go index d91fc16b7f..068cfa628e 100644 --- a/internal/lsp/references.go +++ b/internal/lsp/references.go @@ -9,11 +9,10 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" ) func (s *Server) references(ctx context.Context, params *protocol.ReferenceParams) ([]protocol.Location, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -41,7 +40,7 @@ func (s *Server) references(ctx context.Context, params *protocol.ReferenceParam } locations = append(locations, protocol.Location{ - URI: protocol.NewURI(ref.URI()), + URI: protocol.URIFromSpanURI(ref.URI()), Range: refRange, }) } diff --git a/internal/lsp/rename.go b/internal/lsp/rename.go index 04f00546f5..4043b14174 100644 --- a/internal/lsp/rename.go +++ b/internal/lsp/rename.go @@ -9,11 +9,10 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" ) func (s *Server) rename(ctx context.Context, params *protocol.RenameParams) (*protocol.WorkspaceEdit, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -46,7 +45,7 @@ func (s *Server) rename(ctx context.Context, params *protocol.RenameParams) (*pr } func (s *Server) prepareRename(ctx context.Context, params *protocol.PrepareRenameParams) (*protocol.Range, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/server.go b/internal/lsp/server.go index ab1c26351a..f4ba6b6533 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -70,7 +70,7 @@ func (s *Server) cancelRequest(ctx context.Context, params *protocol.CancelParam } func (s *Server) codeLens(ctx context.Context, params *protocol.CodeLensParams) ([]protocol.CodeLens, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -95,7 +95,7 @@ func (s *Server) nonstandardRequest(ctx context.Context, method string, params i paramMap := params.(map[string]interface{}) if method == "gopls/diagnoseFiles" { for _, file := range paramMap["files"].([]interface{}) { - uri := span.NewURI(file.(string)) + uri := span.URIFromURI(file.(string)) view, err := s.session.ViewOf(uri) if err != nil { return nil, err @@ -105,7 +105,7 @@ func (s *Server) nonstandardRequest(ctx context.Context, method string, params i return nil, err } if err := s.client.PublishDiagnostics(ctx, &protocol.PublishDiagnosticsParams{ - URI: protocol.NewURI(uri), + URI: protocol.URIFromSpanURI(uri), Diagnostics: toProtocolDiagnostics(diagnostics), Version: fileID.Version, }); err != nil { diff --git a/internal/lsp/signature_help.go b/internal/lsp/signature_help.go index 1cbe5177da..c514d58075 100644 --- a/internal/lsp/signature_help.go +++ b/internal/lsp/signature_help.go @@ -9,13 +9,12 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" - "golang.org/x/tools/internal/span" "golang.org/x/tools/internal/telemetry/log" "golang.org/x/tools/internal/telemetry/tag" ) func (s *Server) signatureHelp(ctx context.Context, params *protocol.SignatureHelpParams) (*protocol.SignatureHelp, error) { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/source/completion_format.go b/internal/lsp/source/completion_format.go index f44b553eba..600ad5c455 100644 --- a/internal/lsp/source/completion_format.go +++ b/internal/lsp/source/completion_format.go @@ -179,7 +179,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) { if !pos.IsValid() { return item, nil } - uri := span.FileURI(pos.Filename) + uri := span.URIFromPath(pos.Filename) // Find the source file of the candidate, starting from a package // that should have it in its dependencies. @@ -213,7 +213,7 @@ func (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) { return nil, nil } - uri := span.FileURI(c.filename) + uri := span.URIFromPath(c.filename) var ph ParseGoHandle for _, h := range c.pkg.CompiledGoFiles() { if h.File().Identity().URI == uri { diff --git a/internal/lsp/source/implementation.go b/internal/lsp/source/implementation.go index 9cd10ca376..547e2c582c 100644 --- a/internal/lsp/source/implementation.go +++ b/internal/lsp/source/implementation.go @@ -39,7 +39,7 @@ func Implementation(ctx context.Context, s Snapshot, f FileHandle, pp protocol.P return nil, err } locations = append(locations, protocol.Location{ - URI: protocol.NewURI(rng.URI()), + URI: protocol.URIFromSpanURI(rng.URI()), Range: pr, }) } diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index 6e52d6ce63..dd660acc0e 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -51,7 +51,7 @@ func testSource(t *testing.T, exporter packagestest.Exporter) { session := cache.NewSession() options := tests.DefaultOptions() options.Env = datum.Config.Env - view, _, err := session.NewView(ctx, "source_test", span.FileURI(datum.Config.Dir), options) + view, _, err := session.NewView(ctx, "source_test", span.URIFromPath(datum.Config.Dir), options) if err != nil { t.Fatal(err) } @@ -67,7 +67,7 @@ func testSource(t *testing.T, exporter packagestest.Exporter) { continue } modifications = append(modifications, source.FileModification{ - URI: span.FileURI(filename), + URI: span.URIFromPath(filename), Action: source.Open, Version: -1, Text: content, @@ -547,7 +547,7 @@ func (r *runner) Implementation(t *testing.T, spn span.Span, impls []span.Span) } var results []span.Span for i := range locs { - locURI := span.NewURI(locs[i].URI) + locURI := locs[i].URI.SpanURI() lm, err := r.data.Mapper(locURI) if err != nil { t.Fatal(err) diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go index 1a66ad71b8..ffb166f08b 100644 --- a/internal/lsp/source/util.go +++ b/internal/lsp/source/util.go @@ -201,7 +201,7 @@ func nameToMappedRange(v View, pkg Package, pos token.Pos, name string) (mappedR func posToMappedRange(v View, pkg Package, pos, end token.Pos) (mappedRange, error) { logicalFilename := v.Session().Cache().FileSet().File(pos).Position(pos).Filename - m, err := findMapperInPackage(v, pkg, span.FileURI(logicalFilename)) + m, err := findMapperInPackage(v, pkg, span.URIFromPath(logicalFilename)) if err != nil { return mappedRange{}, err } @@ -631,7 +631,7 @@ func findPosInPackage(v View, searchpkg Package, pos token.Pos) (*ast.File, Pack if tok == nil { return nil, nil, errors.Errorf("no file for pos in package %s", searchpkg.ID()) } - uri := span.FileURI(tok.Name()) + uri := span.URIFromPath(tok.Name()) var ( ph ParseGoHandle diff --git a/internal/lsp/source/workspace_symbol.go b/internal/lsp/source/workspace_symbol.go index 009b9f4288..f1033c5023 100644 --- a/internal/lsp/source/workspace_symbol.go +++ b/internal/lsp/source/workspace_symbol.go @@ -53,7 +53,7 @@ func WorkspaceSymbols(ctx context.Context, views []View, query string) ([]protoc Name: si.name, Kind: si.kind, Location: protocol.Location{ - URI: protocol.NewURI(fh.File().Identity().URI), + URI: protocol.URIFromSpanURI(fh.File().Identity().URI), Range: rng, }, }) diff --git a/internal/lsp/symbols.go b/internal/lsp/symbols.go index 0e167d3e68..b0d93718eb 100644 --- a/internal/lsp/symbols.go +++ b/internal/lsp/symbols.go @@ -10,7 +10,6 @@ import ( "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/source" "golang.org/x/tools/internal/lsp/telemetry" - "golang.org/x/tools/internal/span" "golang.org/x/tools/internal/telemetry/log" "golang.org/x/tools/internal/telemetry/trace" ) @@ -19,7 +18,7 @@ func (s *Server) documentSymbol(ctx context.Context, params *protocol.DocumentSy ctx, done := trace.StartSpan(ctx, "lsp.Server.documentSymbol") defer done() - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() view, err := s.session.ViewOf(uri) if err != nil { return nil, err diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index 16dbec9d7a..4b8c8559d3 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -466,7 +466,7 @@ func Run(t *testing.T, tests Tests, data *Data) { t.Helper() dirs := make(map[string]struct{}) for _, si := range expectedSymbols { - d := filepath.Dir(si.Location.URI) + d := filepath.Dir(si.Location.URI.SpanURI().Filename()) if _, ok := dirs[d]; !ok { dirs[d] = struct{}{} } @@ -1077,7 +1077,7 @@ func (data *Data) collectSymbols(name string, spn span.Span, kind string, parent Name: sym.Name, Kind: sym.Kind, Location: protocol.Location{ - URI: protocol.NewURI(spn.URI()), + URI: protocol.URIFromSpanURI(spn.URI()), Range: sym.SelectionRange, }, } diff --git a/internal/lsp/tests/util.go b/internal/lsp/tests/util.go index f7787571c4..dcea4662b9 100644 --- a/internal/lsp/tests/util.go +++ b/internal/lsp/tests/util.go @@ -109,7 +109,7 @@ func summarizeSymbols(t *testing.T, i int, want, got []protocol.DocumentSymbol, func FilterWorkspaceSymbols(got []protocol.SymbolInformation, dirs map[string]struct{}) []protocol.SymbolInformation { var result []protocol.SymbolInformation for _, si := range got { - if _, ok := dirs[filepath.Dir(si.Location.URI)]; ok { + if _, ok := dirs[filepath.Dir(si.Location.URI.SpanURI().Filename())]; ok { result = append(result, si) } } diff --git a/internal/lsp/text_synchronization.go b/internal/lsp/text_synchronization.go index 652132d2c1..e4db204ddc 100644 --- a/internal/lsp/text_synchronization.go +++ b/internal/lsp/text_synchronization.go @@ -19,7 +19,7 @@ import ( func (s *Server) didOpen(ctx context.Context, params *protocol.DidOpenTextDocumentParams) error { _, err := s.didModifyFiles(ctx, []source.FileModification{ { - URI: span.NewURI(params.TextDocument.URI), + URI: params.TextDocument.URI.SpanURI(), Action: source.Open, Version: params.TextDocument.Version, Text: []byte(params.TextDocument.Text), @@ -30,7 +30,7 @@ func (s *Server) didOpen(ctx context.Context, params *protocol.DidOpenTextDocume } func (s *Server) didChange(ctx context.Context, params *protocol.DidChangeTextDocumentParams) error { - uri := span.NewURI(params.TextDocument.URI) + uri := params.TextDocument.URI.SpanURI() text, err := s.changedText(ctx, uri, params.ContentChanges) if err != nil { return err @@ -66,7 +66,7 @@ func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.Did var modifications []source.FileModification for _, change := range params.Changes { modifications = append(modifications, source.FileModification{ - URI: span.NewURI(change.URI), + URI: change.URI.SpanURI(), Action: changeTypeToFileAction(change.Type), OnDisk: true, }) @@ -77,7 +77,7 @@ func (s *Server) didChangeWatchedFiles(ctx context.Context, params *protocol.Did func (s *Server) didSave(ctx context.Context, params *protocol.DidSaveTextDocumentParams) error { c := source.FileModification{ - URI: span.NewURI(params.TextDocument.URI), + URI: params.TextDocument.URI.SpanURI(), Action: source.Save, Version: params.TextDocument.Version, } @@ -91,7 +91,7 @@ func (s *Server) didSave(ctx context.Context, params *protocol.DidSaveTextDocume func (s *Server) didClose(ctx context.Context, params *protocol.DidCloseTextDocumentParams) error { _, err := s.didModifyFiles(ctx, []source.FileModification{ { - URI: span.NewURI(params.TextDocument.URI), + URI: params.TextDocument.URI.SpanURI(), Action: source.Close, Version: -1, Text: nil, diff --git a/internal/span/parse.go b/internal/span/parse.go index b3f268a38a..aa17c84ec1 100644 --- a/internal/span/parse.go +++ b/internal/span/parse.go @@ -11,7 +11,7 @@ import ( ) // Parse returns the location represented by the input. -// All inputs are valid locations, as they can always be a pure filename. +// Only file paths are accepted, not URIs. // The returned span will be normalized, and thus if printed may produce a // different string. func Parse(input string) Span { @@ -32,12 +32,12 @@ func Parse(input string) Span { } switch { case suf.sep == ":": - return New(NewURI(suf.remains), NewPoint(suf.num, hold, offset), Point{}) + return New(URIFromPath(suf.remains), NewPoint(suf.num, hold, offset), Point{}) case suf.sep == "-": // we have a span, fall out of the case to continue default: // separator not valid, rewind to either the : or the start - return New(NewURI(valid), NewPoint(hold, 0, offset), Point{}) + return New(URIFromPath(valid), NewPoint(hold, 0, offset), Point{}) } // only the span form can get here // at this point we still don't know what the numbers we have mean @@ -53,20 +53,20 @@ func Parse(input string) Span { } if suf.sep != ":" { // turns out we don't have a span after all, rewind - return New(NewURI(valid), end, Point{}) + return New(URIFromPath(valid), end, Point{}) } valid = suf.remains hold = suf.num suf = rstripSuffix(suf.remains) if suf.sep != ":" { // line#offset only - return New(NewURI(valid), NewPoint(hold, 0, offset), end) + return New(URIFromPath(valid), NewPoint(hold, 0, offset), end) } // we have a column, so if end only had one number, it is also the column if !hadCol { end = NewPoint(suf.num, end.v.Line, end.v.Offset) } - return New(NewURI(suf.remains), NewPoint(suf.num, hold, offset), end) + return New(URIFromPath(suf.remains), NewPoint(suf.num, hold, offset), end) } type suffix struct { diff --git a/internal/span/span_test.go b/internal/span/span_test.go index 8212d0cb12..150ea3fbac 100644 --- a/internal/span/span_test.go +++ b/internal/span/span_test.go @@ -14,8 +14,7 @@ import ( ) var ( - formats = []string{"%v", "%#v", "%+v"} - tests = [][]string{ + tests = [][]string{ {"C:/file_a", "C:/file_a", "file:///C:/file_a:1:1#0"}, {"C:/file_b:1:2", "C:/file_b:#1", "file:///C:/file_b:1:2#1"}, {"C:/file_c:1000", "C:/file_c:#9990", "file:///C:/file_c:1000:1#9990"}, @@ -30,7 +29,7 @@ var ( func TestFormat(t *testing.T) { converter := lines(10) for _, test := range tests { - for ti, text := range test { + for ti, text := range test[:2] { spn := span.Parse(text) if ti <= 1 { // we can check %v produces the same as the input diff --git a/internal/span/token.go b/internal/span/token.go index d0ec03ac71..1710b7779d 100644 --- a/internal/span/token.go +++ b/internal/span/token.go @@ -75,7 +75,7 @@ func (r Range) Span() (Span, error) { if err != nil { return Span{}, err } - s.v.URI = FileURI(startFilename) + s.v.URI = URIFromPath(startFilename) if r.End.IsValid() { var endFilename string endFilename, s.v.End.Line, s.v.End.Column, err = position(f, r.End) diff --git a/internal/span/token_test.go b/internal/span/token_test.go index db11df11f0..81b263180e 100644 --- a/internal/span/token_test.go +++ b/internal/span/token_test.go @@ -32,10 +32,10 @@ package test`)}, } var tokenTests = []span.Span{ - span.New(span.FileURI("/a.go"), span.NewPoint(1, 1, 0), span.Point{}), - span.New(span.FileURI("/a.go"), span.NewPoint(3, 7, 20), span.NewPoint(3, 7, 20)), - span.New(span.FileURI("/b.go"), span.NewPoint(4, 9, 15), span.NewPoint(4, 13, 19)), - span.New(span.FileURI("/c.go"), span.NewPoint(4, 1, 26), span.Point{}), + span.New(span.URIFromPath("/a.go"), span.NewPoint(1, 1, 0), span.Point{}), + span.New(span.URIFromPath("/a.go"), span.NewPoint(3, 7, 20), span.NewPoint(3, 7, 20)), + span.New(span.URIFromPath("/b.go"), span.NewPoint(4, 9, 15), span.NewPoint(4, 13, 19)), + span.New(span.URIFromPath("/c.go"), span.NewPoint(4, 1, 26), span.Point{}), } func TestToken(t *testing.T) { @@ -44,7 +44,7 @@ func TestToken(t *testing.T) { for _, f := range testdata { file := fset.AddFile(f.uri, -1, len(f.content)) file.SetLinesForContent(f.content) - files[span.FileURI(f.uri)] = file + files[span.URIFromPath(f.uri)] = file } for _, test := range tokenTests { f := files[test.URI()] diff --git a/internal/span/uri.go b/internal/span/uri.go index 26dc90c94e..a794a2d06b 100644 --- a/internal/span/uri.go +++ b/internal/span/uri.go @@ -49,28 +49,26 @@ func filename(uri URI) (string, error) { return u.Path, nil } -// NewURI returns a span URI for the string. -// It will attempt to detect if the string is a file path or uri. -func NewURI(s string) URI { - // If a path has a scheme, it is already a URI. - // We only handle the file:// scheme. - if i := len(fileScheme + "://"); strings.HasPrefix(s, "file:///") { - // Handle microsoft/vscode#75027 by making it a special case. - // On Windows, VS Code sends file URIs that look like file:///C%3A/x/y/z. - // Replace the %3A so that the URI looks like: file:///C:/x/y/z. - if strings.ToLower(s[i+2:i+5]) == "%3a" { - s = s[:i+2] + ":" + s[i+5:] - } - // File URIs from Windows may have lowercase drive letters. - // Since drive letters are guaranteed to be case insensitive, - // we change them to uppercase to remain consistent. - // For example, file:///c:/x/y/z becomes file:///C:/x/y/z. - if isWindowsDriveURIPath(s[i:]) { - s = s[:i+1] + strings.ToUpper(string(s[i+1])) + s[i+2:] - } +func URIFromURI(s string) URI { + if !strings.HasPrefix(s, "file:///") { return URI(s) } - return FileURI(s) + // Handle Windows-specific glitches. We can't parse the URI -- it may not be valid. + path := s[len("file://"):] + // Handle microsoft/vscode#75027 by making it a special case. + // On Windows, VS Code sends file URIs that look like file:///C%3A/x/y/z. + // Replace the %3A so that the URI looks like: file:///C:/x/y/z. + if strings.ToLower(path[2:5]) == "%3a" { + path = path[:2] + ":" + path[5:] + } + // File URIs from Windows may have lowercase drive letters. + // Since drive letters are guaranteed to be case insensitive, + // we change them to uppercase to remain consistent. + // For example, file:///c:/x/y/z becomes file:///C:/x/y/z. + if isWindowsDriveURIPath(path) { + path = path[:1] + strings.ToUpper(string(path[1])) + path[2:] + } + return URI("file://" + path) } func CompareURI(a, b URI) int { @@ -111,9 +109,9 @@ func equalURI(a, b URI) bool { return os.SameFile(infoa, infob) } -// FileURI returns a span URI for the supplied file path. +// URIFromPath returns a span URI for the supplied file path. // It will always have the file scheme. -func FileURI(path string) URI { +func URIFromPath(path string) URI { if path == "" { return "" } diff --git a/internal/span/uri_test.go b/internal/span/uri_test.go index a3754e3381..be5bf8cb6d 100644 --- a/internal/span/uri_test.go +++ b/internal/span/uri_test.go @@ -16,7 +16,7 @@ import ( // include Windows-style URIs and filepaths, but we avoid having OS-specific // tests by using only forward slashes, assuming that the standard library // functions filepath.ToSlash and filepath.FromSlash do not need testing. -func TestURI(t *testing.T) { +func TestURIFromPath(t *testing.T) { for _, test := range []struct { path, wantFile string wantURI span.URI @@ -56,25 +56,42 @@ func TestURI(t *testing.T) { wantFile: `C:/Go/src/bob george/george/george.go`, wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), }, - { - path: `file:///c:/Go/src/bob%20george/george/george.go`, - wantFile: `C:/Go/src/bob george/george/george.go`, - wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), - }, - { - path: `file:///C%3A/Go/src/bob%20george/george/george.go`, - wantFile: `C:/Go/src/bob george/george/george.go`, - wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), - }, - { - path: `file:///path/to/%25p%25ercent%25/per%25cent.go`, - wantFile: `/path/to/%p%ercent%/per%cent.go`, - wantURI: span.URI(`file:///path/to/%25p%25ercent%25/per%25cent.go`), - }, } { - got := span.NewURI(test.path) + got := span.URIFromPath(test.path) if got != test.wantURI { - t.Errorf("NewURI(%q): got %q, expected %q", test.path, got, test.wantURI) + t.Errorf("URIFromPath(%q): got %q, expected %q", test.path, got, test.wantURI) + } + gotFilename := got.Filename() + if gotFilename != test.wantFile { + t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile) + } + } +} + +func TestURIFromURI(t *testing.T) { + for _, test := range []struct { + inputURI, wantFile string + wantURI span.URI + }{ + { + inputURI: `file:///c:/Go/src/bob%20george/george/george.go`, + wantFile: `C:/Go/src/bob george/george/george.go`, + wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), + }, + { + inputURI: `file:///C%3A/Go/src/bob%20george/george/george.go`, + wantFile: `C:/Go/src/bob george/george/george.go`, + wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), + }, + { + inputURI: `file:///path/to/%25p%25ercent%25/per%25cent.go`, + wantFile: `/path/to/%p%ercent%/per%cent.go`, + wantURI: span.URI(`file:///path/to/%25p%25ercent%25/per%25cent.go`), + }, + } { + got := span.URIFromURI(test.inputURI) + if got != test.wantURI { + t.Errorf("NewURI(%q): got %q, expected %q", test.inputURI, got, test.wantURI) } gotFilename := got.Filename() if gotFilename != test.wantFile { diff --git a/internal/span/uri_windows_test.go b/internal/span/uri_windows_test.go index 1370b19c8f..cb145ad57d 100644 --- a/internal/span/uri_windows_test.go +++ b/internal/span/uri_windows_test.go @@ -16,7 +16,7 @@ import ( // include Windows-style URIs and filepaths, but we avoid having OS-specific // tests by using only forward slashes, assuming that the standard library // functions filepath.ToSlash and filepath.FromSlash do not need testing. -func TestURI(t *testing.T) { +func TestURIFromPath(t *testing.T) { for _, test := range []struct { path, wantFile string wantURI span.URI @@ -56,28 +56,46 @@ func TestURI(t *testing.T) { wantFile: `C:\Go\src\bob george\george\george.go`, wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), }, + } { + got := span.URIFromPath(test.path) + if got != test.wantURI { + t.Errorf("URIFromPath(%q): got %q, expected %q", test.path, got, test.wantURI) + } + gotFilename := got.Filename() + if gotFilename != test.wantFile { + t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile) + } + } +} + +func TestURIFromURI(t *testing.T) { + for _, test := range []struct { + inputURI, wantFile string + wantURI span.URI + }{ { - path: `file:///c:/Go/src/bob%20george/george/george.go`, + inputURI: `file:///c:/Go/src/bob%20george/george/george.go`, wantFile: `C:\Go\src\bob george\george\george.go`, wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), }, { - path: `file:///C%3A/Go/src/bob%20george/george/george.go`, + inputURI: `file:///C%3A/Go/src/bob%20george/george/george.go`, wantFile: `C:\Go\src\bob george\george\george.go`, wantURI: span.URI("file:///C:/Go/src/bob%20george/george/george.go"), }, { - path: `file:///c:/path/to/%25p%25ercent%25/per%25cent.go`, + inputURI: `file:///c:/path/to/%25p%25ercent%25/per%25cent.go`, wantFile: `C:\path\to\%p%ercent%\per%cent.go`, wantURI: span.URI(`file:///C:/path/to/%25p%25ercent%25/per%25cent.go`), }, } { - got := span.NewURI(test.path) + got := span.URIFromURI(test.inputURI) if got != test.wantURI { - t.Errorf("ToURI: got %s, expected %s", got, test.wantURI) + t.Errorf("NewURI(%q): got %q, expected %q", test.inputURI, got, test.wantURI) } - if got.Filename() != test.wantFile { - t.Errorf("Filename: got %s, expected %s", got.Filename(), test.wantFile) + gotFilename := got.Filename() + if gotFilename != test.wantFile { + t.Errorf("Filename(%q): got %q, expected %q", got, gotFilename, test.wantFile) } } }