.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools / gopls@v0.6.9 / test / debug / debug_test.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools/gopls@v0.6.9/test/debug/debug_test.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools/gopls@v0.6.9/test/debug/debug_test.go
new file mode 100644 (file)
index 0000000..4d680ee
--- /dev/null
@@ -0,0 +1,181 @@
+// 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 debug_test
+
+// Provide 'static type checking' of the templates. This guards against changes is various
+// gopls datastructures causing template execution to fail. The checking is done by
+// the github.com/jba/templatecheck pacakge. Before that is run, the test checks that
+// its list of templates and their arguments corresponds to the arguments in
+// calls to render(). The test assumes that all uses of templates are done through render().
+
+import (
+       "go/ast"
+       "html/template"
+       "log"
+       "runtime"
+       "sort"
+       "strings"
+       "testing"
+
+       "github.com/jba/templatecheck"
+       "golang.org/x/tools/go/packages"
+       "golang.org/x/tools/internal/lsp/cache"
+       "golang.org/x/tools/internal/lsp/debug"
+       "golang.org/x/tools/internal/lsp/source"
+       "golang.org/x/tools/internal/span"
+)
+
+type tdata struct {
+       tmpl *template.Template
+       data interface{} // a value of the needed type
+}
+
+var templates = map[string]tdata{
+       "MainTmpl":    {debug.MainTmpl, &debug.Instance{}},
+       "DebugTmpl":   {debug.DebugTmpl, nil},
+       "RPCTmpl":     {debug.RPCTmpl, &debug.Rpcs{}},
+       "TraceTmpl":   {debug.TraceTmpl, debug.TraceResults{}},
+       "CacheTmpl":   {debug.CacheTmpl, &cache.Cache{}},
+       "SessionTmpl": {debug.SessionTmpl, &cache.Session{}},
+       "ViewTmpl":    {debug.ViewTmpl, &cache.View{}},
+       "ClientTmpl":  {debug.ClientTmpl, &debug.Client{}},
+       "ServerTmpl":  {debug.ServerTmpl, &debug.Server{}},
+       //"FileTmpl":    {FileTmpl, source.Overlay{}}, // need to construct a source.Overlay in init
+       "InfoTmpl":   {debug.InfoTmpl, "something"},
+       "MemoryTmpl": {debug.MemoryTmpl, runtime.MemStats{}},
+}
+
+// construct a source.Overlay for fileTmpl
+type fakeOverlay struct{}
+
+func (fakeOverlay) Version() int32 {
+       return 0
+}
+func (fakeOverlay) Session() string {
+       return ""
+}
+func (fakeOverlay) VersionedFileIdentity() source.VersionedFileIdentity {
+       return source.VersionedFileIdentity{}
+}
+func (fakeOverlay) FileIdentity() source.FileIdentity {
+       return source.FileIdentity{}
+}
+func (fakeOverlay) Kind() source.FileKind {
+       return 0
+}
+func (fakeOverlay) Read() ([]byte, error) {
+       return nil, nil
+}
+func (fakeOverlay) Saved() bool {
+       return true
+}
+func (fakeOverlay) URI() span.URI {
+       return ""
+}
+
+var _ source.Overlay = fakeOverlay{}
+
+func init() {
+       log.SetFlags(log.Lshortfile)
+       var v fakeOverlay
+       templates["FileTmpl"] = tdata{debug.FileTmpl, v}
+}
+
+func TestTemplates(t *testing.T) {
+       if runtime.GOOS == "android" {
+               t.Skip("this test is not supported for Android")
+       }
+       cfg := &packages.Config{
+               Mode: packages.NeedTypesInfo | packages.LoadAllSyntax, // figure out what's necessary PJW
+       }
+       pkgs, err := packages.Load(cfg, "golang.org/x/tools/internal/lsp/debug")
+       if err != nil {
+               t.Fatal(err)
+       }
+       if len(pkgs) != 1 {
+               t.Fatalf("expected a single package, but got %d", len(pkgs))
+       }
+       p := pkgs[0]
+       if len(p.Errors) != 0 {
+               t.Fatalf("compiler error, e.g. %v", p.Errors[0])
+       }
+       // find the calls to render in serve.go
+       tree := treeOf(p, "serve.go")
+       if tree == nil {
+               t.Fatalf("found no syntax tree for %s", "serve.go")
+       }
+       renders := callsOf(p, tree, "render")
+       if len(renders) == 0 {
+               t.Fatalf("found no calls to render")
+       }
+       var found = make(map[string]bool)
+       for _, r := range renders {
+               if len(r.Args) != 2 {
+                       // template, func
+                       t.Fatalf("got %d args, expected 2", len(r.Args))
+               }
+               t0, ok := p.TypesInfo.Types[r.Args[0]]
+               if !ok || !t0.IsValue() || t0.Type.String() != "*html/template.Template" {
+                       t.Fatalf("no type info for template")
+               }
+               if id, ok := r.Args[0].(*ast.Ident); !ok {
+                       t.Errorf("expected *ast.Ident, got %T", r.Args[0])
+               } else {
+                       found[id.Name] = true
+               }
+       }
+       // make sure found and templates have the same templates
+       for k := range found {
+               if _, ok := templates[k]; !ok {
+                       t.Errorf("code has template %s, but test does not", k)
+               }
+       }
+       for k := range templates {
+               if _, ok := found[k]; !ok {
+                       t.Errorf("test has template %s, code does not", k)
+               }
+       }
+       // now check all the known templates, in alphabetic order, for determinacy
+       keys := []string{}
+       for k := range templates {
+               keys = append(keys, k)
+       }
+       sort.Strings(keys)
+       for _, k := range keys {
+               v := templates[k]
+               // the FuncMap is an annoyance; should not be necessary
+               if err := templatecheck.CheckHTML(v.tmpl, v.data); err != nil {
+                       t.Errorf("%s: %v", k, err)
+               }
+       }
+}
+
+func callsOf(p *packages.Package, tree *ast.File, name string) []*ast.CallExpr {
+       var ans []*ast.CallExpr
+       f := func(n ast.Node) bool {
+               x, ok := n.(*ast.CallExpr)
+               if !ok {
+                       return true
+               }
+               if y, ok := x.Fun.(*ast.Ident); ok {
+                       if y.Name == name {
+                               ans = append(ans, x)
+                       }
+               }
+               return true
+       }
+       ast.Inspect(tree, f)
+       return ans
+}
+func treeOf(p *packages.Package, fname string) *ast.File {
+       for _, tree := range p.Syntax {
+               loc := tree.Package
+               pos := p.Fset.PositionFor(loc, false)
+               if strings.HasSuffix(pos.Filename, fname) {
+                       return tree
+               }
+       }
+       return nil
+}