github.com/v2fly/tools@v0.100.0/internal/lsp/protocol/span.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // this file contains protocol<->span converters 6 7 package protocol 8 9 import ( 10 "fmt" 11 12 "github.com/v2fly/tools/internal/span" 13 errors "golang.org/x/xerrors" 14 ) 15 16 type ColumnMapper struct { 17 URI span.URI 18 Converter *span.TokenConverter 19 Content []byte 20 } 21 22 func URIFromSpanURI(uri span.URI) DocumentURI { 23 return DocumentURI(uri) 24 } 25 26 func URIFromPath(path string) DocumentURI { 27 return URIFromSpanURI(span.URIFromPath(path)) 28 } 29 30 func (u DocumentURI) SpanURI() span.URI { 31 return span.URIFromURI(string(u)) 32 } 33 34 func (m *ColumnMapper) Location(s span.Span) (Location, error) { 35 rng, err := m.Range(s) 36 if err != nil { 37 return Location{}, err 38 } 39 return Location{URI: URIFromSpanURI(s.URI()), Range: rng}, nil 40 } 41 42 func (m *ColumnMapper) Range(s span.Span) (Range, error) { 43 if span.CompareURI(m.URI, s.URI()) != 0 { 44 return Range{}, errors.Errorf("column mapper is for file %q instead of %q", m.URI, s.URI()) 45 } 46 s, err := s.WithAll(m.Converter) 47 if err != nil { 48 return Range{}, err 49 } 50 start, err := m.Position(s.Start()) 51 if err != nil { 52 return Range{}, err 53 } 54 end, err := m.Position(s.End()) 55 if err != nil { 56 return Range{}, err 57 } 58 return Range{Start: start, End: end}, nil 59 } 60 61 func (m *ColumnMapper) Position(p span.Point) (Position, error) { 62 chr, err := span.ToUTF16Column(p, m.Content) 63 if err != nil { 64 return Position{}, err 65 } 66 return Position{ 67 Line: uint32(p.Line() - 1), 68 Character: uint32(chr - 1), 69 }, nil 70 } 71 72 func (m *ColumnMapper) Span(l Location) (span.Span, error) { 73 return m.RangeSpan(l.Range) 74 } 75 76 func (m *ColumnMapper) RangeSpan(r Range) (span.Span, error) { 77 start, err := m.Point(r.Start) 78 if err != nil { 79 return span.Span{}, err 80 } 81 end, err := m.Point(r.End) 82 if err != nil { 83 return span.Span{}, err 84 } 85 return span.New(m.URI, start, end).WithAll(m.Converter) 86 } 87 88 func (m *ColumnMapper) RangeToSpanRange(r Range) (span.Range, error) { 89 spn, err := m.RangeSpan(r) 90 if err != nil { 91 return span.Range{}, err 92 } 93 return spn.Range(m.Converter) 94 } 95 96 func (m *ColumnMapper) PointSpan(p Position) (span.Span, error) { 97 start, err := m.Point(p) 98 if err != nil { 99 return span.Span{}, err 100 } 101 return span.New(m.URI, start, start).WithAll(m.Converter) 102 } 103 104 func (m *ColumnMapper) Point(p Position) (span.Point, error) { 105 line := int(p.Line) + 1 106 offset, err := m.Converter.ToOffset(line, 1) 107 if err != nil { 108 return span.Point{}, err 109 } 110 lineStart := span.NewPoint(line, 1, offset) 111 return span.FromUTF16Column(lineStart, int(p.Character)+1, m.Content) 112 } 113 114 func IsPoint(r Range) bool { 115 return r.Start.Line == r.End.Line && r.Start.Character == r.End.Character 116 } 117 118 func CompareRange(a, b Range) int { 119 if r := ComparePosition(a.Start, b.Start); r != 0 { 120 return r 121 } 122 return ComparePosition(a.End, b.End) 123 } 124 125 func ComparePosition(a, b Position) int { 126 if a.Line < b.Line { 127 return -1 128 } 129 if a.Line > b.Line { 130 return 1 131 } 132 if a.Character < b.Character { 133 return -1 134 } 135 if a.Character > b.Character { 136 return 1 137 } 138 return 0 139 } 140 141 func Intersect(a, b Range) bool { 142 if a.Start.Line > b.End.Line || a.End.Line < b.Start.Line { 143 return false 144 } 145 return !((a.Start.Line == b.End.Line) && a.Start.Character > b.End.Character || 146 (a.End.Line == b.Start.Line) && a.End.Character < b.Start.Character) 147 } 148 149 func (r Range) Format(f fmt.State, _ rune) { 150 fmt.Fprintf(f, "%v:%v-%v:%v", r.Start.Line, r.Start.Character, r.End.Line, r.End.Character) 151 }