.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / internal / lsp / fake / edit.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/fake/edit.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/fake/edit.go
new file mode 100644 (file)
index 0000000..e5be4f6
--- /dev/null
@@ -0,0 +1,153 @@
+// Copyright 2020 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 fake
+
+import (
+       "fmt"
+       "sort"
+       "strings"
+
+       "golang.org/x/tools/internal/lsp/protocol"
+)
+
+// Pos represents a position in a text buffer. Both Line and Column are
+// 0-indexed.
+type Pos struct {
+       Line, Column int
+}
+
+// Range corresponds to protocol.Range, but uses the editor friend Pos
+// instead of UTF-16 oriented protocol.Position
+type Range struct {
+       Start Pos
+       End   Pos
+}
+
+func (p Pos) ToProtocolPosition() protocol.Position {
+       return protocol.Position{
+               Line:      float64(p.Line),
+               Character: float64(p.Column),
+       }
+}
+
+func fromProtocolPosition(pos protocol.Position) Pos {
+       return Pos{
+               Line:   int(pos.Line),
+               Column: int(pos.Character),
+       }
+}
+
+// Edit represents a single (contiguous) buffer edit.
+type Edit struct {
+       Start, End Pos
+       Text       string
+}
+
+// Location is the editor friendly equivalent of protocol.Location
+type Location struct {
+       Path  string
+       Range Range
+}
+
+// SymbolInformation is an editor friendly version of
+// protocol.SymbolInformation, with location information transformed to byte
+// offsets. Field names correspond to the protocol type.
+type SymbolInformation struct {
+       Name     string
+       Kind     protocol.SymbolKind
+       Location Location
+}
+
+// NewEdit creates an edit replacing all content between
+// (startLine, startColumn) and (endLine, endColumn) with text.
+func NewEdit(startLine, startColumn, endLine, endColumn int, text string) Edit {
+       return Edit{
+               Start: Pos{Line: startLine, Column: startColumn},
+               End:   Pos{Line: endLine, Column: endColumn},
+               Text:  text,
+       }
+}
+
+func (e Edit) toProtocolChangeEvent() protocol.TextDocumentContentChangeEvent {
+       return protocol.TextDocumentContentChangeEvent{
+               Range: &protocol.Range{
+                       Start: e.Start.ToProtocolPosition(),
+                       End:   e.End.ToProtocolPosition(),
+               },
+               Text: e.Text,
+       }
+}
+
+func fromProtocolTextEdit(textEdit protocol.TextEdit) Edit {
+       return Edit{
+               Start: fromProtocolPosition(textEdit.Range.Start),
+               End:   fromProtocolPosition(textEdit.Range.End),
+               Text:  textEdit.NewText,
+       }
+}
+
+// inText reports whether p is a valid position in the text buffer.
+func inText(p Pos, content []string) bool {
+       if p.Line < 0 || p.Line >= len(content) {
+               return false
+       }
+       // Note the strict right bound: the column indexes character _separators_,
+       // not characters.
+       if p.Column < 0 || p.Column > len([]rune(content[p.Line])) {
+               return false
+       }
+       return true
+}
+
+// editContent implements a simplistic, inefficient algorithm for applying text
+// edits to our buffer representation. It returns an error if the edit is
+// invalid for the current content.
+func editContent(content []string, edits []Edit) ([]string, error) {
+       newEdits := make([]Edit, len(edits))
+       copy(newEdits, edits)
+       sort.Slice(newEdits, func(i, j int) bool {
+               if newEdits[i].Start.Line < newEdits[j].Start.Line {
+                       return true
+               }
+               if newEdits[i].Start.Line > newEdits[j].Start.Line {
+                       return false
+               }
+               return newEdits[i].Start.Column < newEdits[j].Start.Column
+       })
+
+       // Validate edits.
+       for _, edit := range newEdits {
+               if edit.End.Line < edit.Start.Line || (edit.End.Line == edit.Start.Line && edit.End.Column < edit.Start.Column) {
+                       return nil, fmt.Errorf("invalid edit: end %v before start %v", edit.End, edit.Start)
+               }
+               if !inText(edit.Start, content) {
+                       return nil, fmt.Errorf("start position %v is out of bounds", edit.Start)
+               }
+               if !inText(edit.End, content) {
+                       return nil, fmt.Errorf("end position %v is out of bounds", edit.End)
+               }
+       }
+
+       var (
+               b            strings.Builder
+               line, column int
+       )
+       advance := func(toLine, toColumn int) {
+               for ; line < toLine; line++ {
+                       b.WriteString(string([]rune(content[line])[column:]) + "\n")
+                       column = 0
+               }
+               b.WriteString(string([]rune(content[line])[column:toColumn]))
+               column = toColumn
+       }
+       for _, edit := range newEdits {
+               advance(edit.Start.Line, edit.Start.Column)
+               b.WriteString(edit.Text)
+               line = edit.End.Line
+               column = edit.End.Column
+       }
+       advance(len(content)-1, len([]rune(content[len(content)-1])))
+       return strings.Split(b.String(), "\n"), nil
+}