Repository: tomarrell/lbadd
Pull request #55 (2020-02-24 14:21:18)

Add internal analyzers to CI and makefile
Depends on #54 


Patch:
diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml
index 98ecb31..078d916 100644
--- a/.github/workflows/static_analysis.yml
+++ b/.github/workflows/static_analysis.yml
@@ -2,6 +2,23 @@ name: Static analysis
 on: [push, pull_request]
 
 jobs:
+  internal-analysis:
+    name: Run internal analyzers
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        go_version: [1.13]
+    steps:
+    - name: Set up Go ${{ matrix.go_version }}
+      uses: actions/setup-go@v1
+      with:
+        go-version: ${{ matrix.go_version }}
+      id: go
+    - name: Check out code into the Go module directory
+      uses: actions/checkout@v1
+    - name: analyze
+      run: go run ./internal/tool/analysis ./...
+  
   errcheck:
     name: Errcheck
     runs-on: ubuntu-latest
diff --git a/Makefile b/Makefile
index c360d82..48efba0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,16 @@
 .PHONY: watch
 watch: ## Start a file watcher to run tests on change. (requires: watchexec)
-	watchexec -c "go test -failfast ."
+	watchexec -c "go test -failfast ./..."
 
 .PHONY: test
 test: ## Runs the unit test suite
 	go test -failfast ./...
 
 .PHONY: lint
-lint: ## Runs the linters
+lint: ## Runs the linters (including internal ones)
+	# internal analysis tools
+	go run ./internal/tool/analysis ./...;
+	# external analysis tools
 	golint ./...;
 	errcheck ./...;
 	gosec -quiet ./...;
diff --git a/internal/tool/analysis/analysis.go b/internal/tool/analysis/analysis.go
index 56f07c8..16a186f 100644
--- a/internal/tool/analysis/analysis.go
+++ b/internal/tool/analysis/analysis.go
@@ -1,9 +1,14 @@
 package main
 
-import "golang.org/x/tools/go/analysis/multichecker"
+import (
+	"github.com/tomarrell/lbadd/internal/tool/analysis/nopanic"
+	"golang.org/x/tools/go/analysis/multichecker"
+)
 
 func main() {
 	// write an analyzer in a sub-package of this package and add it here as an
 	// argument in multichecker.Main(...).
-	multichecker.Main()
+	multichecker.Main(
+		nopanic.Analyzer,
+	)
 }
diff --git a/internal/tool/analysis/nopanic/nopanic.go b/internal/tool/analysis/nopanic/nopanic.go
new file mode 100644
index 0000000..3fbc704
--- /dev/null
+++ b/internal/tool/analysis/nopanic/nopanic.go
@@ -0,0 +1,46 @@
+// Package nopanic implements an analyzer that checks if somewhere in the
+// source, there is a panic.
+package nopanic
+
+import (
+	"go/ast"
+
+	"golang.org/x/tools/go/analysis"
+	"golang.org/x/tools/go/analysis/passes/inspect"
+	"golang.org/x/tools/go/ast/inspector"
+)
+
+// Analyzer implements the analyzer that checks for panics.
+var Analyzer = &analysis.Analyzer{
+	Name: "nopanic",
+	Doc:  Doc,
+	Run:  run,
+	Requires: []*analysis.Analyzer{
+		inspect.Analyzer,
+	},
+}
+
+// Doc is the documentation string that is shown on the command line if help is
+// requested.
+const Doc = "check if there is any panic in the code"
+
+func run(pass *analysis.Pass) (interface{}, error) {
+	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
+	inspect.Preorder([]ast.Node{
+		(*ast.CallExpr)(nil),
+	}, func(n ast.Node) {
+		call := n.(*ast.CallExpr)
+		if callExprIsPanic(call) {
+			pass.Reportf(call.Pos(), "panic is disallowed in this location")
+		}
+	})
+	return nil, nil
+}
+
+func callExprIsPanic(call *ast.CallExpr) bool {
+	ident, ok := call.Fun.(*ast.Ident)
+	if !ok {
+		return false
+	}
+	return ident.Name == "panic"
+}


Test patch:
diff --git a/internal/tool/analysis/nopanic/nopanic_test.go b/internal/tool/analysis/nopanic/nopanic_test.go
new file mode 100644
index 0000000..aac4406
--- /dev/null
+++ b/internal/tool/analysis/nopanic/nopanic_test.go
@@ -0,0 +1,17 @@
+package nopanic_test
+
+import (
+	"path/filepath"
+	"testing"
+
+	"github.com/tomarrell/lbadd/internal/tool/analysis/nopanic"
+	"golang.org/x/tools/go/analysis/analysistest"
+)
+
+func TestAnalyzer(t *testing.T) {
+	dir, err := filepath.Abs("./testdata")
+	if err != nil {
+		t.Error(err)
+	}
+	analysistest.Run(t, dir, nopanic.Analyzer, "./...")
+}
diff --git a/internal/tool/analysis/nopanic/testdata/test1.go b/internal/tool/analysis/nopanic/testdata/test1.go
new file mode 100644
index 0000000..f160aa6
--- /dev/null
+++ b/internal/tool/analysis/nopanic/testdata/test1.go
@@ -0,0 +1,5 @@
+package main
+
+func main() {
+	panic(nil) // want `panic is disallowed in this location`
+}