Create & Init Project...
This commit is contained in:
44
app/admin/main/config/pkg/lint/BUILD
Normal file
44
app/admin/main/config/pkg/lint/BUILD
Normal file
@ -0,0 +1,44 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["lint.go"],
|
||||
importpath = "go-common/app/admin/main/config/pkg/lint",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_xtest",
|
||||
srcs = ["lint_test.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/admin/main/config/pkg/lint:go_default_library",
|
||||
"//app/admin/main/config/pkg/lint/json:go_default_library",
|
||||
"//app/admin/main/config/pkg/lint/toml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//app/admin/main/config/pkg/lint/json:all-srcs",
|
||||
"//app/admin/main/config/pkg/lint/toml:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
37
app/admin/main/config/pkg/lint/json/BUILD
Normal file
37
app/admin/main/config/pkg/lint/json/BUILD
Normal file
@ -0,0 +1,37 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_test",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["jsonlint_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["jsonlint.go"],
|
||||
importpath = "go-common/app/admin/main/config/pkg/lint/json",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//app/admin/main/config/pkg/lint:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
26
app/admin/main/config/pkg/lint/json/jsonlint.go
Normal file
26
app/admin/main/config/pkg/lint/json/jsonlint.go
Normal file
@ -0,0 +1,26 @@
|
||||
package jsonlint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"go-common/app/admin/main/config/pkg/lint"
|
||||
)
|
||||
|
||||
const filetype = "json"
|
||||
|
||||
type jsonlint struct{}
|
||||
|
||||
func (jsonlint) Lint(r io.Reader) lint.Error {
|
||||
var v interface{}
|
||||
dec := json.NewDecoder(r)
|
||||
err := dec.Decode(&v)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return lint.Error{{Line: -1, Message: err.Error()}}
|
||||
}
|
||||
|
||||
func init() {
|
||||
lint.RegisterLinter(filetype, jsonlint{})
|
||||
}
|
38
app/admin/main/config/pkg/lint/json/jsonlint_test.go
Normal file
38
app/admin/main/config/pkg/lint/json/jsonlint_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package jsonlint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var testdata = `
|
||||
{
|
||||
"a1": "a1",
|
||||
"b2":
|
||||
}
|
||||
`
|
||||
|
||||
var testdataok = `
|
||||
{
|
||||
"hello": "world"
|
||||
}
|
||||
`
|
||||
|
||||
func TestJsonLint(t *testing.T) {
|
||||
lint := jsonlint{}
|
||||
r := bytes.NewBufferString(testdata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
t.Logf("%s", lintErr.Error())
|
||||
}
|
||||
|
||||
func TestJsonLintOk(t *testing.T) {
|
||||
lint := jsonlint{}
|
||||
r := bytes.NewBufferString(testdataok)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr != nil {
|
||||
t.Error(lintErr)
|
||||
}
|
||||
}
|
63
app/admin/main/config/pkg/lint/lint.go
Normal file
63
app/admin/main/config/pkg/lint/lint.go
Normal file
@ -0,0 +1,63 @@
|
||||
package lint
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var linterMap map[string]Linter
|
||||
|
||||
// ErrLintNotExists .
|
||||
var ErrLintNotExists = errors.New("linter not exists")
|
||||
|
||||
func init() {
|
||||
linterMap = make(map[string]Linter)
|
||||
}
|
||||
|
||||
// RegisterLinter register linter for a kind of file
|
||||
func RegisterLinter(filetype string, linter Linter) {
|
||||
if _, ok := linterMap[filetype]; ok {
|
||||
panic("linter for filetype " + filetype + " already exists")
|
||||
}
|
||||
linterMap[filetype] = linter
|
||||
}
|
||||
|
||||
// LineErr error contains line number
|
||||
type LineErr struct {
|
||||
Line int `json:"line"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Error lint error
|
||||
type Error []LineErr
|
||||
|
||||
func (errs Error) Error() string {
|
||||
messages := make([]string, 0, len(errs))
|
||||
for _, err := range errs {
|
||||
messages = append(messages, fmt.Sprintf("%d:%s", err.Line, err.Message))
|
||||
}
|
||||
return strings.Join(messages, "\n")
|
||||
}
|
||||
|
||||
func (errs Error) String() string {
|
||||
return errs.Error()
|
||||
}
|
||||
|
||||
// Linter lint config file
|
||||
type Linter interface {
|
||||
Lint(r io.Reader) Error
|
||||
}
|
||||
|
||||
// Lint config file,
|
||||
func Lint(filetype string, r io.Reader) error {
|
||||
lint, ok := linterMap[filetype]
|
||||
if !ok {
|
||||
return ErrLintNotExists
|
||||
}
|
||||
if lintErr := lint.Lint(r); lintErr != nil {
|
||||
return lintErr
|
||||
}
|
||||
return nil
|
||||
}
|
35
app/admin/main/config/pkg/lint/lint_test.go
Normal file
35
app/admin/main/config/pkg/lint/lint_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package lint_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/main/config/pkg/lint"
|
||||
_ "go-common/app/admin/main/config/pkg/lint/json"
|
||||
_ "go-common/app/admin/main/config/pkg/lint/toml"
|
||||
)
|
||||
|
||||
func TestLint(t *testing.T) {
|
||||
jsonRead := bytes.NewBufferString(`{"hello": "world", "a1":"ab"}`)
|
||||
err := lint.Lint("json", jsonRead)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
tomlRead := bytes.NewBufferString(`[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00 # First class dates
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true`)
|
||||
err = lint.Lint("toml", tomlRead)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
err = lint.Lint("test", tomlRead)
|
||||
if err != lint.ErrLintNotExists {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
}
|
43
app/admin/main/config/pkg/lint/toml/BUILD
Normal file
43
app/admin/main/config/pkg/lint/toml/BUILD
Normal file
@ -0,0 +1,43 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_test",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"testdata_test.go",
|
||||
"tomllint_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["tomllint.go"],
|
||||
importpath = "go-common/app/admin/main/config/pkg/lint/toml",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/main/config/pkg/lint:go_default_library",
|
||||
"//vendor/github.com/BurntSushi/toml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
62
app/admin/main/config/pkg/lint/toml/testdata_test.go
Normal file
62
app/admin/main/config/pkg/lint/toml/testdata_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package tomllint
|
||||
|
||||
var synataxerrordata = `
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob 1979-05-27T07:32:00-08:00 # First class dates
|
||||
|
||||
`
|
||||
var normaldata = `
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00 # First class dates
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# Indentation (tabs and/or spaces) is allowed but not required
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ]
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
]
|
||||
`
|
||||
|
||||
var notopkvdata = `
|
||||
title = "test123"
|
||||
age = 123
|
||||
array = [1,2,3]
|
||||
[clients]
|
||||
data = "helo"
|
||||
`
|
||||
|
||||
var nocommondata = `
|
||||
version = "v1.1"
|
||||
user = "nobody"
|
||||
`
|
||||
|
||||
var noidentify = `
|
||||
[identify]
|
||||
xxx = 123
|
||||
`
|
||||
|
||||
var noapp = `
|
||||
[app]
|
||||
xxx = 123
|
||||
`
|
100
app/admin/main/config/pkg/lint/toml/tomllint.go
Normal file
100
app/admin/main/config/pkg/lint/toml/tomllint.go
Normal file
@ -0,0 +1,100 @@
|
||||
package tomllint
|
||||
|
||||
import (
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"go-common/app/admin/main/config/pkg/lint"
|
||||
)
|
||||
|
||||
var lineNumberRe *regexp.Regexp
|
||||
|
||||
const filetype = "toml"
|
||||
|
||||
type lintFn func(metadata toml.MetaData) []lint.LineErr
|
||||
|
||||
var lintFns []lintFn
|
||||
|
||||
type tomllint struct{}
|
||||
|
||||
// Lint toml file return lint.Error
|
||||
func (tomllint) Lint(r io.Reader) lint.Error {
|
||||
var v interface{}
|
||||
var lintErr lint.Error
|
||||
metadata, err := toml.DecodeReader(r, &v)
|
||||
if err != nil {
|
||||
line := -1
|
||||
if match := lineNumberRe.FindStringSubmatch(err.Error()); len(match) == 2 {
|
||||
line, _ = strconv.Atoi(match[1])
|
||||
}
|
||||
lintErr = append(lintErr, lint.LineErr{Line: line, Message: err.Error()})
|
||||
return lintErr
|
||||
}
|
||||
for _, fn := range lintFns {
|
||||
if lineErrs := fn(metadata); lineErrs != nil {
|
||||
lintErr = append(lintErr, lineErrs...)
|
||||
}
|
||||
}
|
||||
if len(lintErr) == 0 {
|
||||
return nil
|
||||
}
|
||||
return lintErr
|
||||
}
|
||||
|
||||
// not allowed defined kv that type is not Hash at top level
|
||||
//func noTopKV(metadata toml.MetaData) []lint.LineErr {
|
||||
// var lineErrs []lint.LineErr
|
||||
// for _, keys := range metadata.Keys() {
|
||||
// if len(keys) != 1 {
|
||||
// continue
|
||||
// }
|
||||
// typeName := metadata.Type(keys...)
|
||||
// if typeName != "Hash" {
|
||||
// lineErrs = append(lineErrs, lint.LineErr{
|
||||
// Line: -1,
|
||||
// Message: fmt.Sprintf("top level value must be Object, key: %s type is %s", keys[0], typeName),
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// return lineErrs
|
||||
//}
|
||||
|
||||
// noApp not allowed app section exists
|
||||
func noApp(metadata toml.MetaData) []lint.LineErr {
|
||||
if metadata.IsDefined("app") {
|
||||
return []lint.LineErr{{Line: -1, Message: "请删除无用 App 配置 see: http://git.bilibili.co/platform/go-common/issues/310 (゜-゜)つロ"}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// noIdentify not allowed identify config
|
||||
func noIdentify(metadata toml.MetaData) []lint.LineErr {
|
||||
if metadata.IsDefined("identify") {
|
||||
return []lint.LineErr{{Line: -1, Message: "请删除无用 Identify 配置 see: http://git.bilibili.co/platform/go-common/issues/310 (゜-゜)つロ"}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// noCommon not allowed common config
|
||||
func noCommon(metadata toml.MetaData) []lint.LineErr {
|
||||
count := 0
|
||||
commonKey := []string{"version", "user", "pid", "dir", "perf"}
|
||||
for _, key := range commonKey {
|
||||
if metadata.IsDefined(key) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count > 0 {
|
||||
return []lint.LineErr{{Line: -1, Message: "请删除无用 Common 配置 see: http://git.bilibili.co/platform/go-common/issues/310 (゜-゜)つロ"}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
lint.RegisterLinter(filetype, tomllint{})
|
||||
lintFns = []lintFn{noApp, noIdentify, noCommon}
|
||||
lineNumberRe = regexp.MustCompile("^Near line (\\d+)")
|
||||
}
|
67
app/admin/main/config/pkg/lint/toml/tomllint_test.go
Normal file
67
app/admin/main/config/pkg/lint/toml/tomllint_test.go
Normal file
@ -0,0 +1,67 @@
|
||||
package tomllint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSyntaxError(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(synataxerrordata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
if lintErr[0].Line == -1 {
|
||||
t.Errorf("expect get line number")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTomlLintOK(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(normaldata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr != nil {
|
||||
t.Errorf("error %v", lintErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoCommon(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(nocommondata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
message := lintErr.Error()
|
||||
if !strings.Contains(message, "Common") {
|
||||
t.Errorf("expect error contains common")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoIdentify(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(noidentify)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
message := lintErr.Error()
|
||||
if !strings.Contains(message, "Identify") {
|
||||
t.Errorf("expect error Identify common")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoApp(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(noapp)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
message := lintErr.Error()
|
||||
if !strings.Contains(message, "App") {
|
||||
t.Errorf("expect error App common")
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user