Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / cfg / cfg_test.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/go/cfg/cfg_test.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/go/cfg/cfg_test.go
new file mode 100644 (file)
index 0000000..f22bda3
--- /dev/null
@@ -0,0 +1,177 @@
+// Copyright 2016 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 cfg
+
+import (
+       "bytes"
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "go/token"
+       "testing"
+)
+
+const src = `package main
+
+import "log"
+
+func f1() {
+       live()
+       return
+       dead()
+}
+
+func f2() {
+       for {
+               live()
+       }
+       dead()
+}
+
+func f3() {
+       if true { // even known values are ignored
+               return
+       }
+       for true { // even known values are ignored
+               live()
+       }
+       for {
+               live()
+       }
+       dead()
+}
+
+func f4(x int) {
+       switch x {
+       case 1:
+               live()
+               fallthrough
+       case 2:
+               live()
+               log.Fatal()
+       default:
+               panic("oops")
+       }
+       dead()
+}
+
+func f4(ch chan int) {
+       select {
+       case <-ch:
+               live()
+               return
+       default:
+               live()
+               panic("oops")
+       }
+       dead()
+}
+
+func f5(unknown bool) {
+       for {
+               if unknown {
+                       break
+               }
+               continue
+               dead()
+       }
+       live()
+}
+
+func f6(unknown bool) {
+outer:
+       for {
+               for {
+                       break outer
+                       dead()
+               }
+               dead()
+       }
+       live()
+}
+
+func f7() {
+       for {
+               break nosuchlabel
+               dead()
+       }
+       dead()
+}
+
+func f8() {
+       select{}
+       dead()
+}
+
+func f9(ch chan int) {
+       select {
+       case <-ch:
+               return
+       }
+       dead()
+}
+
+func f10(ch chan int) {
+       select {
+       case <-ch:
+               return
+               dead()
+       default:
+       }
+       live()
+}
+
+func f11() {
+       goto; // mustn't crash
+       dead()
+}
+
+`
+
+func TestDeadCode(t *testing.T) {
+       // We'll use dead code detection to verify the CFG.
+
+       fset := token.NewFileSet()
+       f, err := parser.ParseFile(fset, "dummy.go", src, parser.Mode(0))
+       if err != nil {
+               t.Fatal(err)
+       }
+       for _, decl := range f.Decls {
+               if decl, ok := decl.(*ast.FuncDecl); ok {
+                       g := New(decl.Body, mayReturn)
+
+                       // Print statements in unreachable blocks
+                       // (in order determined by builder).
+                       var buf bytes.Buffer
+                       for _, b := range g.Blocks {
+                               if !b.Live {
+                                       for _, n := range b.Nodes {
+                                               fmt.Fprintf(&buf, "\t%s\n", formatNode(fset, n))
+                                       }
+                               }
+                       }
+
+                       // Check that the result contains "dead" at least once but not "live".
+                       if !bytes.Contains(buf.Bytes(), []byte("dead")) ||
+                               bytes.Contains(buf.Bytes(), []byte("live")) {
+                               t.Errorf("unexpected dead statements in function %s:\n%s",
+                                       decl.Name.Name,
+                                       &buf)
+                               t.Logf("control flow graph:\n%s", g.Format(fset))
+                       }
+               }
+       }
+}
+
+// A trivial mayReturn predicate that looks only at syntax, not types.
+func mayReturn(call *ast.CallExpr) bool {
+       switch fun := call.Fun.(type) {
+       case *ast.Ident:
+               return fun.Name != "panic"
+       case *ast.SelectorExpr:
+               return fun.Sel.Name != "Fatal"
+       }
+       return true
+}