golang.org/x/tools/gopls@v0.15.3/internal/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 package protocol 6 7 import ( 8 "fmt" 9 "unicode/utf8" 10 ) 11 12 // CompareLocation defines a three-valued comparison over locations, 13 // lexicographically ordered by (URI, Range). 14 func CompareLocation(x, y Location) int { 15 if x.URI != y.URI { 16 if x.URI < y.URI { 17 return -1 18 } else { 19 return +1 20 } 21 } 22 return CompareRange(x.Range, y.Range) 23 } 24 25 // CompareRange returns -1 if a is before b, 0 if a == b, and 1 if a is after b. 26 // 27 // A range a is defined to be 'before' b if a.Start is before b.Start, or 28 // a.Start == b.Start and a.End is before b.End. 29 func CompareRange(a, b Range) int { 30 if r := ComparePosition(a.Start, b.Start); r != 0 { 31 return r 32 } 33 return ComparePosition(a.End, b.End) 34 } 35 36 // ComparePosition returns -1 if a is before b, 0 if a == b, and 1 if a is after b. 37 func ComparePosition(a, b Position) int { 38 if a.Line != b.Line { 39 if a.Line < b.Line { 40 return -1 41 } else { 42 return +1 43 } 44 } 45 if a.Character != b.Character { 46 if a.Character < b.Character { 47 return -1 48 } else { 49 return +1 50 } 51 } 52 return 0 53 } 54 55 func Intersect(a, b Range) bool { 56 if a.Start.Line > b.End.Line || a.End.Line < b.Start.Line { 57 return false 58 } 59 return !((a.Start.Line == b.End.Line) && a.Start.Character > b.End.Character || 60 (a.End.Line == b.Start.Line) && a.End.Character < b.Start.Character) 61 } 62 63 // Format implements fmt.Formatter. 64 // 65 // Note: Formatter is implemented instead of Stringer (presumably) for 66 // performance reasons, though it is not clear that it matters in practice. 67 func (r Range) Format(f fmt.State, _ rune) { 68 fmt.Fprintf(f, "%v-%v", r.Start, r.End) 69 } 70 71 // Format implements fmt.Formatter. 72 // 73 // See Range.Format for discussion of why the Formatter interface is 74 // implemented rather than Stringer. 75 func (p Position) Format(f fmt.State, _ rune) { 76 fmt.Fprintf(f, "%v:%v", p.Line, p.Character) 77 } 78 79 // -- implementation helpers -- 80 81 // UTF16Len returns the number of codes in the UTF-16 transcoding of s. 82 func UTF16Len(s []byte) int { 83 var n int 84 for len(s) > 0 { 85 n++ 86 87 // Fast path for ASCII. 88 if s[0] < 0x80 { 89 s = s[1:] 90 continue 91 } 92 93 r, size := utf8.DecodeRune(s) 94 if r >= 0x10000 { 95 n++ // surrogate pair 96 } 97 s = s[size:] 98 } 99 return n 100 }