Skip to content

Commit

Permalink
Add the maincheck linter that ensures all the main functions are decl…
Browse files Browse the repository at this point in the history
…ared

in a file that is called main.go

GitOrigin-RevId: 6d554550b9b9edd19bda3c7ab9a5d16e28a8d017
oncilla committed Mar 14, 2022
1 parent cb5bfa6 commit 309ecd9
Showing 14 changed files with 98 additions and 12 deletions.
3 changes: 2 additions & 1 deletion nogo.bzl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
nogo_deps = [
"@com_github_scionproto_scion//tools/lint/log:log",
"@com_github_scionproto_scion//tools/lint/log:go_default_library",
"@com_github_scionproto_scion//tools/lint/maincheck:go_default_library",
"@com_github_oncilla_gochecks//logcheck:go_default_library",
"@com_github_oncilla_gochecks//serrorscheck:go_default_library",
"@org_golang_x_tools//go/analysis/passes/asmdecl:go_default_library",
8 changes: 7 additions & 1 deletion nogo.json
Original file line number Diff line number Diff line change
@@ -99,5 +99,11 @@
"exclude_files": {
"com_github_grpc_ecosystem_go_grpc_middleware/retry": ""
}
},
"maincheck": {
"exclude_files": {
"/com_github_deepmap_oapi_codegen/": "",
"/com_github_golang_mock/mockgen": ""
}
}
}
}
2 changes: 1 addition & 1 deletion scion/cmd/scion/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -5,9 +5,9 @@ go_library(
name = "go_default_library",
srcs = [
"address.go",
"main.go",
"observability.go",
"ping.go",
"scion.go",
"showpaths.go",
"traceroute.go",
],
File renamed without changes.
8 changes: 3 additions & 5 deletions tools/lint/log/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")

#gazelle:ignore gazelle would add a go_library block which we don't need here.
load("//lint:go.bzl", "go_library")

go_library(
name = "log",
name = "go_default_library",
srcs = ["log.go"],
importpath = "lint",
importpath = "github.com/scionproto/scion/tools/lint/log",
visibility = ["//visibility:public"],
deps = [
"@org_golang_x_tools//go/analysis:go_default_library",
9 changes: 9 additions & 0 deletions tools/lint/maincheck/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("//lint:go.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = ["maincheck.go"],
importpath = "github.com/scionproto/scion/tools/lint/maincheck",
visibility = ["//visibility:public"],
deps = ["@org_golang_x_tools//go/analysis:go_default_library"],
)
72 changes: 72 additions & 0 deletions tools/lint/maincheck/maincheck.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2022 Anapaya Systems
//
// 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 maincheck

import (
"go/ast"
"path/filepath"

"golang.org/x/tools/go/analysis"
)

var permitted = []string{
"main.go",
"testmain.go", // bazel uses this for unit and integration tests.
"go_default_mock_gomock_prog.go", // bazel uses this for mock generation.
}

// Analyzer contains an analyzer that makes sure that go target is always a
// func literal that calls defer log.HandlePanic as first statement.
var Analyzer = &analysis.Analyzer{
Name: "maincheck",
Doc: "Check that main function is located in a main.go file",
Run: run,
RunDespiteErrors: true,
}

func run(pass *analysis.Pass) (interface{}, error) {
for _, file := range pass.Files {
// If this is not a main package, we can exit early.
if file.Name.Name != "main" {
return nil, nil
}

for _, dec := range file.Decls {
fun, ok := dec.(*ast.FuncDecl)
if !ok {
continue
}
if fun.Name.Name != "main" {
continue
}
base := filepath.Base(pass.Fset.File(file.Name.NamePos).Name())
found := func() bool {
for _, p := range permitted {
if base == p {
return true
}
}
return false
}()

if !found {
pass.Reportf(fun.Pos(),
"main function must be located in a file called main.go instead of %s", base,
)
}
}
}
return nil, nil
}
2 changes: 1 addition & 1 deletion tools/pathdb_dump/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ load("//:scion.bzl", "scion_go_binary")

go_library(
name = "go_default_library",
srcs = ["pathdb_dump.go"],
srcs = ["main.go"],
importpath = "github.com/scionproto/scion/tools/pathdb_dump",
visibility = ["//visibility:private"],
deps = [
File renamed without changes.
4 changes: 2 additions & 2 deletions tools/pktgen/cmd/pktgen/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ go_library(
name = "go_default_library",
srcs = [
"config.go",
"pktgen.go",
"main.go",
],
importpath = "github.com/scionproto/scion/tools/pktgen/cmd/pktgen",
visibility = ["//visibility:private"],
@@ -40,7 +40,7 @@ go_test(
srcs = [
"config_test.go",
"export_test.go",
"pktgen_test.go",
"main_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion tools/udpproxy/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ load("@io_bazel_rules_docker//go:image.bzl", "go_image")

go_library(
name = "go_default_library",
srcs = ["udpproxy.go"],
srcs = ["main.go"],
importpath = "github.com/scionproto/scion/tools/udpproxy",
visibility = ["//visibility:private"],
deps = [
File renamed without changes.

0 comments on commit 309ecd9

Please sign in to comment.