summaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/constraintutil/BUILD18
-rw-r--r--tools/constraintutil/constraintutil.go169
-rw-r--r--tools/constraintutil/constraintutil_test.go138
-rw-r--r--tools/go_generics/go_merge/BUILD2
-rw-r--r--tools/go_generics/go_merge/main.go13
-rw-r--r--tools/go_marshal/gomarshal/BUILD2
-rw-r--r--tools/go_marshal/gomarshal/generator.go33
-rw-r--r--tools/go_stateify/BUILD2
-rw-r--r--tools/go_stateify/main.go11
-rw-r--r--tools/nogo/BUILD8
-rw-r--r--tools/nogo/config.go18
-rw-r--r--tools/nogo/config_test.go301
-rw-r--r--tools/nogo/findings.go2
-rw-r--r--tools/tags/BUILD11
-rw-r--r--tools/tags/tags.go89
15 files changed, 683 insertions, 134 deletions
diff --git a/tools/constraintutil/BUILD b/tools/constraintutil/BUILD
new file mode 100644
index 000000000..004b708c4
--- /dev/null
+++ b/tools/constraintutil/BUILD
@@ -0,0 +1,18 @@
+load("//tools:defs.bzl", "go_library", "go_test")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "constraintutil",
+ srcs = ["constraintutil.go"],
+ marshal = False,
+ stateify = False,
+ visibility = ["//tools:__subpackages__"],
+)
+
+go_test(
+ name = "constraintutil_test",
+ size = "small",
+ srcs = ["constraintutil_test.go"],
+ library = ":constraintutil",
+)
diff --git a/tools/constraintutil/constraintutil.go b/tools/constraintutil/constraintutil.go
new file mode 100644
index 000000000..fb3fbe5c2
--- /dev/null
+++ b/tools/constraintutil/constraintutil.go
@@ -0,0 +1,169 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package constraintutil provides utilities for working with Go build
+// constraints.
+package constraintutil
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "go/build/constraint"
+ "io"
+ "os"
+ "strings"
+)
+
+// FromReader extracts the build constraint from the Go source or assembly file
+// whose contents are read by r.
+func FromReader(r io.Reader) (constraint.Expr, error) {
+ // See go/build.parseFileHeader() for the "official" logic that this is
+ // derived from.
+ const (
+ slashStar = "/*"
+ starSlash = "*/"
+ gobuildPrefix = "//go:build"
+ )
+ s := bufio.NewScanner(r)
+ var (
+ inSlashStar = false // between /* and */
+ haveGobuild = false
+ e constraint.Expr
+ )
+Lines:
+ for s.Scan() {
+ line := bytes.TrimSpace(s.Bytes())
+ if !inSlashStar && constraint.IsGoBuild(string(line)) {
+ if haveGobuild {
+ return nil, fmt.Errorf("multiple go:build directives")
+ }
+ haveGobuild = true
+ var err error
+ e, err = constraint.Parse(string(line))
+ if err != nil {
+ return nil, err
+ }
+ }
+ ThisLine:
+ for len(line) > 0 {
+ if inSlashStar {
+ if i := bytes.Index(line, []byte(starSlash)); i >= 0 {
+ inSlashStar = false
+ line = bytes.TrimSpace(line[i+len(starSlash):])
+ continue ThisLine
+ }
+ continue Lines
+ }
+ if bytes.HasPrefix(line, []byte("//")) {
+ continue Lines
+ }
+ // Note that if /* appears in the line, but not at the beginning,
+ // then the line is still non-empty, so skipping this and
+ // terminating below is correct.
+ if bytes.HasPrefix(line, []byte(slashStar)) {
+ inSlashStar = true
+ line = bytes.TrimSpace(line[len(slashStar):])
+ continue ThisLine
+ }
+ // A non-empty non-comment line terminates scanning for go:build.
+ break Lines
+ }
+ }
+ return e, s.Err()
+}
+
+// FromString extracts the build constraint from the Go source or assembly file
+// containing the given data. If no build constraint applies to the file, it
+// returns nil.
+func FromString(str string) (constraint.Expr, error) {
+ return FromReader(strings.NewReader(str))
+}
+
+// FromFile extracts the build constraint from the Go source or assembly file
+// at the given path. If no build constraint applies to the file, it returns
+// nil.
+func FromFile(path string) (constraint.Expr, error) {
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+ return FromReader(f)
+}
+
+// Combine returns a constraint.Expr that evaluates to true iff all expressions
+// in es evaluate to true. If es is empty, Combine returns nil.
+//
+// Preconditions: All constraint.Exprs in es are non-nil.
+func Combine(es []constraint.Expr) constraint.Expr {
+ switch len(es) {
+ case 0:
+ return nil
+ case 1:
+ return es[0]
+ default:
+ a := &constraint.AndExpr{es[0], es[1]}
+ for i := 2; i < len(es); i++ {
+ a = &constraint.AndExpr{a, es[i]}
+ }
+ return a
+ }
+}
+
+// CombineFromFiles returns a build constraint expression that evaluates to
+// true iff the build constraints from all of the given Go source or assembly
+// files evaluate to true. If no build constraints apply to any of the given
+// files, it returns nil.
+func CombineFromFiles(paths []string) (constraint.Expr, error) {
+ var es []constraint.Expr
+ for _, path := range paths {
+ e, err := FromFile(path)
+ if err != nil {
+ return nil, fmt.Errorf("failed to read build constraints from %q: %v", path, err)
+ }
+ if e != nil {
+ es = append(es, e)
+ }
+ }
+ return Combine(es), nil
+}
+
+// Lines returns a string containing build constraint directives for the given
+// constraint.Expr, including two trailing newlines, as appropriate for a Go
+// source or assembly file. At least a go:build directive will be emitted; if
+// the constraint is expressible using +build directives as well, then +build
+// directives will also be emitted.
+//
+// If e is nil, Lines returns the empty string.
+func Lines(e constraint.Expr) string {
+ if e == nil {
+ return ""
+ }
+
+ var b strings.Builder
+ b.WriteString("//go:build ")
+ b.WriteString(e.String())
+ b.WriteByte('\n')
+
+ if pblines, err := constraint.PlusBuildLines(e); err == nil {
+ for _, line := range pblines {
+ b.WriteString(line)
+ b.WriteByte('\n')
+ }
+ }
+
+ b.WriteByte('\n')
+ return b.String()
+}
diff --git a/tools/constraintutil/constraintutil_test.go b/tools/constraintutil/constraintutil_test.go
new file mode 100644
index 000000000..eeabd8dcf
--- /dev/null
+++ b/tools/constraintutil/constraintutil_test.go
@@ -0,0 +1,138 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package constraintutil
+
+import (
+ "go/build/constraint"
+ "testing"
+)
+
+func TestFileParsing(t *testing.T) {
+ for _, test := range []struct {
+ name string
+ data string
+ expr string
+ }{
+ {
+ name: "Empty",
+ },
+ {
+ name: "NoConstraint",
+ data: "// copyright header\n\npackage main",
+ },
+ {
+ name: "ConstraintOnFirstLine",
+ data: "//go:build amd64\n#include \"textflag.h\"",
+ expr: "amd64",
+ },
+ {
+ name: "ConstraintAfterSlashSlashComment",
+ data: "// copyright header\n\n//go:build linux\n\npackage newlib",
+ expr: "linux",
+ },
+ {
+ name: "ConstraintAfterSlashStarComment",
+ data: "/*\ncopyright header\n*/\n\n//go:build !race\n\npackage oldlib",
+ expr: "!race",
+ },
+ {
+ name: "ConstraintInSlashSlashComment",
+ data: "// blah blah //go:build windows",
+ },
+ {
+ name: "ConstraintInSlashStarComment",
+ data: "/*\n//go:build windows\n*/",
+ },
+ {
+ name: "ConstraintAfterPackageClause",
+ data: "package oops\n//go:build race",
+ },
+ {
+ name: "ConstraintAfterCppInclude",
+ data: "#include \"textflag.h\"\n//go:build arm64",
+ },
+ } {
+ t.Run(test.name, func(t *testing.T) {
+ e, err := FromString(test.data)
+ if err != nil {
+ t.Fatalf("FromString(%q) failed: %v", test.data, err)
+ }
+ if e == nil {
+ if len(test.expr) != 0 {
+ t.Errorf("FromString(%q): got no constraint, wanted %q", test.data, test.expr)
+ }
+ } else {
+ got := e.String()
+ if len(test.expr) == 0 {
+ t.Errorf("FromString(%q): got %q, wanted no constraint", test.data, got)
+ } else if got != test.expr {
+ t.Errorf("FromString(%q): got %q, wanted %q", test.data, got, test.expr)
+ }
+ }
+ })
+ }
+}
+
+func TestCombine(t *testing.T) {
+ for _, test := range []struct {
+ name string
+ in []string
+ out string
+ }{
+ {
+ name: "0",
+ },
+ {
+ name: "1",
+ in: []string{"amd64 || arm64"},
+ out: "amd64 || arm64",
+ },
+ {
+ name: "2",
+ in: []string{"amd64", "amd64 && linux"},
+ out: "amd64 && amd64 && linux",
+ },
+ {
+ name: "3",
+ in: []string{"amd64", "amd64 || arm64", "amd64 || riscv64"},
+ out: "amd64 && (amd64 || arm64) && (amd64 || riscv64)",
+ },
+ } {
+ t.Run(test.name, func(t *testing.T) {
+ inexprs := make([]constraint.Expr, 0, len(test.in))
+ for _, estr := range test.in {
+ line := "//go:build " + estr
+ e, err := constraint.Parse(line)
+ if err != nil {
+ t.Fatalf("constraint.Parse(%q) failed: %v", line, err)
+ }
+ inexprs = append(inexprs, e)
+ }
+ outexpr := Combine(inexprs)
+ if outexpr == nil {
+ if len(test.out) != 0 {
+ t.Errorf("Combine(%v): got no constraint, wanted %q", test.in, test.out)
+ }
+ } else {
+ got := outexpr.String()
+ if len(test.out) == 0 {
+ t.Errorf("Combine(%v): got %q, wanted no constraint", test.in, got)
+ } else if got != test.out {
+ t.Errorf("Combine(%v): got %q, wanted %q", test.in, got, test.out)
+ }
+ }
+ })
+ }
+}
diff --git a/tools/go_generics/go_merge/BUILD b/tools/go_generics/go_merge/BUILD
index 5e0487e93..211e6b3ed 100644
--- a/tools/go_generics/go_merge/BUILD
+++ b/tools/go_generics/go_merge/BUILD
@@ -7,6 +7,6 @@ go_binary(
srcs = ["main.go"],
visibility = ["//:sandbox"],
deps = [
- "//tools/tags",
+ "//tools/constraintutil",
],
)
diff --git a/tools/go_generics/go_merge/main.go b/tools/go_generics/go_merge/main.go
index 801f2354f..81394ddce 100644
--- a/tools/go_generics/go_merge/main.go
+++ b/tools/go_generics/go_merge/main.go
@@ -25,9 +25,8 @@ import (
"os"
"path/filepath"
"strconv"
- "strings"
- "gvisor.dev/gvisor/tools/tags"
+ "gvisor.dev/gvisor/tools/constraintutil"
)
var (
@@ -131,6 +130,12 @@ func main() {
}
f.Decls = newDecls
+ // Infer build constraints for the output file.
+ bcexpr, err := constraintutil.CombineFromFiles(flag.Args())
+ if err != nil {
+ fatalf("Failed to read build constraints: %v\n", err)
+ }
+
// Write the output file.
var buf bytes.Buffer
if err := format.Node(&buf, fset, f); err != nil {
@@ -141,9 +146,7 @@ func main() {
fatalf("opening output: %v\n", err)
}
defer outf.Close()
- if t := tags.Aggregate(flag.Args()); len(t) > 0 {
- fmt.Fprintf(outf, "%s\n\n", strings.Join(t.Lines(), "\n"))
- }
+ outf.WriteString(constraintutil.Lines(bcexpr))
if _, err := outf.Write(buf.Bytes()); err != nil {
fatalf("write: %v\n", err)
}
diff --git a/tools/go_marshal/gomarshal/BUILD b/tools/go_marshal/gomarshal/BUILD
index c2747d94c..aaa203115 100644
--- a/tools/go_marshal/gomarshal/BUILD
+++ b/tools/go_marshal/gomarshal/BUILD
@@ -18,5 +18,5 @@ go_library(
visibility = [
"//:sandbox",
],
- deps = ["//tools/tags"],
+ deps = ["//tools/constraintutil"],
)
diff --git a/tools/go_marshal/gomarshal/generator.go b/tools/go_marshal/gomarshal/generator.go
index 00961c90d..4c23637c0 100644
--- a/tools/go_marshal/gomarshal/generator.go
+++ b/tools/go_marshal/gomarshal/generator.go
@@ -25,7 +25,7 @@ import (
"sort"
"strings"
- "gvisor.dev/gvisor/tools/tags"
+ "gvisor.dev/gvisor/tools/constraintutil"
)
// List of identifiers we use in generated code that may conflict with a
@@ -123,16 +123,18 @@ func (g *Generator) writeHeader() error {
var b sourceBuffer
b.emit("// Automatically generated marshal implementation. See tools/go_marshal.\n\n")
- // Emit build tags.
- b.emit("// If there are issues with build tag aggregation, see\n")
- b.emit("// tools/go_marshal/gomarshal/generator.go:writeHeader(). The build tags here\n")
- b.emit("// come from the input set of files used to generate this file. This input set\n")
- b.emit("// is filtered based on pre-defined file suffixes related to build tags, see \n")
- b.emit("// tools/defs.bzl:calculate_sets().\n\n")
-
- if t := tags.Aggregate(g.inputs); len(t) > 0 {
- b.emit(strings.Join(t.Lines(), "\n"))
- b.emit("\n\n")
+ bcexpr, err := constraintutil.CombineFromFiles(g.inputs)
+ if err != nil {
+ return err
+ }
+ if bcexpr != nil {
+ // Emit build constraints.
+ b.emit("// If there are issues with build constraint aggregation, see\n")
+ b.emit("// tools/go_marshal/gomarshal/generator.go:writeHeader(). The constraints here\n")
+ b.emit("// come from the input set of files used to generate this file. This input set\n")
+ b.emit("// is filtered based on pre-defined file suffixes related to build constraints,\n")
+ b.emit("// see tools/defs.bzl:calculate_sets().\n\n")
+ b.emit(constraintutil.Lines(bcexpr))
}
// Package header.
@@ -553,11 +555,12 @@ func (g *Generator) writeTests(ts []*testGenerator) error {
b.reset()
b.emit("// Automatically generated marshal tests. See tools/go_marshal.\n\n")
- // Emit build tags.
- if t := tags.Aggregate(g.inputs); len(t) > 0 {
- b.emit(strings.Join(t.Lines(), "\n"))
- b.emit("\n\n")
+ // Emit build constraints.
+ bcexpr, err := constraintutil.CombineFromFiles(g.inputs)
+ if err != nil {
+ return err
}
+ b.emit(constraintutil.Lines(bcexpr))
b.emit("package %s\n\n", g.pkg)
if err := b.write(g.outputTest); err != nil {
diff --git a/tools/go_stateify/BUILD b/tools/go_stateify/BUILD
index 913558b4e..ad66981c7 100644
--- a/tools/go_stateify/BUILD
+++ b/tools/go_stateify/BUILD
@@ -6,7 +6,7 @@ go_binary(
name = "stateify",
srcs = ["main.go"],
visibility = ["//:sandbox"],
- deps = ["//tools/tags"],
+ deps = ["//tools/constraintutil"],
)
bzl_library(
diff --git a/tools/go_stateify/main.go b/tools/go_stateify/main.go
index 93022f504..7216388a0 100644
--- a/tools/go_stateify/main.go
+++ b/tools/go_stateify/main.go
@@ -28,7 +28,7 @@ import (
"strings"
"sync"
- "gvisor.dev/gvisor/tools/tags"
+ "gvisor.dev/gvisor/tools/constraintutil"
)
var (
@@ -214,10 +214,13 @@ func main() {
// Automated warning.
fmt.Fprint(outputFile, "// automatically generated by stateify.\n\n")
- // Emit build tags.
- if t := tags.Aggregate(flag.Args()); len(t) > 0 {
- fmt.Fprintf(outputFile, "%s\n\n", strings.Join(t.Lines(), "\n"))
+ // Emit build constraints.
+ bcexpr, err := constraintutil.CombineFromFiles(flag.Args())
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to infer build constraints: %v", err)
+ os.Exit(1)
}
+ outputFile.WriteString(constraintutil.Lines(bcexpr))
// Emit the package name.
_, pkg := filepath.Split(*fullPkg)
diff --git a/tools/nogo/BUILD b/tools/nogo/BUILD
index a7e280b32..27fe48680 100644
--- a/tools/nogo/BUILD
+++ b/tools/nogo/BUILD
@@ -1,4 +1,4 @@
-load("//tools:defs.bzl", "bzl_library", "go_library", "select_goarch", "select_goos")
+load("//tools:defs.bzl", "bzl_library", "go_library", "go_test", "select_goarch", "select_goos")
load("//tools/nogo:defs.bzl", "nogo_objdump_tool", "nogo_stdlib", "nogo_target")
package(licenses = ["notice"])
@@ -73,6 +73,12 @@ go_library(
],
)
+go_test(
+ name = "nogo_test",
+ srcs = ["config_test.go"],
+ library = ":nogo",
+)
+
bzl_library(
name = "defs_bzl",
srcs = ["defs.bzl"],
diff --git a/tools/nogo/config.go b/tools/nogo/config.go
index 6436f9d34..ee2533610 100644
--- a/tools/nogo/config.go
+++ b/tools/nogo/config.go
@@ -186,16 +186,19 @@ func (a AnalyzerConfig) merge(other AnalyzerConfig) {
}
}
-func (a AnalyzerConfig) shouldReport(groupConfig *Group, fullPos, msg string) bool {
+// shouldReport returns whether the finding should be reported or suppressed.
+// It returns !ok if there is no configuration sufficient to decide one way or
+// another.
+func (a AnalyzerConfig) shouldReport(groupConfig *Group, fullPos, msg string) (report, ok bool) {
gc, ok := a[groupConfig.Name]
if !ok {
- return groupConfig.Default
+ return false, false
}
// Note that if a section appears for a particular group
// for a particular analyzer, then it will now be enabled,
// and the group default no longer applies.
- return gc.shouldReport(fullPos, msg)
+ return gc.shouldReport(fullPos, msg), true
}
// Config is a nogo configuration.
@@ -298,7 +301,8 @@ func (c *Config) ShouldReport(finding Finding) bool {
}
// Suppress via global rule?
- if !c.Global.shouldReport(groupConfig, fullPos, finding.Message) {
+ report, ok := c.Global.shouldReport(groupConfig, fullPos, finding.Message)
+ if ok && !report {
return false
}
@@ -307,5 +311,9 @@ func (c *Config) ShouldReport(finding Finding) bool {
if !ok {
return groupConfig.Default
}
- return ac.shouldReport(groupConfig, fullPos, finding.Message)
+ report, ok = ac.shouldReport(groupConfig, fullPos, finding.Message)
+ if !ok {
+ return groupConfig.Default
+ }
+ return report
}
diff --git a/tools/nogo/config_test.go b/tools/nogo/config_test.go
new file mode 100644
index 000000000..685cffbec
--- /dev/null
+++ b/tools/nogo/config_test.go
@@ -0,0 +1,301 @@
+// Copyright 2021 The gVisor Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.package nogo
+package nogo
+
+import (
+ "go/token"
+ "testing"
+)
+
+// TestShouldReport validates the suppression behavior of Config.ShouldReport.
+func TestShouldReport(t *testing.T) {
+ config := &Config{
+ Groups: []Group{
+ {
+ Name: "default-enabled",
+ Regex: "^default-enabled/",
+ Default: true,
+ },
+ {
+ Name: "default-disabled",
+ Regex: "^default-disabled/",
+ Default: false,
+ },
+ {
+ Name: "default-disabled-omitted-from-global",
+ Regex: "^default-disabled-omitted-from-global/",
+ Default: false,
+ },
+ },
+ Global: AnalyzerConfig{
+ "default-enabled": &ItemConfig{
+ Exclude: []string{"excluded.go"},
+ Suppress: []string{"suppressed"},
+ },
+ "default-disabled": &ItemConfig{
+ Exclude: []string{"excluded.go"},
+ Suppress: []string{"suppressed"},
+ },
+ // Omitting default-disabled-omitted-from-global here
+ // has no effect on configuration below.
+ },
+ Analyzers: map[AnalyzerName]AnalyzerConfig{
+ "analyzer-suppressions": AnalyzerConfig{
+ // Suppress some.
+ "default-enabled": &ItemConfig{
+ Exclude: []string{"limited-exclude.go"},
+ Suppress: []string{"limited suppress"},
+ },
+ // Enable all.
+ "default-disabled": nil,
+ },
+ "enabled-for-default-disabled": AnalyzerConfig{
+ "default-disabled": nil,
+ "default-disabled-omitted-from-global": nil,
+ },
+ },
+ }
+
+ if err := config.Compile(); err != nil {
+ t.Fatalf("Compile(%+v) = %v, want nil", config, err)
+ }
+
+ cases := []struct {
+ name string
+ finding Finding
+ want bool
+ }{
+ {
+ name: "enabled",
+ finding: Finding{
+ Category: "foo",
+ Position: token.Position{
+ Filename: "default-enabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: true,
+ },
+ {
+ name: "ungrouped",
+ finding: Finding{
+ Category: "foo",
+ Position: token.Position{
+ Filename: "ungrouped/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: true,
+ },
+ {
+ name: "suppressed",
+ finding: Finding{
+ Category: "foo",
+ Position: token.Position{
+ Filename: "default-enabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message suppressed",
+ },
+ want: false,
+ },
+ {
+ name: "excluded",
+ finding: Finding{
+ Category: "foo",
+ Position: token.Position{
+ Filename: "default-enabled/excluded.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: false,
+ },
+ {
+ name: "disabled",
+ finding: Finding{
+ Category: "foo",
+ Position: token.Position{
+ Filename: "default-disabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: false,
+ },
+ {
+ name: "analyzer suppressed",
+ finding: Finding{
+ Category: "analyzer-suppressions",
+ Position: token.Position{
+ Filename: "default-enabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message limited suppress",
+ },
+ want: false,
+ },
+ {
+ name: "analyzer suppressed not global",
+ finding: Finding{
+ // Doesn't apply outside of analyzer-suppressions.
+ Category: "foo",
+ Position: token.Position{
+ Filename: "default-enabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message limited suppress",
+ },
+ want: true,
+ },
+ {
+ name: "analyzer suppressed grouped",
+ finding: Finding{
+ Category: "analyzer-suppressions",
+ Position: token.Position{
+ // Doesn't apply outside of default-enabled.
+ Filename: "default-disabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message limited suppress",
+ },
+ want: true,
+ },
+ {
+ name: "analyzer excluded",
+ finding: Finding{
+ Category: "analyzer-suppressions",
+ Position: token.Position{
+ Filename: "default-enabled/limited-exclude.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: false,
+ },
+ {
+ name: "analyzer excluded not global",
+ finding: Finding{
+ // Doesn't apply outside of analyzer-suppressions.
+ Category: "foo",
+ Position: token.Position{
+ Filename: "default-enabled/limited-exclude.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: true,
+ },
+ {
+ name: "analyzer excluded grouped",
+ finding: Finding{
+ Category: "analyzer-suppressions",
+ Position: token.Position{
+ // Doesn't apply outside of default-enabled.
+ Filename: "default-disabled/limited-exclude.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: true,
+ },
+ {
+ name: "disabled-omitted",
+ finding: Finding{
+ Category: "foo",
+ Position: token.Position{
+ Filename: "default-disabled-omitted-from-global/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: false,
+ },
+ {
+ name: "default enabled applies to customized analyzer",
+ finding: Finding{
+ Category: "enabled-for-default-disabled",
+ Position: token.Position{
+ Filename: "default-enabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: true,
+ },
+ {
+ name: "default overridden in customized analyzer",
+ finding: Finding{
+ Category: "enabled-for-default-disabled",
+ Position: token.Position{
+ Filename: "default-disabled/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: true,
+ },
+ {
+ name: "default overridden in customized analyzer even when omitted from global",
+ finding: Finding{
+ Category: "enabled-for-default-disabled",
+ Position: token.Position{
+ Filename: "default-disabled-omitted-from-global/file.go",
+ Offset: 0,
+ Line: 1,
+ Column: 1,
+ },
+ Message: "message",
+ },
+ want: true,
+ },
+ }
+ for _, tc := range cases {
+ t.Run(tc.name, func(t *testing.T) {
+ if got := config.ShouldReport(tc.finding); got != tc.want {
+ t.Errorf("ShouldReport(%+v) = %v, want %v", tc.finding, got, tc.want)
+ }
+ })
+ }
+}
diff --git a/tools/nogo/findings.go b/tools/nogo/findings.go
index 329a7062e..a73bf1a09 100644
--- a/tools/nogo/findings.go
+++ b/tools/nogo/findings.go
@@ -109,7 +109,7 @@ func ExtractFindingsFromFile(filename string, asJSON bool) (FindingSet, error) {
return ExtractFindingsFrom(r, asJSON)
}
-// ExtractFindingsFromBytes loads findings from bytes.
+// ExtractFindingsFrom loads findings from an io.Reader.
func ExtractFindingsFrom(r io.Reader, asJSON bool) (findings FindingSet, err error) {
if asJSON {
dec := json.NewDecoder(r)
diff --git a/tools/tags/BUILD b/tools/tags/BUILD
deleted file mode 100644
index 1c02e2c89..000000000
--- a/tools/tags/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-load("//tools:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "tags",
- srcs = ["tags.go"],
- marshal = False,
- stateify = False,
- visibility = ["//tools:__subpackages__"],
-)
diff --git a/tools/tags/tags.go b/tools/tags/tags.go
deleted file mode 100644
index f35904e0a..000000000
--- a/tools/tags/tags.go
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package tags is a utility for parsing build tags.
-package tags
-
-import (
- "fmt"
- "io/ioutil"
- "strings"
-)
-
-// OrSet is a set of tags on a single line.
-//
-// Note that tags may include ",", and we don't distinguish this case in the
-// logic below. Ideally, this constraints can be split into separate top-level
-// build tags in order to resolve any issues.
-type OrSet []string
-
-// Line returns the line for this or.
-func (or OrSet) Line() string {
- return fmt.Sprintf("// +build %s", strings.Join([]string(or), " "))
-}
-
-// AndSet is the set of all OrSets.
-type AndSet []OrSet
-
-// Lines returns the lines to be printed.
-func (and AndSet) Lines() (ls []string) {
- for _, or := range and {
- ls = append(ls, or.Line())
- }
- return
-}
-
-// Join joins this AndSet with another.
-func (and AndSet) Join(other AndSet) AndSet {
- return append(and, other...)
-}
-
-// Tags returns the unique set of +build tags.
-//
-// Derived form the runtime's canBuild.
-func Tags(file string) (tags AndSet) {
- data, err := ioutil.ReadFile(file)
- if err != nil {
- return nil
- }
- // Check file contents for // +build lines.
- for _, p := range strings.Split(string(data), "\n") {
- p = strings.TrimSpace(p)
- if p == "" {
- continue
- }
- if !strings.HasPrefix(p, "//") {
- break
- }
- if !strings.Contains(p, "+build") {
- continue
- }
- fields := strings.Fields(p[2:])
- if len(fields) < 1 || fields[0] != "+build" {
- continue
- }
- tags = append(tags, OrSet(fields[1:]))
- }
- return tags
-}
-
-// Aggregate aggregates all tags from a set of files.
-//
-// Note that these may be in conflict, in which case the build will fail.
-func Aggregate(files []string) (tags AndSet) {
- for _, file := range files {
- tags = tags.Join(Tags(file))
- }
- return tags
-}