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  }