From a45dac53a0e6f48cec0c971b81bf3e580c765c05 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 17 Aug 2023 17:54:00 +0200 Subject: [PATCH 1/8] Introduce koanf linter that checks that field names match koanf tags --- .gitignore | 1 + .gitmodules | 3 + .golangci.yml | 7 +++ Makefile | 4 +- go.mod | 17 +++--- go.sum | 34 ++++++----- linter/golangci-lint | 1 + linter/koanf/koanf.go | 116 +++++++++++++++++++++++++++++++++++++ linter/koanf/koanf_test.go | 31 ++++++++++ 9 files changed, 189 insertions(+), 25 deletions(-) create mode 160000 linter/golangci-lint create mode 100644 linter/koanf/koanf.go create mode 100644 linter/koanf/koanf_test.go diff --git a/.gitignore b/.gitignore index f0eb5c2ec3..8937c1b5d1 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ yarn-error.log local/ testdata system_tests/test-data/* +linter/koanf/koanf.so \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 7c78791c78..11d9caa2aa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,6 @@ [submodule "nitro-testnode"] path = nitro-testnode url = https://github.com/OffchainLabs/nitro-testnode.git +[submodule "linter/golangci-lint"] + path = linter/golangci-lint + url = https://github.com/golangci/golangci-lint diff --git a/.golangci.yml b/.golangci.yml index e794cdb844..952a52a0c8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,6 +23,7 @@ linters: - nilerr # ensure errors aren't mishandled - staticcheck # check for suspicious constructs - unused # check for unused constructs + - koanf linters-settings: errcheck: @@ -51,3 +52,9 @@ linters-settings: disable: - shadow - fieldalignment + + + custom: + koanf: + path: linter/koanf/koanf.so + description: Koanf configuration linter diff --git a/Makefile b/Makefile index 205025dfe9..71c051087a 100644 --- a/Makefile +++ b/Makefile @@ -304,7 +304,9 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - golangci-lint run --fix + make build -C linter/golangci-lint + go build -buildmode=plugin -o linter/koanf/koanf.so linter/koanf/koanf.go + ./linter/golangci-lint/golangci-lint run --fix yarn --cwd contracts solhint @touch $@ diff --git a/go.mod b/go.mod index 5adfd19388..526f0a819f 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/codeclysm/extract/v3 v3.0.2 github.com/dgraph-io/badger/v3 v3.2103.2 github.com/ethereum/go-ethereum v1.10.26 + github.com/fatih/structtag v1.2.0 github.com/google/go-cmp v0.5.9 github.com/hashicorp/golang-lru/v2 v2.0.1 github.com/ipfs/go-cid v0.3.2 @@ -31,7 +32,8 @@ require ( github.com/multiformats/go-multihash v0.2.1 github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 - golang.org/x/term v0.6.0 + golang.org/x/term v0.11.0 + golang.org/x/tools v0.12.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -256,8 +258,7 @@ require ( go.uber.org/zap v1.24.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/mod v0.12.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/grpc v1.46.0 // indirect @@ -309,11 +310,11 @@ require ( github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - golang.org/x/crypto v0.6.0 - golang.org/x/net v0.8.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 - golang.org/x/text v0.8.0 // indirect + golang.org/x/crypto v0.12.0 + golang.org/x/net v0.14.0 // indirect + golang.org/x/sync v0.3.0 // indirect + golang.org/x/sys v0.11.0 + golang.org/x/text v0.12.0 // indirect golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect ) diff --git a/go.sum b/go.sum index 58155db124..43240135c5 100644 --- a/go.sum +++ b/go.sum @@ -326,6 +326,8 @@ github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:Jp github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -1737,8 +1739,8 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= -golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1774,8 +1776,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1835,8 +1837,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1857,8 +1859,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1951,12 +1953,12 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1966,8 +1968,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2035,8 +2037,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= +golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/linter/golangci-lint b/linter/golangci-lint new file mode 160000 index 0000000000..8000abaf0e --- /dev/null +++ b/linter/golangci-lint @@ -0,0 +1 @@ +Subproject commit 8000abaf0e6e28e8179864f0317349cecab47c05 diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go new file mode 100644 index 0000000000..4aaddaa495 --- /dev/null +++ b/linter/koanf/koanf.go @@ -0,0 +1,116 @@ +package main + +import ( + "fmt" + "go/ast" + "go/token" + "reflect" + "strings" + "unicode" + + "github.com/fatih/structtag" + + "golang.org/x/tools/go/analysis" +) + +func New(conf any) ([]*analysis.Analyzer, error) { + return []*analysis.Analyzer{Analyzer}, nil +} + +var Analyzer = &analysis.Analyzer{ + Name: "koanfcheck", + Doc: "check for koanf misconfigurations", + Run: func(p *analysis.Pass) (interface{}, error) { return run(false, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +var analyzerForTests = &analysis.Analyzer{ + Name: "testkoanfcheck", + Doc: "check for koanf misconfigurations (for tests)", + Run: func(p *analysis.Pass) (interface{}, error) { return run(true, p) }, + ResultType: reflect.TypeOf(Result{}), +} + +// koanfError indicates the position of an error in configuration. +type koanfError struct { + Pos token.Position + Message string +} + +// Result is returned from the checkStruct function, and holds all the +// configuration errors. +type Result struct { + Errors []koanfError +} + +func run(dryRun bool, pass *analysis.Pass) (interface{}, error) { + var ret Result + for _, f := range pass.Files { + ast.Inspect(f, func(node ast.Node) bool { + var res Result + switch v := node.(type) { + case *ast.StructType: + res = checkStruct(pass, v) + default: + } + for _, err := range res.Errors { + ret.Errors = append(ret.Errors, err) + if !dryRun { + pass.Report(analysis.Diagnostic{ + Pos: pass.Fset.File(f.Pos()).Pos(err.Pos.Offset), + Message: err.Message, + Category: "koanf", + }) + } + } + return true + }, + ) + } + return ret, nil +} + +func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { + var res Result + for _, f := range s.Fields.List { + if f.Tag == nil { + continue + } + tags, err := structtag.Parse(strings.Trim((f.Tag.Value), "`")) + if err != nil { + continue + } + tag, err := tags.Get("koanf") + if err != nil { + continue + } + tagName := normalize(tag.Name) + fieldName := f.Names[0].Name + if !strings.EqualFold(tagName, fieldName) { + res.Errors = append(res.Errors, koanfError{ + Pos: pass.Fset.Position(f.Pos()), + Message: fmt.Sprintf("field name: %q doesn't match tag name: %q\n", fieldName, tagName), + }) + } + } + return res +} + +func normalize(s string) string { + ans := s[:1] + for i := 1; i < len(s); i++ { + c := rune(s[i]) + if !isAlphanumeric(c) { + continue + } + if !isAlphanumeric(rune(s[i-1])) && unicode.IsLower(c) { + c = unicode.ToUpper(c) + } + ans += string(c) + } + return ans +} + +func isAlphanumeric(c rune) bool { + return unicode.IsLetter(c) || unicode.IsDigit(c) +} diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go new file mode 100644 index 0000000000..2e3e68b0f4 --- /dev/null +++ b/linter/koanf/koanf_test.go @@ -0,0 +1,31 @@ +package main + +import ( + "os" + "path/filepath" + "testing" + + "golang.org/x/tools/go/analysis/analysistest" +) + +func TestAll(t *testing.T) { + wd, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get wd: %s", err) + } + testdata := filepath.Join(filepath.Dir(wd), "testdata") + res := analysistest.Run(t, testdata, analyzerForTests, "a") + if cnt := countErrors(res); cnt != 1 { + t.Errorf("analysistest.Run() got %v errors, expected 1", cnt) + } +} + +func countErrors(errs []*analysistest.Result) int { + cnt := 0 + for _, e := range errs { + if r, ok := e.Result.(Result); ok { + cnt += len(r.Errors) + } + } + return cnt +} From 7547edb550f6bca2761d2b06d761e6cf201cb7bf Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 17 Aug 2023 17:56:28 +0200 Subject: [PATCH 2/8] Add empty line at the end of gitignore --- .gitignore | 2 +- .golangci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8937c1b5d1..02cc86192b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,4 @@ yarn-error.log local/ testdata system_tests/test-data/* -linter/koanf/koanf.so \ No newline at end of file +linter/koanf/koanf.so diff --git a/.golangci.yml b/.golangci.yml index 952a52a0c8..8f2fdda037 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,7 +23,7 @@ linters: - nilerr # ensure errors aren't mishandled - staticcheck # check for suspicious constructs - unused # check for unused constructs - - koanf + - koanf # check for koanf configurations linters-settings: errcheck: From eba8989a80857d89573223c385ea5f4dabbe66a8 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 17 Aug 2023 17:57:31 +0200 Subject: [PATCH 3/8] drop extra empty line in golangci.yml --- .golangci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 8f2fdda037..47f471b5a1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -53,7 +53,6 @@ linters-settings: - shadow - fieldalignment - custom: koanf: path: linter/koanf/koanf.so From a5c667343a62d839baa5384141001bd3b182778f Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 18 Aug 2023 15:11:13 +0200 Subject: [PATCH 4/8] Run custom linter as go binary instead of plugin for golangci-lint, drop golangci-lint submodule --- .gitignore | 1 - .gitmodules | 3 --- .golangci.yml | 6 ------ Makefile | 4 +--- linter/golangci-lint | 1 - linter/koanf/koanf.go | 6 +++++- 6 files changed, 6 insertions(+), 15 deletions(-) delete mode 160000 linter/golangci-lint diff --git a/.gitignore b/.gitignore index 02cc86192b..f0eb5c2ec3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,3 @@ yarn-error.log local/ testdata system_tests/test-data/* -linter/koanf/koanf.so diff --git a/.gitmodules b/.gitmodules index 11d9caa2aa..7c78791c78 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,6 +20,3 @@ [submodule "nitro-testnode"] path = nitro-testnode url = https://github.com/OffchainLabs/nitro-testnode.git -[submodule "linter/golangci-lint"] - path = linter/golangci-lint - url = https://github.com/golangci/golangci-lint diff --git a/.golangci.yml b/.golangci.yml index 47f471b5a1..e794cdb844 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,7 +23,6 @@ linters: - nilerr # ensure errors aren't mishandled - staticcheck # check for suspicious constructs - unused # check for unused constructs - - koanf # check for koanf configurations linters-settings: errcheck: @@ -52,8 +51,3 @@ linters-settings: disable: - shadow - fieldalignment - - custom: - koanf: - path: linter/koanf/koanf.so - description: Koanf configuration linter diff --git a/Makefile b/Makefile index 71c051087a..896bdd6a6e 100644 --- a/Makefile +++ b/Makefile @@ -304,9 +304,7 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(arbitrator_pro # strategic rules to minimize dependency building .make/lint: $(DEP_PREDICATE) build-node-deps $(ORDER_ONLY_PREDICATE) .make - make build -C linter/golangci-lint - go build -buildmode=plugin -o linter/koanf/koanf.so linter/koanf/koanf.go - ./linter/golangci-lint/golangci-lint run --fix + go run linter/koanf/koanf.go ./... yarn --cwd contracts solhint @touch $@ diff --git a/linter/golangci-lint b/linter/golangci-lint deleted file mode 160000 index 8000abaf0e..0000000000 --- a/linter/golangci-lint +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8000abaf0e6e28e8179864f0317349cecab47c05 diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index 4aaddaa495..bc94a9c20e 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -9,8 +9,8 @@ import ( "unicode" "github.com/fatih/structtag" - "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/singlechecker" ) func New(conf any) ([]*analysis.Analyzer, error) { @@ -114,3 +114,7 @@ func normalize(s string) string { func isAlphanumeric(c rune) bool { return unicode.IsLetter(c) || unicode.IsDigit(c) } + +func main() { + singlechecker.Main(Analyzer) +} From ed4942d38adc5afe1918740d35c3e67d1204f372 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 18 Aug 2023 16:02:53 +0200 Subject: [PATCH 5/8] Rename testdata to testsdata because testdata is already in .gitignore --- linter/koanf/koanf_test.go | 2 +- linter/testsdata/src/a/a.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 linter/testsdata/src/a/a.go diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go index 2e3e68b0f4..5582e61605 100644 --- a/linter/koanf/koanf_test.go +++ b/linter/koanf/koanf_test.go @@ -13,7 +13,7 @@ func TestAll(t *testing.T) { if err != nil { t.Fatalf("Failed to get wd: %s", err) } - testdata := filepath.Join(filepath.Dir(wd), "testdata") + testdata := filepath.Join(filepath.Dir(wd), "testsdata") res := analysistest.Run(t, testdata, analyzerForTests, "a") if cnt := countErrors(res); cnt != 1 { t.Errorf("analysistest.Run() got %v errors, expected 1", cnt) diff --git a/linter/testsdata/src/a/a.go b/linter/testsdata/src/a/a.go new file mode 100644 index 0000000000..ddf77b6ed1 --- /dev/null +++ b/linter/testsdata/src/a/a.go @@ -0,0 +1,11 @@ +package a + +type Config struct { + L2 int `koanf:"chain"` + LogLevel int `koanf:"log-level"` + LogType int `koanf:"log-type"` + Metrics int `koanf:"metrics"` + PProf int `koanf:"pprof"` + Node int `koanf:"node"` + Queue int `koanf:"queue"` +} From c93e79a45f37bc729e2d83a70991f4078964b0f4 Mon Sep 17 00:00:00 2001 From: Nodar Date: Fri, 18 Aug 2023 17:18:21 +0200 Subject: [PATCH 6/8] rename 'testsdata' to 'testdata' drop it from .gitignore --- .gitignore | 1 - linter/koanf/koanf_test.go | 2 +- linter/{testsdata => testdata}/src/a/a.go | 0 3 files changed, 1 insertion(+), 2 deletions(-) rename linter/{testsdata => testdata}/src/a/a.go (100%) diff --git a/.gitignore b/.gitignore index f0eb5c2ec3..60df842f0e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,4 @@ solgen/go/ target/ yarn-error.log local/ -testdata system_tests/test-data/* diff --git a/linter/koanf/koanf_test.go b/linter/koanf/koanf_test.go index 5582e61605..2e3e68b0f4 100644 --- a/linter/koanf/koanf_test.go +++ b/linter/koanf/koanf_test.go @@ -13,7 +13,7 @@ func TestAll(t *testing.T) { if err != nil { t.Fatalf("Failed to get wd: %s", err) } - testdata := filepath.Join(filepath.Dir(wd), "testsdata") + testdata := filepath.Join(filepath.Dir(wd), "testdata") res := analysistest.Run(t, testdata, analyzerForTests, "a") if cnt := countErrors(res); cnt != 1 { t.Errorf("analysistest.Run() got %v errors, expected 1", cnt) diff --git a/linter/testsdata/src/a/a.go b/linter/testdata/src/a/a.go similarity index 100% rename from linter/testsdata/src/a/a.go rename to linter/testdata/src/a/a.go From 121cc8bfee933c856230b9f11d4d9fdb40a4cb0f Mon Sep 17 00:00:00 2001 From: Nodar Date: Wed, 23 Aug 2023 15:04:26 +0200 Subject: [PATCH 7/8] Merge with mater --- go.mod | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 2cae3a9cf2..10991bc3a2 100644 --- a/go.mod +++ b/go.mod @@ -33,6 +33,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/wealdtech/go-merkletree v1.0.0 golang.org/x/term v0.6.0 + golang.org/x/tools v0.7.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) @@ -258,7 +259,6 @@ require ( go4.org v0.0.0-20200411211856-f5505b9728dd // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect golang.org/x/mod v0.9.0 // indirect - golang.org/x/tools v0.7.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1 // indirect google.golang.org/grpc v1.46.0 // indirect @@ -312,7 +312,7 @@ require ( golang.org/x/crypto v0.6.0 golang.org/x/net v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.6.0 + golang.org/x/sys v0.7.0 golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect From a7e26b2c038471bcd11831fbcc517238114efbb9 Mon Sep 17 00:00:00 2001 From: Nodar Date: Thu, 31 Aug 2023 15:30:04 +0200 Subject: [PATCH 8/8] Drop normalize method in koanf.go, ignore case when comparing tag and a field --- linter/koanf/koanf.go | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/linter/koanf/koanf.go b/linter/koanf/koanf.go index bc94a9c20e..2127fb23b0 100644 --- a/linter/koanf/koanf.go +++ b/linter/koanf/koanf.go @@ -6,7 +6,6 @@ import ( "go/token" "reflect" "strings" - "unicode" "github.com/fatih/structtag" "golang.org/x/tools/go/analysis" @@ -84,7 +83,7 @@ func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { if err != nil { continue } - tagName := normalize(tag.Name) + tagName := strings.ReplaceAll(tag.Name, "-", "") fieldName := f.Names[0].Name if !strings.EqualFold(tagName, fieldName) { res.Errors = append(res.Errors, koanfError{ @@ -96,25 +95,6 @@ func checkStruct(pass *analysis.Pass, s *ast.StructType) Result { return res } -func normalize(s string) string { - ans := s[:1] - for i := 1; i < len(s); i++ { - c := rune(s[i]) - if !isAlphanumeric(c) { - continue - } - if !isAlphanumeric(rune(s[i-1])) && unicode.IsLower(c) { - c = unicode.ToUpper(c) - } - ans += string(c) - } - return ans -} - -func isAlphanumeric(c rune) bool { - return unicode.IsLetter(c) || unicode.IsDigit(c) -} - func main() { singlechecker.Main(Analyzer) }