-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Weizhen Wang <[email protected]>
- Loading branch information
1 parent
1b8c93b
commit 9984489
Showing
60 changed files
with
1,375 additions
and
859 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright 2023 PingCAP, Inc. | ||
// | ||
// 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 build | ||
|
||
import ( | ||
_ "embed" | ||
"encoding/json" | ||
) | ||
|
||
//go:embed nogo_config.json | ||
var configFile []byte | ||
|
||
// NogoConfig is the nogo config file | ||
var NogoConfig NogoConfigFormat | ||
|
||
// NogoConfigFormat is the format of the nogo config file | ||
type NogoConfigFormat map[string]AnalysisConfig | ||
|
||
// AnalysisConfig represents the config of an analysis pass | ||
type AnalysisConfig struct { | ||
ExcludeFiles map[string]string `json:"exclude_files"` | ||
OnlyFiles map[string]string `json:"only_files"` | ||
} | ||
|
||
func init() { | ||
err := json.Unmarshal(configFile, &NogoConfig) | ||
if err != nil { | ||
panic("fail to parse nogo_config.json") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||
|
||
go_library( | ||
name = "linter", | ||
srcs = ["linter.go"], | ||
importpath = "github.com/pingcap/tidb/build/linter", | ||
visibility = ["//visibility:public"], | ||
deps = ["@com_github_apache_skywalking_eyes//pkg/config"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||
|
||
go_library( | ||
name = "bootstrap", | ||
srcs = ["analyzer.go"], | ||
importpath = "github.com/pingcap/tidb/build/linter/bootstrap", | ||
visibility = ["//visibility:public"], | ||
deps = [ | ||
"//build/linter/util", | ||
"@org_golang_x_tools//go/analysis", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// Copyright 2023 PingCAP, Inc. | ||
// | ||
// 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 bootstrap | ||
|
||
import ( | ||
"go/ast" | ||
"go/token" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/pingcap/tidb/build/linter/util" | ||
"golang.org/x/tools/go/analysis" | ||
) | ||
|
||
// Analyzer is the analyzer struct of unconvert. | ||
var Analyzer = &analysis.Analyzer{ | ||
Name: "bootstrap", | ||
Doc: "Check developers don't forget something in TiDB bootstrap logic", | ||
Requires: []*analysis.Analyzer{}, | ||
Run: run, | ||
} | ||
|
||
const ( | ||
bootstrapCodeFile = "/bootstrap.go" | ||
) | ||
|
||
func run(pass *analysis.Pass) (any, error) { | ||
for _, file := range pass.Files { | ||
if !strings.HasSuffix(pass.Fset.File(file.Pos()).Name(), bootstrapCodeFile) { | ||
continue | ||
} | ||
|
||
var ( | ||
maxVerVariable int | ||
maxVerVariablePos token.Pos | ||
curVerVariable int | ||
curVerVariablePos token.Pos | ||
maxVerFunc int | ||
maxVerFuncPos token.Pos | ||
maxVerFuncUsed int | ||
maxVerFuncUsedPos token.Pos | ||
err error | ||
) | ||
|
||
for _, decl := range file.Decls { | ||
switch v := decl.(type) { | ||
case *ast.GenDecl: | ||
switch { | ||
case len(v.Specs) == 1: | ||
spec := v.Specs[0] | ||
v2, ok := spec.(*ast.ValueSpec) | ||
if !ok { | ||
continue | ||
} | ||
if len(v2.Names) != 1 { | ||
continue | ||
} | ||
switch v2.Names[0].Name { | ||
case "bootstrapVersion": | ||
composeLit := v2.Values[0].(*ast.CompositeLit) | ||
lastElm := composeLit.Elts[len(composeLit.Elts)-1] | ||
ident := lastElm.(*ast.Ident) | ||
maxVerFuncUsed, err = strconv.Atoi(ident.Name[len("upgradeToVer"):]) | ||
if err != nil { | ||
panic("unexpected value of bootstrapVersion: " + ident.Name) | ||
} | ||
maxVerFuncUsedPos = lastElm.Pos() | ||
case "currentBootstrapVersion": | ||
valueIdent := v2.Values[0].(*ast.Ident) | ||
curVerVariablePos = valueIdent.Pos() | ||
value := v2.Values[0].(*ast.Ident).Name | ||
curVerVariable, err = strconv.Atoi(value[len("version"):]) | ||
if err != nil { | ||
panic("unexpected value of currentBootstrapVersion: " + value) | ||
} | ||
default: | ||
continue | ||
} | ||
case v.Tok == token.CONST && len(v.Specs) > 1: | ||
for _, spec := range v.Specs { | ||
v2, ok := spec.(*ast.ValueSpec) | ||
if !ok { | ||
continue | ||
} | ||
if len(v2.Names) != 1 { | ||
continue | ||
} | ||
name := v2.Names[0].Name | ||
if !strings.HasPrefix(name, "version") { | ||
continue | ||
} | ||
|
||
valInName, err := strconv.Atoi(name[len("version"):]) | ||
if err != nil { | ||
continue | ||
} | ||
|
||
if valInName < maxVerVariable { | ||
pass.Reportf(spec.Pos(), "version variable %q is not valid, we should have a increment list of version variables", name) | ||
continue | ||
} | ||
|
||
maxVerVariable = valInName | ||
maxVerVariablePos = v2.Names[0].Pos() | ||
|
||
if len(v2.Values) != 1 { | ||
pass.Reportf(spec.Pos(), "the value of version variable %q must be specified explicitly", name) | ||
continue | ||
} | ||
|
||
valStr := v2.Values[0].(*ast.BasicLit).Value | ||
val, err := strconv.Atoi(valStr) | ||
if err != nil { | ||
pass.Reportf(spec.Pos(), "unexpected value of version variable %q: %q", name, valStr) | ||
continue | ||
} | ||
|
||
if val != valInName { | ||
pass.Reportf(spec.Pos(), "the value of version variable %q must be '%d', but now is '%d'", name, valInName, val) | ||
continue | ||
} | ||
} | ||
} | ||
case *ast.FuncDecl: | ||
name := v.Name.Name | ||
if !strings.HasPrefix(name, "upgradeToVer") { | ||
continue | ||
} | ||
t, err := strconv.Atoi(name[len("upgradeToVer"):]) | ||
if err != nil { | ||
continue | ||
} | ||
if t > maxVerFunc { | ||
maxVerFunc = t | ||
maxVerFuncPos = v.Pos() | ||
} | ||
} | ||
} | ||
minv := min(maxVerVariable, maxVerFunc, maxVerFuncUsed, curVerVariable) | ||
maxv := max(maxVerVariable, maxVerFunc, maxVerFuncUsed, curVerVariable) | ||
if minv == maxv && minv != 0 { | ||
return nil, nil | ||
} | ||
pass.Reportf(maxVerFuncUsedPos, "found inconsistent bootstrap versions:") | ||
pass.Reportf(maxVerFuncUsedPos, "max version function used: %d", maxVerFuncUsed) | ||
pass.Reportf(maxVerFuncPos, "max version function: %d", maxVerFunc) | ||
pass.Reportf(maxVerVariablePos, "max version variable: %d", maxVerVariable) | ||
pass.Reportf(curVerVariablePos, "current version variable: %d", curVerVariable) | ||
} | ||
return nil, nil | ||
} | ||
|
||
func init() { | ||
util.SkipAnalyzerByConfig(Analyzer) | ||
} |
Oops, something went wrong.