diff --git a/internal/lsp/link.go b/internal/lsp/link.go index a2962b6659..65da8a54c3 100644 --- a/internal/lsp/link.go +++ b/internal/lsp/link.go @@ -49,6 +49,8 @@ func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandl if err != nil { return nil, err } + tokFile := pm.Mapper.TokFile + var links []protocol.DocumentLink for _, req := range pm.File.Require { if req.Syntax == nil { @@ -66,9 +68,9 @@ func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandl } // Shift the start position to the location of the // dependency within the require statement. - start, end := token.Pos(s+i), token.Pos(s+i+len(dep)) + start, end := tokFile.Pos(s+i), tokFile.Pos(s+i+len(dep)) target := source.BuildLink(snapshot.View().Options().LinkTarget, "mod/"+req.Mod.String(), "") - l, err := toProtocolLink(nil, pm.Mapper, target, start, end, source.Mod) + l, err := toProtocolLink(tokFile, pm.Mapper, target, start, end) if err != nil { return nil, err } @@ -79,9 +81,6 @@ func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandl return links, nil } - // Create a throwaway token.File. - tokFile := token.NewFileSet().AddFile(fh.URI().Filename(), -1, len(pm.Mapper.Content)) - // Get all the links that are contained in the comments of the file. for _, expr := range pm.File.Syntax.Stmt { comments := expr.Comment() @@ -91,7 +90,7 @@ func modLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandl for _, section := range [][]modfile.Comment{comments.Before, comments.Suffix, comments.After} { for _, comment := range section { start := tokFile.Pos(comment.Start.Byte) - l, err := findLinksInString(ctx, snapshot, comment.Token, start, tokFile, pm.Mapper, source.Mod) + l, err := findLinksInString(ctx, snapshot, comment.Token, start, tokFile, pm.Mapper) if err != nil { return nil, err } @@ -148,8 +147,8 @@ func goLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle // Account for the quotation marks in the positions. start := imp.Path.Pos() + 1 end := imp.Path.End() - 1 - target = source.BuildLink(view.Options().LinkTarget, target, "") - l, err := toProtocolLink(pgf.Tok, pgf.Mapper, target, start, end, source.Go) + targetURL := source.BuildLink(view.Options().LinkTarget, target, "") + l, err := toProtocolLink(pgf.Tok, pgf.Mapper, targetURL, start, end) if err != nil { return nil, err } @@ -157,7 +156,7 @@ func goLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle } } for _, s := range str { - l, err := findLinksInString(ctx, snapshot, s.Value, s.Pos(), pgf.Tok, pgf.Mapper, source.Go) + l, err := findLinksInString(ctx, snapshot, s.Value, s.Pos(), pgf.Tok, pgf.Mapper) if err != nil { return nil, err } @@ -165,7 +164,7 @@ func goLinks(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle } for _, commentGroup := range pgf.File.Comments { for _, comment := range commentGroup.List { - l, err := findLinksInString(ctx, snapshot, comment.Text, comment.Pos(), pgf.Tok, pgf.Mapper, source.Go) + l, err := findLinksInString(ctx, snapshot, comment.Text, comment.Pos(), pgf.Tok, pgf.Mapper) if err != nil { return nil, err } @@ -199,7 +198,7 @@ var acceptedSchemes = map[string]bool{ } // tokFile may be a throwaway File for non-Go files. -func findLinksInString(ctx context.Context, snapshot source.Snapshot, src string, pos token.Pos, tokFile *token.File, m *protocol.ColumnMapper, fileKind source.FileKind) ([]protocol.DocumentLink, error) { +func findLinksInString(ctx context.Context, snapshot source.Snapshot, src string, pos token.Pos, tokFile *token.File, m *protocol.ColumnMapper) ([]protocol.DocumentLink, error) { var links []protocol.DocumentLink for _, index := range snapshot.View().Options().URLRegexp.FindAllIndex([]byte(src), -1) { start, end := index[0], index[1] @@ -222,7 +221,7 @@ func findLinksInString(ctx context.Context, snapshot source.Snapshot, src string if !acceptedSchemes[linkURL.Scheme] { continue } - l, err := toProtocolLink(tokFile, m, linkURL.String(), startPos, endPos, fileKind) + l, err := toProtocolLink(tokFile, m, linkURL.String(), startPos, endPos) if err != nil { return nil, err } @@ -239,8 +238,8 @@ func findLinksInString(ctx context.Context, snapshot source.Snapshot, src string continue } org, repo, number := matches[1], matches[2], matches[3] - target := fmt.Sprintf("https://github.com/%s/%s/issues/%s", org, repo, number) - l, err := toProtocolLink(tokFile, m, target, startPos, endPos, fileKind) + targetURL := fmt.Sprintf("https://github.com/%s/%s/issues/%s", org, repo, number) + l, err := toProtocolLink(tokFile, m, targetURL, startPos, endPos) if err != nil { return nil, err } @@ -261,38 +260,17 @@ var ( issueRegexp *regexp.Regexp ) -func toProtocolLink(tokFile *token.File, m *protocol.ColumnMapper, target string, start, end token.Pos, fileKind source.FileKind) (protocol.DocumentLink, error) { - var rng protocol.Range - switch fileKind { - case source.Go: - // TODO(adonovan): can we now use this logic for the Mod case too? - spn, err := span.NewRange(tokFile, start, end).Span() - if err != nil { - return protocol.DocumentLink{}, err - } - rng, err = m.Range(spn) - if err != nil { - return protocol.DocumentLink{}, err - } - case source.Mod: - s, e := int(start), int(end) - line, col, err := span.ToPosition(m.TokFile, s) - if err != nil { - return protocol.DocumentLink{}, err - } - start := span.NewPoint(line, col, s) - line, col, err = span.ToPosition(m.TokFile, e) - if err != nil { - return protocol.DocumentLink{}, err - } - end := span.NewPoint(line, col, e) - rng, err = m.Range(span.New(m.URI, start, end)) - if err != nil { - return protocol.DocumentLink{}, err - } +func toProtocolLink(tokFile *token.File, m *protocol.ColumnMapper, targetURL string, start, end token.Pos) (protocol.DocumentLink, error) { + spn, err := span.NewRange(tokFile, start, end).Span() + if err != nil { + return protocol.DocumentLink{}, err + } + rng, err := m.Range(spn) + if err != nil { + return protocol.DocumentLink{}, err } return protocol.DocumentLink{ Range: rng, - Target: target, + Target: targetURL, }, nil }