mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
internal/lsp: switch folding range to protocol ranges
Change-Id: I899b3cd89901b99a5c65a5be79ac561289506623 Reviewed-on: https://go-review.googlesource.com/c/tools/+/193724 Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
parent
04840ef8f3
commit
73ad5c96a1
@ -15,14 +15,27 @@ func (s *Server) foldingRange(ctx context.Context, params *protocol.FoldingRange
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
m, err := getMapper(ctx, f)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ranges, err := source.FoldingRange(ctx, view, f, s.session.Options().LineFoldingOnly)
|
ranges, err := source.FoldingRange(ctx, view, f, s.session.Options().LineFoldingOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return source.ToProtocolFoldingRanges(m, ranges)
|
return toProtocolFoldingRanges(ranges)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toProtocolFoldingRanges(ranges []*source.FoldingRangeInfo) ([]protocol.FoldingRange, error) {
|
||||||
|
result := make([]protocol.FoldingRange, 0, len(ranges))
|
||||||
|
for _, info := range ranges {
|
||||||
|
rng, err := info.Range()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result = append(result, protocol.FoldingRange{
|
||||||
|
StartLine: rng.Start.Line,
|
||||||
|
StartCharacter: rng.Start.Character,
|
||||||
|
EndLine: rng.End.Line,
|
||||||
|
EndCharacter: rng.End.Character,
|
||||||
|
Kind: string(info.Kind),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
m, err := getMapper(ctx, f)
|
data, _, err := f.Handle(ctx).Read(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -35,6 +35,8 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink
|
|||||||
if file == nil {
|
if file == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
tok := view.Session().Cache().FileSet().File(file.Pos())
|
||||||
|
m := protocol.NewColumnMapper(f.URI(), f.URI().Filename(), f.FileSet(), tok, data)
|
||||||
|
|
||||||
var links []protocol.DocumentLink
|
var links []protocol.DocumentLink
|
||||||
ast.Inspect(file, func(node ast.Node) bool {
|
ast.Inspect(file, func(node ast.Node) bool {
|
||||||
|
@ -11,8 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FoldingRangeInfo struct {
|
type FoldingRangeInfo struct {
|
||||||
Range span.Range
|
mappedRange
|
||||||
Kind protocol.FoldingRangeKind
|
Kind protocol.FoldingRangeKind
|
||||||
}
|
}
|
||||||
|
|
||||||
// FoldingRange gets all of the folding range for f.
|
// FoldingRange gets all of the folding range for f.
|
||||||
@ -24,9 +24,14 @@ func FoldingRange(ctx context.Context, view View, f GoFile, lineFoldingOnly bool
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
data, _, err := f.Handle(ctx).Read(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m := protocol.NewColumnMapper(f.URI(), f.URI().Filename(), fset, fset.File(file.Pos()), data)
|
||||||
|
|
||||||
// Get folding ranges for comments separately as they are not walked by ast.Inspect.
|
// Get folding ranges for comments separately as they are not walked by ast.Inspect.
|
||||||
ranges = append(ranges, commentsFoldingRange(f.FileSet(), file)...)
|
ranges = append(ranges, commentsFoldingRange(view, m, file)...)
|
||||||
|
|
||||||
foldingFunc := foldingRange
|
foldingFunc := foldingRange
|
||||||
if lineFoldingOnly {
|
if lineFoldingOnly {
|
||||||
@ -34,29 +39,26 @@ func FoldingRange(ctx context.Context, view View, f GoFile, lineFoldingOnly bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
visit := func(n ast.Node) bool {
|
visit := func(n ast.Node) bool {
|
||||||
rng := foldingFunc(fset, n)
|
rng := foldingFunc(view, m, n)
|
||||||
if rng != nil {
|
if rng != nil {
|
||||||
ranges = append(ranges, rng)
|
ranges = append(ranges, rng)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk the ast and collect folding ranges.
|
// Walk the ast and collect folding ranges.
|
||||||
ast.Inspect(file, visit)
|
ast.Inspect(file, visit)
|
||||||
|
|
||||||
sort.Slice(ranges, func(i, j int) bool {
|
sort.Slice(ranges, func(i, j int) bool {
|
||||||
if ranges[i].Range.Start < ranges[j].Range.Start {
|
irng, _ := ranges[i].Range()
|
||||||
return true
|
jrng, _ := ranges[j].Range()
|
||||||
} else if ranges[i].Range.Start > ranges[j].Range.Start {
|
return protocol.CompareRange(irng, jrng) < 0
|
||||||
return false
|
|
||||||
}
|
|
||||||
return ranges[i].Range.End < ranges[j].Range.End
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return ranges, nil
|
return ranges, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// foldingRange calculates the folding range for n.
|
// foldingRange calculates the folding range for n.
|
||||||
func foldingRange(fset *token.FileSet, n ast.Node) *FoldingRangeInfo {
|
func foldingRange(view View, m *protocol.ColumnMapper, n ast.Node) *FoldingRangeInfo {
|
||||||
var kind protocol.FoldingRangeKind
|
var kind protocol.FoldingRangeKind
|
||||||
var start, end token.Pos
|
var start, end token.Pos
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
@ -80,18 +82,22 @@ func foldingRange(fset *token.FileSet, n ast.Node) *FoldingRangeInfo {
|
|||||||
}
|
}
|
||||||
start, end = n.Lparen+1, n.Rparen
|
start, end = n.Lparen+1, n.Rparen
|
||||||
}
|
}
|
||||||
|
|
||||||
if !start.IsValid() || !end.IsValid() {
|
if !start.IsValid() || !end.IsValid() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &FoldingRangeInfo{
|
return &FoldingRangeInfo{
|
||||||
Range: span.NewRange(fset, start, end),
|
mappedRange: mappedRange{
|
||||||
Kind: kind,
|
m: m,
|
||||||
|
spanRange: span.NewRange(view.Session().Cache().FileSet(), start, end),
|
||||||
|
},
|
||||||
|
Kind: kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lineFoldingRange calculates the line folding range for n.
|
// lineFoldingRange calculates the line folding range for n.
|
||||||
func lineFoldingRange(fset *token.FileSet, n ast.Node) *FoldingRangeInfo {
|
func lineFoldingRange(view View, m *protocol.ColumnMapper, n ast.Node) *FoldingRangeInfo {
|
||||||
|
fset := view.Session().Cache().FileSet()
|
||||||
|
|
||||||
// TODO(suzmue): include trailing empty lines before the closing
|
// TODO(suzmue): include trailing empty lines before the closing
|
||||||
// parenthesis/brace.
|
// parenthesis/brace.
|
||||||
var kind protocol.FoldingRangeKind
|
var kind protocol.FoldingRangeKind
|
||||||
@ -169,47 +175,31 @@ func lineFoldingRange(fset *token.FileSet, n ast.Node) *FoldingRangeInfo {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &FoldingRangeInfo{
|
return &FoldingRangeInfo{
|
||||||
Range: span.NewRange(fset, start, end),
|
mappedRange: mappedRange{
|
||||||
Kind: kind,
|
m: m,
|
||||||
|
spanRange: span.NewRange(fset, start, end),
|
||||||
|
},
|
||||||
|
Kind: kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// commentsFoldingRange returns the folding ranges for all comment blocks in file.
|
// commentsFoldingRange returns the folding ranges for all comment blocks in file.
|
||||||
// The folding range starts at the end of the first comment, and ends at the end of the
|
// The folding range starts at the end of the first comment, and ends at the end of the
|
||||||
// comment block and has kind protocol.Comment.
|
// comment block and has kind protocol.Comment.
|
||||||
func commentsFoldingRange(fset *token.FileSet, file *ast.File) (comments []*FoldingRangeInfo) {
|
func commentsFoldingRange(view View, m *protocol.ColumnMapper, file *ast.File) (comments []*FoldingRangeInfo) {
|
||||||
for _, commentGrp := range file.Comments {
|
for _, commentGrp := range file.Comments {
|
||||||
// Don't fold single comments.
|
// Don't fold single comments.
|
||||||
if len(commentGrp.List) <= 1 {
|
if len(commentGrp.List) <= 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
comments = append(comments, &FoldingRangeInfo{
|
comments = append(comments, &FoldingRangeInfo{
|
||||||
// Fold from the end of the first line comment to the end of the comment block.
|
mappedRange: mappedRange{
|
||||||
Range: span.NewRange(fset, commentGrp.List[0].End(), commentGrp.End()),
|
m: m,
|
||||||
Kind: protocol.Comment,
|
// Fold from the end of the first line comment to the end of the comment block.
|
||||||
|
spanRange: span.NewRange(view.Session().Cache().FileSet(), commentGrp.List[0].End(), commentGrp.End()),
|
||||||
|
},
|
||||||
|
Kind: protocol.Comment,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return comments
|
return comments
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToProtocolFoldingRanges(m *protocol.ColumnMapper, ranges []*FoldingRangeInfo) ([]protocol.FoldingRange, error) {
|
|
||||||
var res []protocol.FoldingRange
|
|
||||||
for _, r := range ranges {
|
|
||||||
spn, err := r.Range.Span()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
rng, err := m.Range(spn)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
res = append(res, protocol.FoldingRange{
|
|
||||||
StartLine: rng.Start.Line,
|
|
||||||
StartCharacter: rng.Start.Character,
|
|
||||||
EndLine: rng.End.Line,
|
|
||||||
EndCharacter: rng.End.Character,
|
|
||||||
Kind: string(r.Kind),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
@ -305,7 +305,7 @@ func (r *runner) FoldingRange(t *testing.T, data tests.FoldingRanges) {
|
|||||||
func (r *runner) foldingRanges(t *testing.T, prefix string, uri span.URI, data string, ranges []*source.FoldingRangeInfo) {
|
func (r *runner) foldingRanges(t *testing.T, prefix string, uri span.URI, data string, ranges []*source.FoldingRangeInfo) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// Fold all ranges.
|
// Fold all ranges.
|
||||||
nonOverlapping := nonOverlappingRanges(ranges)
|
nonOverlapping := nonOverlappingRanges(t, ranges)
|
||||||
for i, rngs := range nonOverlapping {
|
for i, rngs := range nonOverlapping {
|
||||||
got, err := foldRanges(string(data), rngs)
|
got, err := foldRanges(string(data), rngs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -332,7 +332,7 @@ func (r *runner) foldingRanges(t *testing.T, prefix string, uri span.URI, data s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nonOverlapping := nonOverlappingRanges(kindOnly)
|
nonOverlapping := nonOverlappingRanges(t, kindOnly)
|
||||||
for i, rngs := range nonOverlapping {
|
for i, rngs := range nonOverlapping {
|
||||||
got, err := foldRanges(string(data), rngs)
|
got, err := foldRanges(string(data), rngs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -352,13 +352,13 @@ func (r *runner) foldingRanges(t *testing.T, prefix string, uri span.URI, data s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nonOverlappingRanges(ranges []*source.FoldingRangeInfo) (res [][]*source.FoldingRangeInfo) {
|
func nonOverlappingRanges(t *testing.T, ranges []*source.FoldingRangeInfo) (res [][]*source.FoldingRangeInfo) {
|
||||||
for _, fRng := range ranges {
|
for _, fRng := range ranges {
|
||||||
setNum := len(res)
|
setNum := len(res)
|
||||||
for i := 0; i < len(res); i++ {
|
for i := 0; i < len(res); i++ {
|
||||||
canInsert := true
|
canInsert := true
|
||||||
for _, rng := range res[i] {
|
for _, rng := range res[i] {
|
||||||
if conflict(rng, fRng) {
|
if conflict(t, rng, fRng) {
|
||||||
canInsert = false
|
canInsert = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -376,9 +376,17 @@ func nonOverlappingRanges(ranges []*source.FoldingRangeInfo) (res [][]*source.Fo
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func conflict(a, b *source.FoldingRangeInfo) bool {
|
func conflict(t *testing.T, a, b *source.FoldingRangeInfo) bool {
|
||||||
|
arng, err := a.Range()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
brng, err := b.Range()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
// a start position is <= b start positions
|
// a start position is <= b start positions
|
||||||
return a.Range.Start <= b.Range.Start && a.Range.End > b.Range.Start
|
return protocol.ComparePosition(arng.Start, brng.Start) <= 0 && protocol.ComparePosition(arng.End, brng.Start) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func foldRanges(contents string, ranges []*source.FoldingRangeInfo) (string, error) {
|
func foldRanges(contents string, ranges []*source.FoldingRangeInfo) (string, error) {
|
||||||
@ -388,7 +396,7 @@ func foldRanges(contents string, ranges []*source.FoldingRangeInfo) (string, err
|
|||||||
// to preserve the offsets.
|
// to preserve the offsets.
|
||||||
for i := len(ranges) - 1; i >= 0; i-- {
|
for i := len(ranges) - 1; i >= 0; i-- {
|
||||||
fRange := ranges[i]
|
fRange := ranges[i]
|
||||||
spn, err := fRange.Range.Span()
|
spn, err := fRange.Span()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user