From 279b6d62d37265aeb8e48027de92847e089fed78 Mon Sep 17 00:00:00 2001 From: Isaev Denis Date: Tue, 5 May 2020 18:45:19 +0300 Subject: [PATCH] speed up a bit (#1064) Ensure that `unused` is always the last in execution order. It can speed up packages loading a bit. Refactor enabled linters set to remove extra logging. Relates: #944 --- go.mod | 6 +----- go.sum | 22 +++------------------ pkg/commands/linters.go | 20 +++++++------------ pkg/commands/run.go | 18 ++++++----------- pkg/lint/linter/config.go | 12 +++++++++--- pkg/lint/lintersdb/enabled_set.go | 23 +++++++++++++++++----- pkg/lint/lintersdb/manager.go | 1 + pkg/lint/runner.go | 29 +++++++++++++++------------- pkg/result/processors/nolint.go | 11 +++-------- pkg/result/processors/nolint_test.go | 8 ++++---- 10 files changed, 68 insertions(+), 82 deletions(-) diff --git a/go.mod b/go.mod index 03714fe0..2f8de7b3 100644 --- a/go.mod +++ b/go.mod @@ -52,12 +52,8 @@ require ( github.com/valyala/quicktemplate v1.2.0 golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770 gopkg.in/yaml.v2 v2.2.8 + honnef.co/go/tools v0.0.1-2020.1.3 mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f ) - -// See https://github.com/golangci/golangci-lint/issues/995 -// Update only after mitigating this issue. -// TODO: Enable back tests with skip "Issue955" after update. -require honnef.co/go/tools v0.0.1-2020.1.3 diff --git a/go.sum b/go.sum index d13fb507..005b1251 100644 --- a/go.sum +++ b/go.sum @@ -24,7 +24,6 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -156,14 +155,11 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -187,7 +183,6 @@ github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b h1:9+ke9YJ9KGWw5AN github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mozilla/tls-observatory v0.0.0-20200220173314-aae45faa4006/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mozilla/tls-observatory v0.0.0-20200317151703-4fa42e1c2dee/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nakabonne/nestif v0.3.0 h1:+yOViDGhg8ygGrmII72nV9B/zGxY188TYpfolntsaPw= @@ -228,8 +223,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/ryancurrah/gomodguard v1.0.4 h1:oCreMAt9GuFXDe9jW4HBpc3GjdX3R/sUEcLAGh1zPx8= github.com/ryancurrah/gomodguard v1.0.4/go.mod h1:9T/Cfuxs5StfsocWr4WzDL36HqnX0fVb9d5fSEaLhoE= -github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd h1:qB+l4fYZsH78xORC1aqVS0zNmgkQp4rkj2rvfxQMtzc= -github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd/go.mod h1:NurAFZsWJAEZjogSwdVPlHkOZB3DOAU7gsPP8VFZCHc= github.com/securego/gosec/v2 v2.2.1-0.20200424144625-ee3146e63716 h1:E/qamk0wO4PVhJhce201hAJWk/rKnGqKOk/blHzkY7o= github.com/securego/gosec/v2 v2.2.1-0.20200424144625-ee3146e63716/go.mod h1:UzeVyUXbxukhLeHKV3VVqo7HdoQR9MrRfFmZYotn8ME= github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada h1:WokF3GuxBeL+n4Lk4Fa8v9mbdjlrl7bHuneF4N1bk2I= @@ -268,8 +261,6 @@ github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfD github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= @@ -316,10 +307,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -333,8 +321,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -371,20 +357,19 @@ golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200228224639-71482053b885/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331202046-9d5940d49312/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e h1:3Dzrrxi54Io7Aoyb0PYLsI47K2TxkRQg+cqUn+m04do= golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770 h1:M9Fif0OxNji8w+HvmhVQ8KJtiZOsjU9RgslJGhn95XE= +golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770 h1:M9Fif0OxNji8w+HvmhVQ8KJtiZOsjU9RgslJGhn95XE= +golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770 h1:M9Fif0OxNji8w+HvmhVQ8KJtiZOsjU9RgslJGhn95XE= golang.org/x/tools v0.0.0-20200502202811-ed308ab3e770/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -394,6 +379,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -420,8 +406,6 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= diff --git a/pkg/commands/linters.go b/pkg/commands/linters.go index 84452201..ab73de67 100644 --- a/pkg/commands/linters.go +++ b/pkg/commands/linters.go @@ -20,32 +20,26 @@ func (e *Executor) initLinters() { e.initRunConfiguration(lintersCmd) } -func IsLinterInConfigsList(name string, linters []*linter.Config) bool { - for _, lc := range linters { - if lc.Name() == name { - return true - } - } - - return false -} - func (e *Executor) executeLinters(_ *cobra.Command, args []string) { if len(args) != 0 { e.log.Fatalf("Usage: golangci-lint linters") } - enabledLCs, err := e.EnabledLintersSet.Get(false) + enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap() if err != nil { log.Fatalf("Can't get enabled linters: %s", err) } color.Green("Enabled by your configuration linters:\n") - printLinterConfigs(enabledLCs) + enabledLinters := make([]*linter.Config, 0, len(enabledLintersMap)) + for _, linter := range enabledLintersMap { + enabledLinters = append(enabledLinters, linter) + } + printLinterConfigs(enabledLinters) var disabledLCs []*linter.Config for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { - if !IsLinterInConfigsList(lc.Name(), enabledLCs) { + if enabledLintersMap[lc.Name()] == nil { disabledLCs = append(disabledLCs, lc) } } diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 4149a00c..ec3f93dd 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -285,40 +285,34 @@ func fixSlicesFlags(fs *pflag.FlagSet) { func (e *Executor) runAnalysis(ctx context.Context, args []string) ([]result.Issue, error) { e.cfg.Run.Args = args - enabledLinters, err := e.EnabledLintersSet.Get(true) + lintersToRun, err := e.EnabledLintersSet.GetOptimizedLinters() if err != nil { return nil, err } - enabledOriginalLinters, err := e.EnabledLintersSet.Get(false) + enabledLintersMap, err := e.EnabledLintersSet.GetEnabledLintersMap() if err != nil { return nil, err } for _, lc := range e.DBManager.GetAllSupportedLinterConfigs() { - isEnabled := false - for _, enabledLC := range enabledOriginalLinters { - if enabledLC.Name() == lc.Name() { - isEnabled = true - break - } - } + isEnabled := enabledLintersMap[lc.Name()] != nil e.reportData.AddLinter(lc.Name(), isEnabled, lc.EnabledByDefault) } - lintCtx, err := e.contextLoader.Load(ctx, enabledLinters) + lintCtx, err := e.contextLoader.Load(ctx, lintersToRun) if err != nil { return nil, errors.Wrap(err, "context loading failed") } lintCtx.Log = e.log.Child("linters context") runner, err := lint.NewRunner(e.cfg, e.log.Child("runner"), - e.goenv, e.lineCache, e.DBManager, lintCtx.Packages) + e.goenv, e.EnabledLintersSet, e.lineCache, e.DBManager, lintCtx.Packages) if err != nil { return nil, err } - issues, err := runner.Run(ctx, enabledLinters, lintCtx) + issues, err := runner.Run(ctx, lintersToRun, lintCtx) if err != nil { return nil, err } diff --git a/pkg/lint/linter/config.go b/pkg/lint/linter/config.go index 52ff9b90..4ec83525 100644 --- a/pkg/lint/linter/config.go +++ b/pkg/lint/linter/config.go @@ -22,9 +22,10 @@ type Config struct { InPresets []string AlternativeNames []string - OriginalURL string // URL of original (not forked) repo, needed for autogenerated README - CanAutoFix bool - IsSlow bool + OriginalURL string // URL of original (not forked) repo, needed for autogenerated README + CanAutoFix bool + IsSlow bool + DoesChangeTypes bool } func (lc *Config) ConsiderSlow() *Config { @@ -67,6 +68,11 @@ func (lc *Config) WithAutoFix() *Config { return lc } +func (lc *Config) WithChangeTypes() *Config { + lc.DoesChangeTypes = true + return lc +} + func (lc *Config) AllNames() []string { return append([]string{lc.Name()}, lc.AlternativeNames...) } diff --git a/pkg/lint/lintersdb/enabled_set.go b/pkg/lint/lintersdb/enabled_set.go index 37e2166f..6450f1d1 100644 --- a/pkg/lint/lintersdb/enabled_set.go +++ b/pkg/lint/lintersdb/enabled_set.go @@ -77,16 +77,25 @@ func (es EnabledSet) build(lcfg *config.Linters, enabledByDefaultLinters []*lint return resultLintersSet } -func (es EnabledSet) Get(optimize bool) ([]*linter.Config, error) { +func (es EnabledSet) GetEnabledLintersMap() (map[string]*linter.Config, error) { + if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil { + return nil, err + } + + return es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters()), nil +} + +// GetOptimizedLinters returns enabled linters after optimization (merging) of multiple linters +// into a fewer number of linters. E.g. some go/analysis linters can be optimized into +// one metalinter for data reuse and speed up. +func (es EnabledSet) GetOptimizedLinters() ([]*linter.Config, error) { if err := es.v.validateEnabledDisabledLintersConfig(&es.cfg.Linters); err != nil { return nil, err } resultLintersSet := es.build(&es.cfg.Linters, es.m.GetAllEnabledByDefaultLinters()) es.verbosePrintLintersStatus(resultLintersSet) - if optimize { - es.combineGoAnalysisLinters(resultLintersSet) - } + es.combineGoAnalysisLinters(resultLintersSet) var resultLinters []*linter.Config for _, lc := range resultLintersSet { @@ -95,7 +104,11 @@ func (es EnabledSet) Get(optimize bool) ([]*linter.Config, error) { // Make order of execution of linters (go/analysis metalinter and unused) stable. sort.Slice(resultLinters, func(i, j int) bool { - return strings.Compare(resultLinters[i].Name(), resultLinters[j].Name()) <= 0 + a, b := resultLinters[i], resultLinters[j] + if a.DoesChangeTypes != b.DoesChangeTypes { + return b.DoesChangeTypes // move type-changing linters to the end to optimize speed + } + return strings.Compare(a.Name(), b.Name()) < 0 }) return resultLinters, nil diff --git a/pkg/lint/lintersdb/manager.go b/pkg/lint/lintersdb/manager.go index 492b9225..33b4378c 100644 --- a/pkg/lint/lintersdb/manager.go +++ b/pkg/lint/lintersdb/manager.go @@ -125,6 +125,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetUnused). WithAlternativeNames(megacheckName). ConsiderSlow(). + WithChangeTypes(). WithURL("https://github.com/dominikh/go-tools/tree/master/unused"), linter.NewConfig(golinters.NewGosimple()). WithLoadForGoAnalysis(). diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go index e8f427e0..05dc51ba 100644 --- a/pkg/lint/runner.go +++ b/pkg/lint/runner.go @@ -7,6 +7,8 @@ import ( "runtime/debug" "strings" + "github.com/pkg/errors" + "github.com/golangci/golangci-lint/internal/errorutil" "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/fsutils" @@ -27,7 +29,7 @@ type Runner struct { Log logutils.Log } -func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, +func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lintersdb.EnabledSet, lineCache *fsutils.LineCache, dbManager *lintersdb.Manager, pkgs []*gopackages.Package) (*Runner, error) { icfg := cfg.Issues excludePatterns := icfg.ExcludePatterns @@ -77,11 +79,9 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, excludeRulesProcessor = processors.NewExcludeRules(excludeRules, lineCache, log.Child("exclude_rules")) } - enabledLintersSet := lintersdb.NewEnabledSet(dbManager, - lintersdb.NewValidator(dbManager), log.Child("enabledLinters"), cfg) - lcs, err := enabledLintersSet.Get(false) + enabledLinters, err := es.GetEnabledLintersMap() if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to get enabled linters") } return &Runner{ @@ -103,7 +103,7 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, excludeProcessor, excludeRulesProcessor, - processors.NewNolint(log.Child("nolint"), dbManager, lcs), + processors.NewNolint(log.Child("nolint"), dbManager, enabledLinters), processors.NewUniqByLine(cfg), processors.NewDiff(icfg.Diff, icfg.DiffFromRevision, icfg.DiffPatchFilePath), @@ -131,14 +131,17 @@ func (r *Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, } }() - specificLintCtx := *lintCtx - specificLintCtx.Log = r.Log.Child(lc.Name()) + issues, err := lc.Linter.Run(ctx, lintCtx) + + if lc.DoesChangeTypes { + // Packages in lintCtx might be dirty due to the last analysis, + // which affects to the next analysis. + // To avoid this issue, we clear type information from the packages. + // See https://github.com/golangci/golangci-lint/pull/944. + // Currently DoesChangeTypes is true only for `unused`. + lintCtx.ClearTypesInPackages() + } - // Packages in lintCtx might be dirty due to the last analysis, - // which affects to the next analysis. - // To avoid this issue, we clear type information from the packages. - specificLintCtx.ClearTypesInPackages() - issues, err := lc.Linter.Run(ctx, &specificLintCtx) if err != nil { return nil, err } diff --git a/pkg/result/processors/nolint.go b/pkg/result/processors/nolint.go index 2f1e48db..cda10178 100644 --- a/pkg/result/processors/nolint.go +++ b/pkg/result/processors/nolint.go @@ -60,18 +60,13 @@ type filesCache map[string]*fileData type Nolint struct { cache filesCache dbManager *lintersdb.Manager - enabledLinters map[string]bool + enabledLinters map[string]*linter.Config log logutils.Log unknownLintersSet map[string]bool } -func NewNolint(log logutils.Log, dbManager *lintersdb.Manager, enabledLCs []*linter.Config) *Nolint { - enabledLinters := make(map[string]bool, len(enabledLCs)) - for _, lc := range enabledLCs { - enabledLinters[lc.Name()] = true - } - +func NewNolint(log logutils.Log, dbManager *lintersdb.Manager, enabledLinters map[string]*linter.Config) *Nolint { return &Nolint{ cache: filesCache{}, dbManager: dbManager, @@ -154,7 +149,7 @@ func (p *Nolint) shouldPassIssue(i *result.Issue) (bool, error) { if i.ExpectedNoLintLinter != "" { // don't expect disabled linters to cover their nolint statements nolintDebugf("enabled linters: %v", p.enabledLinters) - if !p.enabledLinters[i.ExpectedNoLintLinter] { + if p.enabledLinters[i.ExpectedNoLintLinter] == nil { return false, nil } nolintDebugf("checking that lint issue was used for %s: %v", i.ExpectedNoLintLinter, i) diff --git a/pkg/result/processors/nolint_test.go b/pkg/result/processors/nolint_test.go index 051b1ebc..9fe50c4c 100644 --- a/pkg/result/processors/nolint_test.go +++ b/pkg/result/processors/nolint_test.go @@ -253,9 +253,9 @@ func TestNolintUnused(t *testing.T) { cfg := &config.Config{Linters: config.Linters{DisableAll: true, Enable: enabledLinters}} dbManager := lintersdb.NewManager(cfg, nil) enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg) - lcs, err := enabledLintersSet.Get(false) + enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap() assert.NoError(t, err) - return NewNolint(log, dbManager, lcs) + return NewNolint(log, dbManager, enabledLintersMap) } // the issues below the nolintlint issues that would be generated for the test file @@ -297,9 +297,9 @@ func TestNolintUnused(t *testing.T) { dbManager := lintersdb.NewManager(cfg, nil) enabledLintersSet := lintersdb.NewEnabledSet(dbManager, lintersdb.NewValidator(dbManager), enabledSetLog, cfg) - lcs, err := enabledLintersSet.Get(false) + enabledLintersMap, err := enabledLintersSet.GetEnabledLintersMap() assert.NoError(t, err) - p := NewNolint(log, dbManager, lcs) + p := NewNolint(log, dbManager, enabledLintersMap) defer p.Finish() processAssertEmpty(t, p, nolintlintIssueVarcheck)