Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / span / span.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/span/span.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/span/span.go
new file mode 100644 (file)
index 0000000..4d2ad09
--- /dev/null
@@ -0,0 +1,285 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package span contains support for representing with positions and ranges in
+// text files.
+package span
+
+import (
+       "encoding/json"
+       "fmt"
+       "path"
+)
+
+// Span represents a source code range in standardized form.
+type Span struct {
+       v span
+}
+
+// Point represents a single point within a file.
+// In general this should only be used as part of a Span, as on its own it
+// does not carry enough information.
+type Point struct {
+       v point
+}
+
+type span struct {
+       URI   URI   `json:"uri"`
+       Start point `json:"start"`
+       End   point `json:"end"`
+}
+
+type point struct {
+       Line   int `json:"line"`
+       Column int `json:"column"`
+       Offset int `json:"offset"`
+}
+
+// Invalid is a span that reports false from IsValid
+var Invalid = Span{v: span{Start: invalidPoint.v, End: invalidPoint.v}}
+
+var invalidPoint = Point{v: point{Line: 0, Column: 0, Offset: -1}}
+
+// Converter is the interface to an object that can convert between line:column
+// and offset forms for a single file.
+type Converter interface {
+       //ToPosition converts from an offset to a line:column pair.
+       ToPosition(offset int) (int, int, error)
+       //ToOffset converts from a line:column pair to an offset.
+       ToOffset(line, col int) (int, error)
+}
+
+func New(uri URI, start Point, end Point) Span {
+       s := Span{v: span{URI: uri, Start: start.v, End: end.v}}
+       s.v.clean()
+       return s
+}
+
+func NewPoint(line, col, offset int) Point {
+       p := Point{v: point{Line: line, Column: col, Offset: offset}}
+       p.v.clean()
+       return p
+}
+
+func Compare(a, b Span) int {
+       if r := CompareURI(a.URI(), b.URI()); r != 0 {
+               return r
+       }
+       if r := comparePoint(a.v.Start, b.v.Start); r != 0 {
+               return r
+       }
+       return comparePoint(a.v.End, b.v.End)
+}
+
+func ComparePoint(a, b Point) int {
+       return comparePoint(a.v, b.v)
+}
+
+func comparePoint(a, b point) int {
+       if !a.hasPosition() {
+               if a.Offset < b.Offset {
+                       return -1
+               }
+               if a.Offset > b.Offset {
+                       return 1
+               }
+               return 0
+       }
+       if a.Line < b.Line {
+               return -1
+       }
+       if a.Line > b.Line {
+               return 1
+       }
+       if a.Column < b.Column {
+               return -1
+       }
+       if a.Column > b.Column {
+               return 1
+       }
+       return 0
+}
+
+func (s Span) HasPosition() bool             { return s.v.Start.hasPosition() }
+func (s Span) HasOffset() bool               { return s.v.Start.hasOffset() }
+func (s Span) IsValid() bool                 { return s.v.Start.isValid() }
+func (s Span) IsPoint() bool                 { return s.v.Start == s.v.End }
+func (s Span) URI() URI                      { return s.v.URI }
+func (s Span) Start() Point                  { return Point{s.v.Start} }
+func (s Span) End() Point                    { return Point{s.v.End} }
+func (s *Span) MarshalJSON() ([]byte, error) { return json.Marshal(&s.v) }
+func (s *Span) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &s.v) }
+
+func (p Point) HasPosition() bool             { return p.v.hasPosition() }
+func (p Point) HasOffset() bool               { return p.v.hasOffset() }
+func (p Point) IsValid() bool                 { return p.v.isValid() }
+func (p *Point) MarshalJSON() ([]byte, error) { return json.Marshal(&p.v) }
+func (p *Point) UnmarshalJSON(b []byte) error { return json.Unmarshal(b, &p.v) }
+func (p Point) Line() int {
+       if !p.v.hasPosition() {
+               panic(fmt.Errorf("position not set in %v", p.v))
+       }
+       return p.v.Line
+}
+func (p Point) Column() int {
+       if !p.v.hasPosition() {
+               panic(fmt.Errorf("position not set in %v", p.v))
+       }
+       return p.v.Column
+}
+func (p Point) Offset() int {
+       if !p.v.hasOffset() {
+               panic(fmt.Errorf("offset not set in %v", p.v))
+       }
+       return p.v.Offset
+}
+
+func (p point) hasPosition() bool { return p.Line > 0 }
+func (p point) hasOffset() bool   { return p.Offset >= 0 }
+func (p point) isValid() bool     { return p.hasPosition() || p.hasOffset() }
+func (p point) isZero() bool {
+       return (p.Line == 1 && p.Column == 1) || (!p.hasPosition() && p.Offset == 0)
+}
+
+func (s *span) clean() {
+       //this presumes the points are already clean
+       if !s.End.isValid() || (s.End == point{}) {
+               s.End = s.Start
+       }
+}
+
+func (p *point) clean() {
+       if p.Line < 0 {
+               p.Line = 0
+       }
+       if p.Column <= 0 {
+               if p.Line > 0 {
+                       p.Column = 1
+               } else {
+                       p.Column = 0
+               }
+       }
+       if p.Offset == 0 && (p.Line > 1 || p.Column > 1) {
+               p.Offset = -1
+       }
+}
+
+// Format implements fmt.Formatter to print the Location in a standard form.
+// The format produced is one that can be read back in using Parse.
+func (s Span) Format(f fmt.State, c rune) {
+       fullForm := f.Flag('+')
+       preferOffset := f.Flag('#')
+       // we should always have a uri, simplify if it is file format
+       //TODO: make sure the end of the uri is unambiguous
+       uri := string(s.v.URI)
+       if c == 'f' {
+               uri = path.Base(uri)
+       } else if !fullForm {
+               uri = s.v.URI.Filename()
+       }
+       fmt.Fprint(f, uri)
+       if !s.IsValid() || (!fullForm && s.v.Start.isZero() && s.v.End.isZero()) {
+               return
+       }
+       // see which bits of start to write
+       printOffset := s.HasOffset() && (fullForm || preferOffset || !s.HasPosition())
+       printLine := s.HasPosition() && (fullForm || !printOffset)
+       printColumn := printLine && (fullForm || (s.v.Start.Column > 1 || s.v.End.Column > 1))
+       fmt.Fprint(f, ":")
+       if printLine {
+               fmt.Fprintf(f, "%d", s.v.Start.Line)
+       }
+       if printColumn {
+               fmt.Fprintf(f, ":%d", s.v.Start.Column)
+       }
+       if printOffset {
+               fmt.Fprintf(f, "#%d", s.v.Start.Offset)
+       }
+       // start is written, do we need end?
+       if s.IsPoint() {
+               return
+       }
+       // we don't print the line if it did not change
+       printLine = fullForm || (printLine && s.v.End.Line > s.v.Start.Line)
+       fmt.Fprint(f, "-")
+       if printLine {
+               fmt.Fprintf(f, "%d", s.v.End.Line)
+       }
+       if printColumn {
+               if printLine {
+                       fmt.Fprint(f, ":")
+               }
+               fmt.Fprintf(f, "%d", s.v.End.Column)
+       }
+       if printOffset {
+               fmt.Fprintf(f, "#%d", s.v.End.Offset)
+       }
+}
+
+func (s Span) WithPosition(c Converter) (Span, error) {
+       if err := s.update(c, true, false); err != nil {
+               return Span{}, err
+       }
+       return s, nil
+}
+
+func (s Span) WithOffset(c Converter) (Span, error) {
+       if err := s.update(c, false, true); err != nil {
+               return Span{}, err
+       }
+       return s, nil
+}
+
+func (s Span) WithAll(c Converter) (Span, error) {
+       if err := s.update(c, true, true); err != nil {
+               return Span{}, err
+       }
+       return s, nil
+}
+
+func (s *Span) update(c Converter, withPos, withOffset bool) error {
+       if !s.IsValid() {
+               return fmt.Errorf("cannot add information to an invalid span")
+       }
+       if withPos && !s.HasPosition() {
+               if err := s.v.Start.updatePosition(c); err != nil {
+                       return err
+               }
+               if s.v.End.Offset == s.v.Start.Offset {
+                       s.v.End = s.v.Start
+               } else if err := s.v.End.updatePosition(c); err != nil {
+                       return err
+               }
+       }
+       if withOffset && (!s.HasOffset() || (s.v.End.hasPosition() && !s.v.End.hasOffset())) {
+               if err := s.v.Start.updateOffset(c); err != nil {
+                       return err
+               }
+               if s.v.End.Line == s.v.Start.Line && s.v.End.Column == s.v.Start.Column {
+                       s.v.End.Offset = s.v.Start.Offset
+               } else if err := s.v.End.updateOffset(c); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func (p *point) updatePosition(c Converter) error {
+       line, col, err := c.ToPosition(p.Offset)
+       if err != nil {
+               return err
+       }
+       p.Line = line
+       p.Column = col
+       return nil
+}
+
+func (p *point) updateOffset(c Converter) error {
+       offset, err := c.ToOffset(p.Line, p.Column)
+       if err != nil {
+               return err
+       }
+       p.Offset = offset
+       return nil
+}