.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / internal / stack / process.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/internal/stack/process.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.1-0.20210319172145-bda8f5cee399/internal/stack/process.go
new file mode 100644 (file)
index 0000000..ac19366
--- /dev/null
@@ -0,0 +1,112 @@
+// 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 stack
+
+import (
+       "bytes"
+       "fmt"
+       "io"
+       "runtime"
+       "sort"
+)
+
+// Capture get the current stack traces from the runtime.
+func Capture() Dump {
+       buf := make([]byte, 2<<20)
+       buf = buf[:runtime.Stack(buf, true)]
+       scanner := NewScanner(bytes.NewReader(buf))
+       dump, _ := Parse(scanner)
+       return dump
+}
+
+// Summarize a dump for easier consumption.
+// This collates goroutines with equivalent stacks.
+func Summarize(dump Dump) Summary {
+       s := Summary{
+               Total: len(dump),
+       }
+       for _, gr := range dump {
+               s.addGoroutine(gr)
+       }
+       return s
+}
+
+// Process and input stream to an output stream, summarizing any stacks that
+// are detected in place.
+func Process(out io.Writer, in io.Reader) error {
+       scanner := NewScanner(in)
+       for {
+               dump, err := Parse(scanner)
+               summary := Summarize(dump)
+               switch {
+               case len(dump) > 0:
+                       fmt.Fprintf(out, "%+v\n\n", summary)
+               case err != nil:
+                       return err
+               case scanner.Done():
+                       return scanner.Err()
+               default:
+                       // must have been a line that is not part of a dump
+                       fmt.Fprintln(out, scanner.Next())
+               }
+       }
+}
+
+// Diff calculates the delta between two dumps.
+func Diff(before, after Dump) Delta {
+       result := Delta{}
+       processed := make(map[int]bool)
+       for _, gr := range before {
+               processed[gr.ID] = false
+       }
+       for _, gr := range after {
+               if _, found := processed[gr.ID]; found {
+                       result.Shared = append(result.Shared, gr)
+               } else {
+                       result.After = append(result.After, gr)
+               }
+               processed[gr.ID] = true
+       }
+       for _, gr := range before {
+               if done := processed[gr.ID]; !done {
+                       result.Before = append(result.Before, gr)
+               }
+       }
+       return result
+}
+
+// TODO: do we want to allow contraction of stacks before comparison?
+func (s *Summary) addGoroutine(gr Goroutine) {
+       index := sort.Search(len(s.Calls), func(i int) bool {
+               return !s.Calls[i].Stack.less(gr.Stack)
+       })
+       if index >= len(s.Calls) || !s.Calls[index].Stack.equal(gr.Stack) {
+               // insert new stack, first increase the length
+               s.Calls = append(s.Calls, Call{})
+               // move the top part upward to make space
+               copy(s.Calls[index+1:], s.Calls[index:])
+               // insert the new call
+               s.Calls[index] = Call{
+                       Stack: gr.Stack,
+               }
+       }
+       // merge the goroutine into the matched call
+       s.Calls[index].merge(gr)
+}
+
+//TODO: do we want other grouping strategies?
+func (c *Call) merge(gr Goroutine) {
+       for i := range c.Groups {
+               canditate := &c.Groups[i]
+               if canditate.State == gr.State {
+                       canditate.Goroutines = append(canditate.Goroutines, gr)
+                       return
+               }
+       }
+       c.Groups = append(c.Groups, Group{
+               State:      gr.State,
+               Goroutines: []Goroutine{gr},
+       })
+}