1// Copyright 2018 The Go Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// this file contains protocol<->span converters 16 17package protocol 18 19import ( 20 "fmt" 21 22 "github.com/KhronosGroup/SPIRV-Tools/utils/vscode/src/lsp/span" 23 24 errors "golang.org/x/xerrors" 25) 26 27type ColumnMapper struct { 28 URI span.URI 29 Converter *span.TokenConverter 30 Content []byte 31} 32 33func NewURI(uri span.URI) string { 34 return string(uri) 35} 36 37func (m *ColumnMapper) Location(s span.Span) (Location, error) { 38 rng, err := m.Range(s) 39 if err != nil { 40 return Location{}, err 41 } 42 return Location{URI: NewURI(s.URI()), Range: rng}, nil 43} 44 45func (m *ColumnMapper) Range(s span.Span) (Range, error) { 46 if span.CompareURI(m.URI, s.URI()) != 0 { 47 return Range{}, errors.Errorf("column mapper is for file %q instead of %q", m.URI, s.URI()) 48 } 49 s, err := s.WithAll(m.Converter) 50 if err != nil { 51 return Range{}, err 52 } 53 start, err := m.Position(s.Start()) 54 if err != nil { 55 return Range{}, err 56 } 57 end, err := m.Position(s.End()) 58 if err != nil { 59 return Range{}, err 60 } 61 return Range{Start: start, End: end}, nil 62} 63 64func (m *ColumnMapper) Position(p span.Point) (Position, error) { 65 chr, err := span.ToUTF16Column(p, m.Content) 66 if err != nil { 67 return Position{}, err 68 } 69 return Position{ 70 Line: float64(p.Line() - 1), 71 Character: float64(chr - 1), 72 }, nil 73} 74 75func (m *ColumnMapper) Span(l Location) (span.Span, error) { 76 return m.RangeSpan(l.Range) 77} 78 79func (m *ColumnMapper) RangeSpan(r Range) (span.Span, error) { 80 start, err := m.Point(r.Start) 81 if err != nil { 82 return span.Span{}, err 83 } 84 end, err := m.Point(r.End) 85 if err != nil { 86 return span.Span{}, err 87 } 88 return span.New(m.URI, start, end).WithAll(m.Converter) 89} 90 91func (m *ColumnMapper) PointSpan(p Position) (span.Span, error) { 92 start, err := m.Point(p) 93 if err != nil { 94 return span.Span{}, err 95 } 96 return span.New(m.URI, start, start).WithAll(m.Converter) 97} 98 99func (m *ColumnMapper) Point(p Position) (span.Point, error) { 100 line := int(p.Line) + 1 101 offset, err := m.Converter.ToOffset(line, 1) 102 if err != nil { 103 return span.Point{}, err 104 } 105 lineStart := span.NewPoint(line, 1, offset) 106 return span.FromUTF16Column(lineStart, int(p.Character)+1, m.Content) 107} 108 109func IsPoint(r Range) bool { 110 return r.Start.Line == r.End.Line && r.Start.Character == r.End.Character 111} 112 113func CompareRange(a, b Range) int { 114 if r := ComparePosition(a.Start, b.Start); r != 0 { 115 return r 116 } 117 return ComparePosition(a.End, b.End) 118} 119 120func ComparePosition(a, b Position) int { 121 if a.Line < b.Line { 122 return -1 123 } 124 if a.Line > b.Line { 125 return 1 126 } 127 if a.Character < b.Character { 128 return -1 129 } 130 if a.Character > b.Character { 131 return 1 132 } 133 return 0 134} 135 136func (r Range) Format(f fmt.State, _ rune) { 137 fmt.Fprintf(f, "%v:%v-%v:%v", r.Start.Line, r.Start.Character, r.End.Line, r.End.Character) 138} 139