diff --git a/internal/lsp/cache/mod.go b/internal/lsp/cache/mod.go index 37fc6e6e09..03fdcbf086 100644 --- a/internal/lsp/cache/mod.go +++ b/internal/lsp/cache/mod.go @@ -55,11 +55,7 @@ func (s *snapshot) ParseMod(ctx context.Context, modFH source.FileHandle) (*sour if err != nil { return &parseModData{err: err} } - m := &protocol.ColumnMapper{ - URI: modFH.URI(), - TokFile: span.NewTokenFile(modFH.URI().Filename(), contents), - Content: contents, - } + m := protocol.NewColumnMapper(modFH.URI(), contents) file, parseErr := modfile.Parse(modFH.URI().Filename(), contents, nil) // Attempt to convert the error to a standardized parse error. var parseErrors []*source.Diagnostic @@ -133,11 +129,7 @@ func (s *snapshot) ParseWork(ctx context.Context, modFH source.FileHandle) (*sou if err != nil { return &parseWorkData{err: err} } - m := &protocol.ColumnMapper{ - URI: modFH.URI(), - TokFile: span.NewTokenFile(modFH.URI().Filename(), contents), - Content: contents, - } + m := protocol.NewColumnMapper(modFH.URI(), contents) file, parseErr := modfile.ParseWork(modFH.URI().Filename(), contents, nil) // Attempt to convert the error to a standardized parse error. var parseErrors []*source.Diagnostic diff --git a/internal/lsp/cmd/semantictokens.go b/internal/lsp/cmd/semantictokens.go index e4b1306ac0..7dbb7f93c6 100644 --- a/internal/lsp/cmd/semantictokens.go +++ b/internal/lsp/cmd/semantictokens.go @@ -117,12 +117,7 @@ func (c *semtok) Run(ctx context.Context, args ...string) error { // can't happen; just parsed this file return fmt.Errorf("can't find %s in fset", args[0]) } - tf := span.NewTokenFile(args[0], buf) - colmap = &protocol.ColumnMapper{ - URI: span.URI(args[0]), - Content: buf, - TokFile: tf, - } + colmap = protocol.NewColumnMapper(uri, buf) err = decorate(file.uri.Filename(), resp.Data) if err != nil { return err diff --git a/internal/lsp/command.go b/internal/lsp/command.go index 6e21c1b239..9bc979a133 100644 --- a/internal/lsp/command.go +++ b/internal/lsp/command.go @@ -579,11 +579,7 @@ func applyFileEdits(ctx context.Context, snapshot source.Snapshot, uri span.URI, return nil, err } - m := &protocol.ColumnMapper{ - URI: fh.URI(), - TokFile: span.NewTokenFile(fh.URI().Filename(), oldContent), - Content: oldContent, - } + m := protocol.NewColumnMapper(fh.URI(), oldContent) diff, err := snapshot.View().Options().ComputeEdits(uri, string(oldContent), string(newContent)) if err != nil { return nil, err diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go index c7cd530f20..ee364b8b03 100644 --- a/internal/lsp/lsp_test.go +++ b/internal/lsp/lsp_test.go @@ -1044,12 +1044,7 @@ func applyTextDocumentEdits(r *runner, edits []protocol.TextDocumentEdit) (map[s // If we have already edited this file, we use the edited version (rather than the // file in its original state) so that we preserve our initial changes. if content, ok := res[uri]; ok { - m = &protocol.ColumnMapper{ - URI: uri, - TokFile: span.NewTokenFile( - uri.Filename(), []byte(content)), - Content: []byte(content), - } + m = protocol.NewColumnMapper(uri, []byte(content)) } else { var err error if m, err = r.data.Mapper(uri); err != nil { @@ -1284,12 +1279,7 @@ func TestBytesOffset(t *testing.T) { f := fset.AddFile(fname, -1, len(test.text)) f.SetLinesForContent([]byte(test.text)) uri := span.URIFromPath(fname) - tf := span.NewTokenFile(fname, []byte(test.text)) - mapper := &protocol.ColumnMapper{ - URI: uri, - TokFile: tf, - Content: []byte(test.text), - } + mapper := protocol.NewColumnMapper(uri, []byte(test.text)) got, err := mapper.Point(test.pos) if err != nil && test.want != -1 { t.Errorf("unexpected error: %v", err) diff --git a/internal/lsp/protocol/span.go b/internal/lsp/protocol/span.go index 4a364d79d3..dac53cbc31 100644 --- a/internal/lsp/protocol/span.go +++ b/internal/lsp/protocol/span.go @@ -13,12 +13,24 @@ import ( "golang.org/x/tools/internal/span" ) +// A ColumnMapper maps between UTF-8 oriented positions (e.g. token.Pos, +// span.Span) and the UTF-16 oriented positions used by the LSP. type ColumnMapper struct { URI span.URI TokFile *token.File Content []byte } +// NewColumnMapper creates a new column mapper for the given uri and content. +func NewColumnMapper(uri span.URI, content []byte) *ColumnMapper { + tf := span.NewTokenFile(uri.Filename(), content) + return &ColumnMapper{ + URI: uri, + TokFile: tf, + Content: content, + } +} + func URIFromSpanURI(uri span.URI) DocumentURI { return DocumentURI(uri) } diff --git a/internal/lsp/source/rename.go b/internal/lsp/source/rename.go index 1cfba80a72..6312bcb129 100644 --- a/internal/lsp/source/rename.go +++ b/internal/lsp/source/rename.go @@ -171,12 +171,7 @@ func Rename(ctx context.Context, s Snapshot, f FileHandle, pp protocol.Position, if err != nil { return nil, err } - tf := span.NewTokenFile(uri.Filename(), data) - m := &protocol.ColumnMapper{ - URI: uri, - TokFile: tf, - Content: data, - } + m := protocol.NewColumnMapper(uri, data) // Sort the edits first. diff.SortTextEdits(edits) protocolEdits, err := ToProtocolEdits(m, edits) diff --git a/internal/lsp/tests/tests.go b/internal/lsp/tests/tests.go index 9a8b76d3b0..8265cf2e9b 100644 --- a/internal/lsp/tests/tests.go +++ b/internal/lsp/tests/tests.go @@ -997,12 +997,7 @@ func (data *Data) Mapper(uri span.URI) (*protocol.ColumnMapper, error) { if err != nil { return nil, err } - tf := span.NewTokenFile(uri.Filename(), content) - data.mappers[uri] = &protocol.ColumnMapper{ - URI: uri, - TokFile: tf, - Content: content, - } + data.mappers[uri] = protocol.NewColumnMapper(uri, content) } return data.mappers[uri], nil } diff --git a/internal/lsp/text_synchronization.go b/internal/lsp/text_synchronization.go index 157ae230bd..ff153d7094 100644 --- a/internal/lsp/text_synchronization.go +++ b/internal/lsp/text_synchronization.go @@ -340,12 +340,7 @@ func (s *Server) applyIncrementalChanges(ctx context.Context, uri span.URI, chan } for _, change := range changes { // Make sure to update column mapper along with the content. - tf := span.NewTokenFile(uri.Filename(), content) - m := &protocol.ColumnMapper{ - URI: uri, - TokFile: tf, - Content: content, - } + m := protocol.NewColumnMapper(uri, content) if change.Range == nil { return nil, fmt.Errorf("%w: unexpected nil range for change", jsonrpc2.ErrInternal) }