From 9e9f7f69ece9394ec1578405596b20912f97b823 Mon Sep 17 00:00:00 2001 From: Mostyn Bramley-Moore Date: Tue, 31 Jul 2018 17:27:32 +0000 Subject: [PATCH] godoc: skip build tag annotations when displaying examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After moving the filepath.Walk example to a standalone example file in CL 122237 (so it could use a standalone function), godoc includes the build tag annotation ("// +build !windows,!plan9" in this case) in the runnable example. The example runs correctly, but the annotation might be confusing for new users. Change the behavior so that godoc skips these annotations when displaying examples. To avoid false positives in older versions of "go vet", which are still used on the build dashboard, we avoid using a multiline string in the test. Fixes golang/go#26490. Change-Id: I1da4b3b7e1e5a85a76773e25d9355b3f92479c19 GitHub-Last-Rev: bc5ed29bd368e5bcf11fed7a0c7f14b872fef065 GitHub-Pull-Request: golang/tools#42 Reviewed-on: https://go-review.googlesource.com/126256 Run-TryBot: Daniel Martí TryBot-Result: Gobot Gobot Reviewed-by: Daniel Martí Reviewed-by: Andrew Bonventre --- godoc/godoc.go | 18 +++++++++++++++++ godoc/godoc_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/godoc/godoc.go b/godoc/godoc.go index f191a9d989..0acb49bf75 100644 --- a/godoc/godoc.go +++ b/godoc/godoc.go @@ -666,6 +666,7 @@ func (p *Presentation) example_htmlFunc(info *PageInfo, funcName string) string play := "" if eg.Play != nil && p.ShowPlayground { var buf bytes.Buffer + eg.Play.Comments = filterOutBuildAnnotations(eg.Play.Comments) if err := format.Node(&buf, info.FSet, eg.Play); err != nil { log.Print(err) } else { @@ -694,6 +695,23 @@ func (p *Presentation) example_htmlFunc(info *PageInfo, funcName string) string return buf.String() } +func filterOutBuildAnnotations(cg []*ast.CommentGroup) []*ast.CommentGroup { + if len(cg) == 0 { + return cg + } + + for i := range cg { + if !strings.HasPrefix(cg[i].Text(), "+build ") { + // Found the first non-build tag, return from here until the end + // of the slice. + return cg[i:] + } + } + + // There weren't any non-build tags, return an empty slice. + return []*ast.CommentGroup{} +} + // example_nameFunc takes an example function name and returns its display // name. For example, "Foo_Bar_quux" becomes "Foo.Bar (Quux)". func (p *Presentation) example_nameFunc(s string) string { diff --git a/godoc/godoc_test.go b/godoc/godoc_test.go index c1d631c157..33dbe3f619 100644 --- a/godoc/godoc_test.go +++ b/godoc/godoc_test.go @@ -321,3 +321,50 @@ func TestSrcToPkgLinkFunc(t *testing.T) { } } } + +func TestFilterOutBuildAnnotations(t *testing.T) { + // TODO: simplify this by using a multiline string once we stop + // using go vet from 1.10 on the build dashboard. + // https://golang.org/issue/26627 + src := []byte("// +build !foo\n" + + "// +build !anothertag\n" + + "\n" + + "// non-tag comment\n" + + "\n" + + "package foo\n" + + "\n" + + "func bar() int {\n" + + " return 42\n" + + "}\n") + + fset := token.NewFileSet() + af, err := parser.ParseFile(fset, "foo.go", src, parser.ParseComments) + if err != nil { + t.Fatal(err) + } + + var found bool + for _, cg := range af.Comments { + if strings.HasPrefix(cg.Text(), "+build ") { + found = true + break + } + } + if !found { + t.Errorf("TestFilterOutBuildAnnotations is broken: missing build tag in test input") + } + + found = false + for _, cg := range filterOutBuildAnnotations(af.Comments) { + if strings.HasPrefix(cg.Text(), "+build ") { + t.Errorf("filterOutBuildAnnotations failed to filter build tag") + } + + if strings.Contains(cg.Text(), "non-tag comment") { + found = true + } + } + if !found { + t.Errorf("filterOutBuildAnnotations should not remove non-build tag comment") + } +}