.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / internal / lsp / diff / unified.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/diff/unified.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/diff/unified.go
new file mode 100644 (file)
index 0000000..b2e630e
--- /dev/null
@@ -0,0 +1,210 @@
+// 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 diff
+
+import (
+       "fmt"
+       "strings"
+)
+
+// Unified represents a set of edits as a unified diff.
+type Unified struct {
+       // From is the name of the original file.
+       From string
+       // To is the name of the modified file.
+       To string
+       // Hunks is the set of edit hunks needed to transform the file content.
+       Hunks []*Hunk
+}
+
+// Hunk represents a contiguous set of line edits to apply.
+type Hunk struct {
+       // The line in the original source where the hunk starts.
+       FromLine int
+       // The line in the original source where the hunk finishes.
+       ToLine int
+       // The set of line based edits to apply.
+       Lines []Line
+}
+
+// Line represents a single line operation to apply as part of a Hunk.
+type Line struct {
+       // Kind is the type of line this represents, deletion, insertion or copy.
+       Kind OpKind
+       // Content is the content of this line.
+       // For deletion it is the line being removed, for all others it is the line
+       // to put in the output.
+       Content string
+}
+
+// OpKind is used to denote the type of operation a line represents.
+type OpKind int
+
+const (
+       // Delete is the operation kind for a line that is present in the input
+       // but not in the output.
+       Delete OpKind = iota
+       // Insert is the operation kind for a line that is new in the output.
+       Insert
+       // Equal is the operation kind for a line that is the same in the input and
+       // output, often used to provide context around edited lines.
+       Equal
+)
+
+// String returns a human readable representation of an OpKind. It is not
+// intended for machine processing.
+func (k OpKind) String() string {
+       switch k {
+       case Delete:
+               return "delete"
+       case Insert:
+               return "insert"
+       case Equal:
+               return "equal"
+       default:
+               panic("unknown operation kind")
+       }
+}
+
+const (
+       edge = 3
+       gap  = edge * 2
+)
+
+// ToUnified takes a file contents and a sequence of edits, and calculates
+// a unified diff that represents those edits.
+func ToUnified(from, to string, content string, edits []TextEdit) Unified {
+       u := Unified{
+               From: from,
+               To:   to,
+       }
+       if len(edits) == 0 {
+               return u
+       }
+       c, edits, partial := prepareEdits(content, edits)
+       if partial {
+               edits = lineEdits(content, c, edits)
+       }
+       lines := splitLines(content)
+       var h *Hunk
+       last := 0
+       toLine := 0
+       for _, edit := range edits {
+               start := edit.Span.Start().Line() - 1
+               end := edit.Span.End().Line() - 1
+               switch {
+               case h != nil && start == last:
+                       //direct extension
+               case h != nil && start <= last+gap:
+                       //within range of previous lines, add the joiners
+                       addEqualLines(h, lines, last, start)
+               default:
+                       //need to start a new hunk
+                       if h != nil {
+                               // add the edge to the previous hunk
+                               addEqualLines(h, lines, last, last+edge)
+                               u.Hunks = append(u.Hunks, h)
+                       }
+                       toLine += start - last
+                       h = &Hunk{
+                               FromLine: start + 1,
+                               ToLine:   toLine + 1,
+                       }
+                       // add the edge to the new hunk
+                       delta := addEqualLines(h, lines, start-edge, start)
+                       h.FromLine -= delta
+                       h.ToLine -= delta
+               }
+               last = start
+               for i := start; i < end; i++ {
+                       h.Lines = append(h.Lines, Line{Kind: Delete, Content: lines[i]})
+                       last++
+               }
+               if edit.NewText != "" {
+                       for _, line := range splitLines(edit.NewText) {
+                               h.Lines = append(h.Lines, Line{Kind: Insert, Content: line})
+                               toLine++
+                       }
+               }
+       }
+       if h != nil {
+               // add the edge to the final hunk
+               addEqualLines(h, lines, last, last+edge)
+               u.Hunks = append(u.Hunks, h)
+       }
+       return u
+}
+
+func splitLines(text string) []string {
+       lines := strings.SplitAfter(text, "\n")
+       if lines[len(lines)-1] == "" {
+               lines = lines[:len(lines)-1]
+       }
+       return lines
+}
+
+func addEqualLines(h *Hunk, lines []string, start, end int) int {
+       delta := 0
+       for i := start; i < end; i++ {
+               if i < 0 {
+                       continue
+               }
+               if i >= len(lines) {
+                       return delta
+               }
+               h.Lines = append(h.Lines, Line{Kind: Equal, Content: lines[i]})
+               delta++
+       }
+       return delta
+}
+
+// Format converts a unified diff to the standard textual form for that diff.
+// The output of this function can be passed to tools like patch.
+func (u Unified) Format(f fmt.State, r rune) {
+       if len(u.Hunks) == 0 {
+               return
+       }
+       fmt.Fprintf(f, "--- %s\n", u.From)
+       fmt.Fprintf(f, "+++ %s\n", u.To)
+       for _, hunk := range u.Hunks {
+               fromCount, toCount := 0, 0
+               for _, l := range hunk.Lines {
+                       switch l.Kind {
+                       case Delete:
+                               fromCount++
+                       case Insert:
+                               toCount++
+                       default:
+                               fromCount++
+                               toCount++
+                       }
+               }
+               fmt.Fprint(f, "@@")
+               if fromCount > 1 {
+                       fmt.Fprintf(f, " -%d,%d", hunk.FromLine, fromCount)
+               } else {
+                       fmt.Fprintf(f, " -%d", hunk.FromLine)
+               }
+               if toCount > 1 {
+                       fmt.Fprintf(f, " +%d,%d", hunk.ToLine, toCount)
+               } else {
+                       fmt.Fprintf(f, " +%d", hunk.ToLine)
+               }
+               fmt.Fprint(f, " @@\n")
+               for _, l := range hunk.Lines {
+                       switch l.Kind {
+                       case Delete:
+                               fmt.Fprintf(f, "-%s", l.Content)
+                       case Insert:
+                               fmt.Fprintf(f, "+%s", l.Content)
+                       default:
+                               fmt.Fprintf(f, " %s", l.Content)
+                       }
+                       if !strings.HasSuffix(l.Content, "\n") {
+                               fmt.Fprintf(f, "\n\\ No newline at end of file\n")
+                       }
+               }
+       }
+}