├── Makefile ├── README.md ├── cmd └── xerrchk │ └── main.go ├── go.mod ├── go.sum └── passes ├── LICENSE ├── erreq ├── erreq.go ├── erreq_test.go └── testdata │ └── src │ └── a │ ├── a.go │ ├── go.mod │ ├── go.sum │ └── vendor │ ├── golang.org │ └── x │ │ └── xerrors │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── README │ │ ├── adaptor.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── fmt.go │ │ ├── format.go │ │ ├── frame.go │ │ ├── go.mod │ │ ├── internal │ │ └── internal.go │ │ └── wrap.go │ └── modules.txt └── wrapping ├── testdata └── src │ └── a │ ├── error.go │ ├── go.mod │ ├── go.sum │ ├── if.go │ ├── map_range.go │ ├── option │ └── all │ │ └── all.go │ └── vendor │ ├── golang.org │ └── x │ │ └── xerrors │ │ ├── LICENSE │ │ ├── PATENTS │ │ ├── README │ │ ├── adaptor.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── fmt.go │ │ ├── format.go │ │ ├── frame.go │ │ ├── go.mod │ │ ├── internal │ │ └── internal.go │ │ └── wrap.go │ └── modules.txt ├── wrapping.go └── wrapping_test.go /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: test 2 | 3 | test: 4 | go test -v ./... 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xerrchk 2 | 3 | Static analysis tool for [xerrors](https://godoc.org/golang.org/x/xerrors). 4 | 5 | This tool has not been fully tested. If you have problem in using this, please report issues or send PR in GitHub. 6 | 7 | ## Install 8 | 9 | ```sh 10 | $ go get github.com/sachaos/xerrchk/cmd/xerrchk 11 | ``` 12 | 13 | ## Features 14 | 15 | * Find unwrapped error 16 | * Find binary expression which is comparing error" 17 | * Find invalid wrap format (using [tenntenn/gosa/passes/wraperrfmt](https://github.com/tenntenn/gosa/tree/master/passes/wraperrfmt)) 18 | * Checks returning nil when err is not nil (using [tenntenn/gosa/passes/nilerr](https://github.com/tenntenn/gosa/tree/master/passes/nilerr)) 19 | -------------------------------------------------------------------------------- /cmd/xerrchk/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/sachaos/xerrchk/passes/erreq" 5 | "github.com/sachaos/xerrchk/passes/wrapping" 6 | "github.com/tenntenn/gosa/passes/nilerr" 7 | "github.com/tenntenn/gosa/passes/wraperrfmt" 8 | "golang.org/x/tools/go/analysis/multichecker" 9 | ) 10 | 11 | func main() { 12 | multichecker.Main( 13 | wrapping.Analyzer, 14 | erreq.Analyzer, 15 | wraperrfmt.Analyzer, 16 | nilerr.Analyzer, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sachaos/xerrchk 2 | 3 | require ( 4 | github.com/tenntenn/gosa/passes/nilerr v0.0.0-20190214154943-d65ba59f6395 5 | github.com/tenntenn/gosa/passes/wraperrfmt v0.0.0-20190214154943-d65ba59f6395 6 | golang.org/x/tools v0.0.0-20190214204934-8dcb7bc8c7fe 7 | golang.org/x/xerrors v0.0.0-20190315151331-d61658bd2e18 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40= 4 | dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= 5 | dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= 6 | dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= 7 | dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= 8 | git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= 9 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 10 | github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 11 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 12 | github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= 13 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 14 | github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 15 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 16 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 17 | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= 18 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 19 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 20 | github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= 21 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 22 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 23 | github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= 24 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 25 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 26 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 27 | github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= 28 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 29 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 30 | github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= 31 | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 32 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 33 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 34 | github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 35 | github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= 36 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 37 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 38 | github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= 39 | github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= 40 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 41 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 42 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 43 | github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 44 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 45 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 46 | github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= 47 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= 48 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= 49 | github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= 50 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 51 | github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 52 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 53 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 54 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 55 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 56 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 57 | github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= 58 | github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= 59 | github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= 60 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= 61 | github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= 62 | github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= 63 | github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= 64 | github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= 65 | github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= 66 | github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= 67 | github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= 68 | github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= 69 | github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= 70 | github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= 71 | github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= 72 | github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= 73 | github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= 74 | github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= 75 | github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= 76 | github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 77 | github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= 78 | github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= 79 | github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= 80 | github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= 81 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 82 | github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= 83 | github.com/tenntenn/comment v0.0.0-20181121002213-5ca9d2df41d1 h1:x2YIpGGEzLRvIPuAwbgaME/YyUumLAlY3CN6BvsAf94= 84 | github.com/tenntenn/comment v0.0.0-20181121002213-5ca9d2df41d1/go.mod h1:EathzjUrWnMPz5E4yfCswi989Ykcx5JZy48KHjwMbx0= 85 | github.com/tenntenn/gosa/passes/nilerr v0.0.0-20190214154943-d65ba59f6395 h1:ulr7hdN8BbxQtZrs3AnEkr6ptIeqhSGX6CqEDdCS2lU= 86 | github.com/tenntenn/gosa/passes/nilerr v0.0.0-20190214154943-d65ba59f6395/go.mod h1:iTIPbMqlCGi5Y2dxbQ7pju7Alpoe+6GW8DGIsIma4Os= 87 | github.com/tenntenn/gosa/passes/wraperrfmt v0.0.0-20190214154943-d65ba59f6395 h1:J2Y++bDqQnmg4btLZOF9IpAGfgGY7ORvFPk4yDjHV5I= 88 | github.com/tenntenn/gosa/passes/wraperrfmt v0.0.0-20190214154943-d65ba59f6395/go.mod h1:S0fKUrZYV/lOBLD0XvDpd/ESVSsToyEbcOLktIxndrQ= 89 | github.com/tenntenn/readonly v0.0.0-20181208054919-8e3cac171114/go.mod h1:QClGzduntKrX7xBATQpfsUEo0MYSeyde+3YJMgmKIOc= 90 | go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= 91 | go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= 92 | golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= 93 | golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 94 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 95 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 96 | golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 97 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 98 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 99 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 100 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 101 | golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 102 | golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 103 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 104 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 105 | golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 106 | golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 107 | golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= 108 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 109 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 110 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 111 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 112 | golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 113 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 114 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 115 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 116 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 117 | golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 118 | golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 119 | golang.org/x/tools v0.0.0-20181120234846-b5f2cae84da8/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 120 | golang.org/x/tools v0.0.0-20190213135902-6bedcd10978a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 121 | golang.org/x/tools v0.0.0-20190214204934-8dcb7bc8c7fe h1:oou9Na+8DBZO/hrVPAjBTaHXmuDq0284mwGwfmQ4ids= 122 | golang.org/x/tools v0.0.0-20190214204934-8dcb7bc8c7fe/go.mod h1:E6PF97AdD6v0s+fPshSmumCW1S1Ne85RbPQxELkKa44= 123 | golang.org/x/xerrors v0.0.0-20190315151331-d61658bd2e18 h1:1AGvnywFL1aB5KLRxyLseWJI6aSYPo3oF7HSpXdWQdU= 124 | golang.org/x/xerrors v0.0.0-20190315151331-d61658bd2e18/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 125 | google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 126 | google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 127 | google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= 128 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 129 | google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 130 | google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 131 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 132 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 133 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 134 | google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 135 | google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= 136 | google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= 137 | google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 138 | google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= 139 | google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= 140 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 141 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 142 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 143 | grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= 144 | honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 145 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 146 | sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= 147 | sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= 148 | -------------------------------------------------------------------------------- /passes/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Takumasa Sakao @sachaos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /passes/erreq/erreq.go: -------------------------------------------------------------------------------- 1 | package erreq 2 | 3 | import ( 4 | "go/ast" 5 | "go/token" 6 | "go/types" 7 | 8 | "golang.org/x/tools/go/analysis" 9 | "golang.org/x/tools/go/analysis/passes/inspect" 10 | "golang.org/x/tools/go/ast/inspector" 11 | ) 12 | 13 | var Analyzer = &analysis.Analyzer{ 14 | Name: "erreq", 15 | Doc: "erreq finds binary ops and switch-case statements comparing errors", 16 | Run: run, 17 | Requires: []*analysis.Analyzer{ 18 | inspect.Analyzer, 19 | }, 20 | } 21 | 22 | var errType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) 23 | 24 | func run(pass *analysis.Pass) (interface{}, error) { 25 | inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) 26 | 27 | checkBinaryOps(pass, inspect) 28 | 29 | checkSwitchStmt(pass, inspect) 30 | 31 | return nil, nil 32 | } 33 | 34 | // Check boolean expression using == or !=. 35 | func checkBinaryOps(pass *analysis.Pass, inspect *inspector.Inspector) { 36 | nodeFilter := []ast.Node{ 37 | (*ast.BinaryExpr)(nil), 38 | } 39 | inspect.Preorder(nodeFilter, func(node ast.Node) { 40 | binExpr, ok := node.(*ast.BinaryExpr) 41 | 42 | if !ok { 43 | return 44 | } 45 | 46 | if !(binExpr.Op == token.EQL || binExpr.Op == token.NEQ) { 47 | return 48 | } 49 | 50 | xType, ok := pass.TypesInfo.Types[binExpr.X] 51 | if !ok { 52 | return 53 | } 54 | 55 | if !types.AssignableTo(xType.Type, errType) { 56 | return 57 | } 58 | 59 | yType, ok := pass.TypesInfo.Types[binExpr.Y] 60 | if !ok { 61 | return 62 | } 63 | 64 | if yType.IsNil() { 65 | return 66 | } 67 | 68 | pass.Reportf(node.Pos(), "do not compare error with \"==\" or \"!=\"") 69 | }) 70 | } 71 | 72 | // Check switch-case statement. 73 | func checkSwitchStmt(pass *analysis.Pass, inspect *inspector.Inspector) { 74 | nodeFilter := []ast.Node{ 75 | (*ast.SwitchStmt)(nil), 76 | } 77 | inspect.Preorder(nodeFilter, func(node ast.Node) { 78 | 79 | switchStmt, ok := node.(*ast.SwitchStmt) 80 | if !ok { 81 | return 82 | } 83 | 84 | tagType, ok := pass.TypesInfo.Types[switchStmt.Tag] 85 | if !ok { 86 | return 87 | } 88 | 89 | if !types.AssignableTo(tagType.Type, errType) { 90 | return 91 | } 92 | 93 | pass.Reportf(node.Pos(), "do not use error on switch statement") 94 | }) 95 | } 96 | -------------------------------------------------------------------------------- /passes/erreq/erreq_test.go: -------------------------------------------------------------------------------- 1 | package erreq_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/sachaos/xerrchk/passes/erreq" 7 | "golang.org/x/tools/go/analysis/analysistest" 8 | ) 9 | 10 | func Test(t *testing.T) { 11 | testdata := analysistest.TestData() 12 | analysistest.Run(t, testdata, erreq.Analyzer, "a") 13 | } 14 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/a.go: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | import ( 4 | "fmt" 5 | 6 | "golang.org/x/xerrors" 7 | ) 8 | 9 | var sentinelErr = fmt.Errorf("sentinel err") 10 | 11 | func main() { 12 | _ = alwaysErr() == nil // OK 13 | _ = alwaysErr() == sentinelErr // want `do not compare error with \"==\" or \"!=\"` 14 | _ = alwaysErr() != nil // OK 15 | _ = alwaysErr() != sentinelErr // want `do not compare error with \"==\" or \"!=\"` 16 | } 17 | 18 | func alwaysErr() error { 19 | return sentinelErr 20 | } 21 | 22 | func switchErrCase1() string { 23 | err := xerrors.New("write failed") 24 | switch err { // want `do not use error on switch statement` 25 | case sentinelErr: 26 | return "true" 27 | default: 28 | return "false" 29 | } 30 | } 31 | 32 | func switchErrCase2() string { 33 | err := xerrors.New("write failed") 34 | switch xerrors.Unwrap(err) { // want `do not use error on switch statement` 35 | case sentinelErr: 36 | return "true" 37 | default: 38 | return "false" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/go.mod: -------------------------------------------------------------------------------- 1 | module a 2 | 3 | require golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 4 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 h1:P6iTFmrTQqWrqLZPX1VMzCUbCRCAUXSUsSpkEOvWzJ0= 2 | golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 3 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/README: -------------------------------------------------------------------------------- 1 | This repository holds the transition packages for the new Go 1.13 error values. 2 | See golang.org/design/29934-error-values. 3 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/adaptor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "io" 11 | "reflect" 12 | "strconv" 13 | ) 14 | 15 | // FormatError calls the FormatError method of f with an errors.Printer 16 | // configured according to s and verb, and writes the result to s. 17 | func FormatError(f Formatter, s fmt.State, verb rune) { 18 | // Assuming this function is only called from the Format method, and given 19 | // that FormatError takes precedence over Format, it cannot be called from 20 | // any package that supports errors.Formatter. It is therefore safe to 21 | // disregard that State may be a specific printer implementation and use one 22 | // of our choice instead. 23 | 24 | // limitations: does not support printing error as Go struct. 25 | 26 | var ( 27 | sep = " " // separator before next error 28 | p = &state{State: s} 29 | direct = true 30 | ) 31 | 32 | var err error = f 33 | 34 | switch verb { 35 | // Note that this switch must match the preference order 36 | // for ordinary string printing (%#v before %+v, and so on). 37 | 38 | case 'v': 39 | if s.Flag('#') { 40 | if stringer, ok := err.(fmt.GoStringer); ok { 41 | io.WriteString(&p.buf, stringer.GoString()) 42 | goto exit 43 | } 44 | // proceed as if it were %v 45 | } else if s.Flag('+') { 46 | p.printDetail = true 47 | sep = "\n - " 48 | } 49 | case 's': 50 | case 'q', 'x', 'X': 51 | // Use an intermediate buffer in the rare cases that precision, 52 | // truncation, or one of the alternative verbs (q, x, and X) are 53 | // specified. 54 | direct = false 55 | 56 | default: 57 | p.buf.WriteString("%!") 58 | p.buf.WriteRune(verb) 59 | p.buf.WriteByte('(') 60 | switch { 61 | case err != nil: 62 | p.buf.WriteString(reflect.TypeOf(f).String()) 63 | default: 64 | p.buf.WriteString("") 65 | } 66 | p.buf.WriteByte(')') 67 | io.Copy(s, &p.buf) 68 | return 69 | } 70 | 71 | loop: 72 | for { 73 | switch v := err.(type) { 74 | case Formatter: 75 | err = v.FormatError((*printer)(p)) 76 | case fmt.Formatter: 77 | v.Format(p, 'v') 78 | break loop 79 | default: 80 | io.WriteString(&p.buf, v.Error()) 81 | break loop 82 | } 83 | if err == nil { 84 | break 85 | } 86 | if p.needColon || !p.printDetail { 87 | p.buf.WriteByte(':') 88 | p.needColon = false 89 | } 90 | p.buf.WriteString(sep) 91 | p.inDetail = false 92 | p.needNewline = false 93 | } 94 | 95 | exit: 96 | width, okW := s.Width() 97 | prec, okP := s.Precision() 98 | 99 | if !direct || (okW && width > 0) || okP { 100 | // Construct format string from State s. 101 | format := []byte{'%'} 102 | if s.Flag('-') { 103 | format = append(format, '-') 104 | } 105 | if s.Flag('+') { 106 | format = append(format, '+') 107 | } 108 | if s.Flag(' ') { 109 | format = append(format, ' ') 110 | } 111 | if okW { 112 | format = strconv.AppendInt(format, int64(width), 10) 113 | } 114 | if okP { 115 | format = append(format, '.') 116 | format = strconv.AppendInt(format, int64(prec), 10) 117 | } 118 | format = append(format, string(verb)...) 119 | fmt.Fprintf(s, string(format), p.buf.String()) 120 | } else { 121 | io.Copy(s, &p.buf) 122 | } 123 | } 124 | 125 | var detailSep = []byte("\n ") 126 | 127 | // state tracks error printing state. It implements fmt.State. 128 | type state struct { 129 | fmt.State 130 | buf bytes.Buffer 131 | 132 | printDetail bool 133 | inDetail bool 134 | needColon bool 135 | needNewline bool 136 | } 137 | 138 | func (s *state) Write(b []byte) (n int, err error) { 139 | if s.printDetail { 140 | if len(b) == 0 { 141 | return 0, nil 142 | } 143 | if s.inDetail && s.needColon { 144 | s.needNewline = true 145 | if b[0] == '\n' { 146 | b = b[1:] 147 | } 148 | } 149 | k := 0 150 | for i, c := range b { 151 | if s.needNewline { 152 | if s.inDetail && s.needColon { 153 | s.buf.WriteByte(':') 154 | s.needColon = false 155 | } 156 | s.buf.Write(detailSep) 157 | s.needNewline = false 158 | } 159 | if c == '\n' { 160 | s.buf.Write(b[k:i]) 161 | k = i + 1 162 | s.needNewline = true 163 | } 164 | } 165 | s.buf.Write(b[k:]) 166 | if !s.inDetail { 167 | s.needColon = true 168 | } 169 | } else if !s.inDetail { 170 | s.buf.Write(b) 171 | } 172 | return len(b), nil 173 | } 174 | 175 | // printer wraps a state to implement an xerrors.Printer. 176 | type printer state 177 | 178 | func (s *printer) Print(args ...interface{}) { 179 | if !s.inDetail || s.printDetail { 180 | fmt.Fprint((*state)(s), args...) 181 | } 182 | } 183 | 184 | func (s *printer) Printf(format string, args ...interface{}) { 185 | if !s.inDetail || s.printDetail { 186 | fmt.Fprintf((*state)(s), format, args...) 187 | } 188 | } 189 | 190 | func (s *printer) Detail() bool { 191 | s.inDetail = true 192 | return s.printDetail 193 | } 194 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package xerrors implements functions to manipulate errors. 6 | // 7 | // This package supports transitioning to the Go 2 proposal for error values: 8 | // https://golang.org/design/29934-error-values 9 | // 10 | // Most of the functions and types in this package will be incorporated into the 11 | // standard library's errors package in Go 1.13; the behavior of this package's 12 | // Errorf function will be incorporated into the standard library's fmt.Errorf. 13 | // Use this package to get equivalent behavior in all supported Go versions. For 14 | // example, create errors using 15 | // 16 | // xerrors.New("write failed") 17 | // 18 | // or 19 | // 20 | // xerrors.Errorf("while reading: %v", err) 21 | // 22 | // If you want your error type to participate in the new formatting 23 | // implementation for %v and %+v, provide it with a Format method that calls 24 | // xerrors.FormatError, as shown in the example for FormatError. 25 | package xerrors // import "golang.org/x/xerrors" 26 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import "fmt" 8 | 9 | // errorString is a trivial implementation of error. 10 | type errorString struct { 11 | s string 12 | frame Frame 13 | } 14 | 15 | // New returns an error that formats as the given text. 16 | // 17 | // The returned error contains a Frame set to the caller's location and 18 | // implements Formatter to show this information when printed with details. 19 | func New(text string) error { 20 | return &errorString{text, Caller(1)} 21 | } 22 | 23 | func (e *errorString) Error() string { 24 | return e.s 25 | } 26 | 27 | func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) } 28 | 29 | func (e *errorString) FormatError(p Printer) (next error) { 30 | p.Print(e.s) 31 | e.frame.Format(p) 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/fmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | 11 | "golang.org/x/xerrors/internal" 12 | ) 13 | 14 | // Errorf formats according to a format specifier and returns the string as a 15 | // value that satisfies error. 16 | // 17 | // The returned error includes the file and line number of the caller when 18 | // formatted with additional detail enabled. If the last argument is an error 19 | // the returned error's Format method will return it if the format string ends 20 | // with ": %s", ": %v", or ": %w". If the last argument is an error and the 21 | // format string ends with ": %w", the returned error implements Wrapper 22 | // with an Unwrap method returning it. 23 | func Errorf(format string, a ...interface{}) error { 24 | err, wrap := lastError(format, a) 25 | format = formatPlusW(format) 26 | if err == nil { 27 | return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)} 28 | } 29 | 30 | // TODO: this is not entirely correct. The error value could be 31 | // printed elsewhere in format if it mixes numbered with unnumbered 32 | // substitutions. With relatively small changes to doPrintf we can 33 | // have it optionally ignore extra arguments and pass the argument 34 | // list in its entirety. 35 | msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...) 36 | frame := Frame{} 37 | if internal.EnableTrace { 38 | frame = Caller(1) 39 | } 40 | if wrap { 41 | return &wrapError{msg, err, frame} 42 | } 43 | return &noWrapError{msg, err, frame} 44 | } 45 | 46 | // formatPlusW is used to avoid the vet check that will barf at %w. 47 | func formatPlusW(s string) string { 48 | return s 49 | } 50 | 51 | func lastError(format string, a []interface{}) (err error, wrap bool) { 52 | wrap = strings.HasSuffix(format, ": %w") 53 | if !wrap && 54 | !strings.HasSuffix(format, ": %s") && 55 | !strings.HasSuffix(format, ": %v") { 56 | return nil, false 57 | } 58 | 59 | if len(a) == 0 { 60 | return nil, false 61 | } 62 | 63 | err, ok := a[len(a)-1].(error) 64 | if !ok { 65 | return nil, false 66 | } 67 | 68 | return err, wrap 69 | } 70 | 71 | type noWrapError struct { 72 | msg string 73 | err error 74 | frame Frame 75 | } 76 | 77 | func (e *noWrapError) Error() string { 78 | return fmt.Sprint(e) 79 | } 80 | 81 | func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } 82 | 83 | func (e *noWrapError) FormatError(p Printer) (next error) { 84 | p.Print(e.msg) 85 | e.frame.Format(p) 86 | return e.err 87 | } 88 | 89 | type wrapError struct { 90 | msg string 91 | err error 92 | frame Frame 93 | } 94 | 95 | func (e *wrapError) Error() string { 96 | return fmt.Sprint(e) 97 | } 98 | 99 | func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } 100 | 101 | func (e *wrapError) FormatError(p Printer) (next error) { 102 | p.Print(e.msg) 103 | e.frame.Format(p) 104 | return e.err 105 | } 106 | 107 | func (e *wrapError) Unwrap() error { 108 | return e.err 109 | } 110 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/format.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | // A Formatter formats error messages. 8 | type Formatter interface { 9 | error 10 | 11 | // FormatError prints the receiver's first error and returns the next error in 12 | // the error chain, if any. 13 | FormatError(p Printer) (next error) 14 | } 15 | 16 | // A Printer formats error messages. 17 | // 18 | // The most common implementation of Printer is the one provided by package fmt 19 | // during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message 20 | // typically provide their own implementations. 21 | type Printer interface { 22 | // Print appends args to the message output. 23 | Print(args ...interface{}) 24 | 25 | // Printf writes a formatted string. 26 | Printf(format string, args ...interface{}) 27 | 28 | // Detail reports whether error detail is requested. 29 | // After the first call to Detail, all text written to the Printer 30 | // is formatted as additional detail, or ignored when 31 | // detail has not been requested. 32 | // If Detail returns false, the caller can avoid printing the detail at all. 33 | Detail() bool 34 | } 35 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/frame.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "runtime" 9 | ) 10 | 11 | // A Frame contains part of a call stack. 12 | type Frame struct { 13 | // Make room for three PCs: the one we were asked for, what it called, 14 | // and possibly a PC for skipPleaseUseCallersFrames. See: 15 | // https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169 16 | frames [3]uintptr 17 | } 18 | 19 | // Caller returns a Frame that describes a frame on the caller's stack. 20 | // The argument skip is the number of frames to skip over. 21 | // Caller(0) returns the frame for the caller of Caller. 22 | func Caller(skip int) Frame { 23 | var s Frame 24 | runtime.Callers(skip+1, s.frames[:]) 25 | return s 26 | } 27 | 28 | // location reports the file, line, and function of a frame. 29 | // 30 | // The returned function may be "" even if file and line are not. 31 | func (f Frame) location() (function, file string, line int) { 32 | frames := runtime.CallersFrames(f.frames[:]) 33 | if _, ok := frames.Next(); !ok { 34 | return "", "", 0 35 | } 36 | fr, ok := frames.Next() 37 | if !ok { 38 | return "", "", 0 39 | } 40 | return fr.Function, fr.File, fr.Line 41 | } 42 | 43 | // Format prints the stack as error detail. 44 | // It should be called from an error's Format implementation 45 | // after printing any other error detail. 46 | func (f Frame) Format(p Printer) { 47 | if p.Detail() { 48 | function, file, line := f.location() 49 | if function != "" { 50 | p.Printf("%s\n ", function) 51 | } 52 | if file != "" { 53 | p.Printf("%s:%d\n", file, line) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/go.mod: -------------------------------------------------------------------------------- 1 | module golang.org/x/xerrors 2 | 3 | go 1.11 4 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/internal/internal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package internal 6 | 7 | // EnableTrace indicates whether stack information should be recorded in errors. 8 | var EnableTrace = true 9 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/golang.org/x/xerrors/wrap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "reflect" 9 | ) 10 | 11 | // A Wrapper provides context around another error. 12 | type Wrapper interface { 13 | // Unwrap returns the next error in the error chain. 14 | // If there is no next error, Unwrap returns nil. 15 | Unwrap() error 16 | } 17 | 18 | // Opaque returns an error with the same error formatting as err 19 | // but that does not match err and cannot be unwrapped. 20 | func Opaque(err error) error { 21 | return noWrapper{err} 22 | } 23 | 24 | type noWrapper struct { 25 | error 26 | } 27 | 28 | func (e noWrapper) FormatError(p Printer) (next error) { 29 | if f, ok := e.error.(Formatter); ok { 30 | return f.FormatError(p) 31 | } 32 | p.Print(e.error) 33 | return nil 34 | } 35 | 36 | // Unwrap returns the result of calling the Unwrap method on err, if err implements 37 | // Unwrap. Otherwise, Unwrap returns nil. 38 | func Unwrap(err error) error { 39 | u, ok := err.(Wrapper) 40 | if !ok { 41 | return nil 42 | } 43 | return u.Unwrap() 44 | } 45 | 46 | // Is reports whether any error in err's chain matches target. 47 | // 48 | // An error is considered to match a target if it is equal to that target or if 49 | // it implements a method Is(error) bool such that Is(target) returns true. 50 | func Is(err, target error) bool { 51 | if target == nil { 52 | return err == target 53 | } 54 | for { 55 | if err == target { 56 | return true 57 | } 58 | if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) { 59 | return true 60 | } 61 | // TODO: consider supporing target.Is(err). This would allow 62 | // user-definable predicates, but also may allow for coping with sloppy 63 | // APIs, thereby making it easier to get away with them. 64 | if err = Unwrap(err); err == nil { 65 | return false 66 | } 67 | } 68 | } 69 | 70 | // As finds the first error in err's chain that matches the type to which target 71 | // points, and if so, sets the target to its value and returns true. An error 72 | // matches a type if it is assignable to the target type, or if it has a method 73 | // As(interface{}) bool such that As(target) returns true. As will panic if target 74 | // is not a non-nil pointer to a type which implements error or is of interface type. 75 | // 76 | // The As method should set the target to its value and return true if err 77 | // matches the type to which target points. 78 | func As(err error, target interface{}) bool { 79 | if target == nil { 80 | panic("errors: target cannot be nil") 81 | } 82 | val := reflect.ValueOf(target) 83 | typ := val.Type() 84 | if typ.Kind() != reflect.Ptr || val.IsNil() { 85 | panic("errors: target must be a non-nil pointer") 86 | } 87 | if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) { 88 | panic("errors: *target must be interface or implement error") 89 | } 90 | targetType := typ.Elem() 91 | for { 92 | if reflect.TypeOf(err).AssignableTo(targetType) { 93 | val.Elem().Set(reflect.ValueOf(err)) 94 | return true 95 | } 96 | if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) { 97 | return true 98 | } 99 | if err = Unwrap(err); err == nil { 100 | return false 101 | } 102 | } 103 | } 104 | 105 | var errorType = reflect.TypeOf((*error)(nil)).Elem() 106 | -------------------------------------------------------------------------------- /passes/erreq/testdata/src/a/vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 2 | golang.org/x/xerrors 3 | golang.org/x/xerrors/internal 4 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/error.go: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | type Error struct{} 4 | 5 | func (e Error) Error() string { 6 | return "something error" 7 | } 8 | 9 | func (e Error) Wrap(next error) error { // want `wrap with xerrros.Errorf or xerrors.Opaque` 10 | return &e 11 | } 12 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/go.mod: -------------------------------------------------------------------------------- 1 | module a 2 | 3 | require golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 4 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 h1:P6iTFmrTQqWrqLZPX1VMzCUbCRCAUXSUsSpkEOvWzJ0= 2 | golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 3 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/if.go: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | import "golang.org/x/xerrors" 4 | 5 | var sentinelErr = xerrors.New("sentinel error") 6 | 7 | func IfStatement(cond bool) error { 8 | var err error // want `wrap with xerrros.Errorf or xerrors.Opaque` 9 | if cond { 10 | err = sentinelErr 11 | } else { 12 | err = xerrors.Errorf("wrap: %w", sentinelErr) 13 | } 14 | 15 | return err 16 | } 17 | 18 | func IfStatement2(cond bool) error { 19 | var err error // OK 20 | if cond { 21 | err = xerrors.Errorf("wrap1: %w", sentinelErr) 22 | } else { 23 | err = xerrors.Errorf("wrap2: %w", sentinelErr) 24 | } 25 | 26 | return err 27 | } 28 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/map_range.go: -------------------------------------------------------------------------------- 1 | package a 2 | 3 | // NOTE: Case https://github.com/sachaos/xerrchk/issues/6 4 | func MapRange() error { 5 | maps := make(map[string]string) 6 | 7 | for range maps { 8 | } 9 | 10 | return nil 11 | } 12 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/option/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import "golang.org/x/xerrors" 4 | 5 | var sentinelErr = xerrors.New("sentinel err") 6 | 7 | func privateFunc1() error { 8 | return errFunc1() // want `wrap with xerrros.Errorf or xerrors.Opaque` 9 | } 10 | 11 | func privateFunc2() error { 12 | return xerrors.Errorf("wrap: %w", errFunc1()) // OK 13 | } 14 | 15 | func privateFunc3() error { 16 | _, err := errFunc2() // want `wrap with xerrros.Errorf or xerrors.Opaque` 17 | return err 18 | } 19 | 20 | func privateFunc4() error { 21 | _, err := errFunc2() // OK 22 | return xerrors.Errorf("wrap: %w", err) 23 | } 24 | 25 | func privateFunc5() error { 26 | return sentinelErr // want `wrap with xerrros.Errorf or xerrors.Opaque` 27 | } 28 | 29 | func PublicFunc1() error { 30 | return errFunc1() // want `wrap with xerrros.Errorf or xerrors.Opaque` 31 | } 32 | 33 | func PublicFunc2() error { 34 | return xerrors.Errorf("wrap: %w", errFunc1()) // OK 35 | } 36 | 37 | func PublicFunc3() error { 38 | _, err := errFunc2() // want `wrap with xerrros.Errorf or xerrors.Opaque` 39 | return err 40 | } 41 | 42 | func PublicFunc4() error { 43 | _, err := errFunc2() // OK 44 | return xerrors.Errorf("wrap: %w", err) 45 | } 46 | 47 | func PublicFunc5() error { 48 | return sentinelErr // want `wrap with xerrros.Errorf or xerrors.Opaque` 49 | } 50 | 51 | func errFunc1() error { 52 | return xerrors.New("foo") 53 | } 54 | 55 | func errFunc2() (int, error) { 56 | return 0, xerrors.New("foo") 57 | } 58 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/README: -------------------------------------------------------------------------------- 1 | This repository holds the transition packages for the new Go 1.13 error values. 2 | See golang.org/design/29934-error-values. 3 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/adaptor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "bytes" 9 | "fmt" 10 | "io" 11 | "reflect" 12 | "strconv" 13 | ) 14 | 15 | // FormatError calls the FormatError method of f with an errors.Printer 16 | // configured according to s and verb, and writes the result to s. 17 | func FormatError(f Formatter, s fmt.State, verb rune) { 18 | // Assuming this function is only called from the Format method, and given 19 | // that FormatError takes precedence over Format, it cannot be called from 20 | // any package that supports errors.Formatter. It is therefore safe to 21 | // disregard that State may be a specific printer implementation and use one 22 | // of our choice instead. 23 | 24 | // limitations: does not support printing error as Go struct. 25 | 26 | var ( 27 | sep = " " // separator before next error 28 | p = &state{State: s} 29 | direct = true 30 | ) 31 | 32 | var err error = f 33 | 34 | switch verb { 35 | // Note that this switch must match the preference order 36 | // for ordinary string printing (%#v before %+v, and so on). 37 | 38 | case 'v': 39 | if s.Flag('#') { 40 | if stringer, ok := err.(fmt.GoStringer); ok { 41 | io.WriteString(&p.buf, stringer.GoString()) 42 | goto exit 43 | } 44 | // proceed as if it were %v 45 | } else if s.Flag('+') { 46 | p.printDetail = true 47 | sep = "\n - " 48 | } 49 | case 's': 50 | case 'q', 'x', 'X': 51 | // Use an intermediate buffer in the rare cases that precision, 52 | // truncation, or one of the alternative verbs (q, x, and X) are 53 | // specified. 54 | direct = false 55 | 56 | default: 57 | p.buf.WriteString("%!") 58 | p.buf.WriteRune(verb) 59 | p.buf.WriteByte('(') 60 | switch { 61 | case err != nil: 62 | p.buf.WriteString(reflect.TypeOf(f).String()) 63 | default: 64 | p.buf.WriteString("") 65 | } 66 | p.buf.WriteByte(')') 67 | io.Copy(s, &p.buf) 68 | return 69 | } 70 | 71 | loop: 72 | for { 73 | switch v := err.(type) { 74 | case Formatter: 75 | err = v.FormatError((*printer)(p)) 76 | case fmt.Formatter: 77 | v.Format(p, 'v') 78 | break loop 79 | default: 80 | io.WriteString(&p.buf, v.Error()) 81 | break loop 82 | } 83 | if err == nil { 84 | break 85 | } 86 | if p.needColon || !p.printDetail { 87 | p.buf.WriteByte(':') 88 | p.needColon = false 89 | } 90 | p.buf.WriteString(sep) 91 | p.inDetail = false 92 | p.needNewline = false 93 | } 94 | 95 | exit: 96 | width, okW := s.Width() 97 | prec, okP := s.Precision() 98 | 99 | if !direct || (okW && width > 0) || okP { 100 | // Construct format string from State s. 101 | format := []byte{'%'} 102 | if s.Flag('-') { 103 | format = append(format, '-') 104 | } 105 | if s.Flag('+') { 106 | format = append(format, '+') 107 | } 108 | if s.Flag(' ') { 109 | format = append(format, ' ') 110 | } 111 | if okW { 112 | format = strconv.AppendInt(format, int64(width), 10) 113 | } 114 | if okP { 115 | format = append(format, '.') 116 | format = strconv.AppendInt(format, int64(prec), 10) 117 | } 118 | format = append(format, string(verb)...) 119 | fmt.Fprintf(s, string(format), p.buf.String()) 120 | } else { 121 | io.Copy(s, &p.buf) 122 | } 123 | } 124 | 125 | var detailSep = []byte("\n ") 126 | 127 | // state tracks error printing state. It implements fmt.State. 128 | type state struct { 129 | fmt.State 130 | buf bytes.Buffer 131 | 132 | printDetail bool 133 | inDetail bool 134 | needColon bool 135 | needNewline bool 136 | } 137 | 138 | func (s *state) Write(b []byte) (n int, err error) { 139 | if s.printDetail { 140 | if len(b) == 0 { 141 | return 0, nil 142 | } 143 | if s.inDetail && s.needColon { 144 | s.needNewline = true 145 | if b[0] == '\n' { 146 | b = b[1:] 147 | } 148 | } 149 | k := 0 150 | for i, c := range b { 151 | if s.needNewline { 152 | if s.inDetail && s.needColon { 153 | s.buf.WriteByte(':') 154 | s.needColon = false 155 | } 156 | s.buf.Write(detailSep) 157 | s.needNewline = false 158 | } 159 | if c == '\n' { 160 | s.buf.Write(b[k:i]) 161 | k = i + 1 162 | s.needNewline = true 163 | } 164 | } 165 | s.buf.Write(b[k:]) 166 | if !s.inDetail { 167 | s.needColon = true 168 | } 169 | } else if !s.inDetail { 170 | s.buf.Write(b) 171 | } 172 | return len(b), nil 173 | } 174 | 175 | // printer wraps a state to implement an xerrors.Printer. 176 | type printer state 177 | 178 | func (s *printer) Print(args ...interface{}) { 179 | if !s.inDetail || s.printDetail { 180 | fmt.Fprint((*state)(s), args...) 181 | } 182 | } 183 | 184 | func (s *printer) Printf(format string, args ...interface{}) { 185 | if !s.inDetail || s.printDetail { 186 | fmt.Fprintf((*state)(s), format, args...) 187 | } 188 | } 189 | 190 | func (s *printer) Detail() bool { 191 | s.inDetail = true 192 | return s.printDetail 193 | } 194 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package xerrors implements functions to manipulate errors. 6 | // 7 | // This package supports transitioning to the Go 2 proposal for error values: 8 | // https://golang.org/design/29934-error-values 9 | // 10 | // Most of the functions and types in this package will be incorporated into the 11 | // standard library's errors package in Go 1.13; the behavior of this package's 12 | // Errorf function will be incorporated into the standard library's fmt.Errorf. 13 | // Use this package to get equivalent behavior in all supported Go versions. For 14 | // example, create errors using 15 | // 16 | // xerrors.New("write failed") 17 | // 18 | // or 19 | // 20 | // xerrors.Errorf("while reading: %v", err) 21 | // 22 | // If you want your error type to participate in the new formatting 23 | // implementation for %v and %+v, provide it with a Format method that calls 24 | // xerrors.FormatError, as shown in the example for FormatError. 25 | package xerrors // import "golang.org/x/xerrors" 26 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import "fmt" 8 | 9 | // errorString is a trivial implementation of error. 10 | type errorString struct { 11 | s string 12 | frame Frame 13 | } 14 | 15 | // New returns an error that formats as the given text. 16 | // 17 | // The returned error contains a Frame set to the caller's location and 18 | // implements Formatter to show this information when printed with details. 19 | func New(text string) error { 20 | return &errorString{text, Caller(1)} 21 | } 22 | 23 | func (e *errorString) Error() string { 24 | return e.s 25 | } 26 | 27 | func (e *errorString) Format(s fmt.State, v rune) { FormatError(e, s, v) } 28 | 29 | func (e *errorString) FormatError(p Printer) (next error) { 30 | p.Print(e.s) 31 | e.frame.Format(p) 32 | return nil 33 | } 34 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/fmt.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | 11 | "golang.org/x/xerrors/internal" 12 | ) 13 | 14 | // Errorf formats according to a format specifier and returns the string as a 15 | // value that satisfies error. 16 | // 17 | // The returned error includes the file and line number of the caller when 18 | // formatted with additional detail enabled. If the last argument is an error 19 | // the returned error's Format method will return it if the format string ends 20 | // with ": %s", ": %v", or ": %w". If the last argument is an error and the 21 | // format string ends with ": %w", the returned error implements Wrapper 22 | // with an Unwrap method returning it. 23 | func Errorf(format string, a ...interface{}) error { 24 | err, wrap := lastError(format, a) 25 | format = formatPlusW(format) 26 | if err == nil { 27 | return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)} 28 | } 29 | 30 | // TODO: this is not entirely correct. The error value could be 31 | // printed elsewhere in format if it mixes numbered with unnumbered 32 | // substitutions. With relatively small changes to doPrintf we can 33 | // have it optionally ignore extra arguments and pass the argument 34 | // list in its entirety. 35 | msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...) 36 | frame := Frame{} 37 | if internal.EnableTrace { 38 | frame = Caller(1) 39 | } 40 | if wrap { 41 | return &wrapError{msg, err, frame} 42 | } 43 | return &noWrapError{msg, err, frame} 44 | } 45 | 46 | // formatPlusW is used to avoid the vet check that will barf at %w. 47 | func formatPlusW(s string) string { 48 | return s 49 | } 50 | 51 | func lastError(format string, a []interface{}) (err error, wrap bool) { 52 | wrap = strings.HasSuffix(format, ": %w") 53 | if !wrap && 54 | !strings.HasSuffix(format, ": %s") && 55 | !strings.HasSuffix(format, ": %v") { 56 | return nil, false 57 | } 58 | 59 | if len(a) == 0 { 60 | return nil, false 61 | } 62 | 63 | err, ok := a[len(a)-1].(error) 64 | if !ok { 65 | return nil, false 66 | } 67 | 68 | return err, wrap 69 | } 70 | 71 | type noWrapError struct { 72 | msg string 73 | err error 74 | frame Frame 75 | } 76 | 77 | func (e *noWrapError) Error() string { 78 | return fmt.Sprint(e) 79 | } 80 | 81 | func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } 82 | 83 | func (e *noWrapError) FormatError(p Printer) (next error) { 84 | p.Print(e.msg) 85 | e.frame.Format(p) 86 | return e.err 87 | } 88 | 89 | type wrapError struct { 90 | msg string 91 | err error 92 | frame Frame 93 | } 94 | 95 | func (e *wrapError) Error() string { 96 | return fmt.Sprint(e) 97 | } 98 | 99 | func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) } 100 | 101 | func (e *wrapError) FormatError(p Printer) (next error) { 102 | p.Print(e.msg) 103 | e.frame.Format(p) 104 | return e.err 105 | } 106 | 107 | func (e *wrapError) Unwrap() error { 108 | return e.err 109 | } 110 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/format.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | // A Formatter formats error messages. 8 | type Formatter interface { 9 | error 10 | 11 | // FormatError prints the receiver's first error and returns the next error in 12 | // the error chain, if any. 13 | FormatError(p Printer) (next error) 14 | } 15 | 16 | // A Printer formats error messages. 17 | // 18 | // The most common implementation of Printer is the one provided by package fmt 19 | // during Printf (as of Go 1.13). Localization packages such as golang.org/x/text/message 20 | // typically provide their own implementations. 21 | type Printer interface { 22 | // Print appends args to the message output. 23 | Print(args ...interface{}) 24 | 25 | // Printf writes a formatted string. 26 | Printf(format string, args ...interface{}) 27 | 28 | // Detail reports whether error detail is requested. 29 | // After the first call to Detail, all text written to the Printer 30 | // is formatted as additional detail, or ignored when 31 | // detail has not been requested. 32 | // If Detail returns false, the caller can avoid printing the detail at all. 33 | Detail() bool 34 | } 35 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/frame.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "runtime" 9 | ) 10 | 11 | // A Frame contains part of a call stack. 12 | type Frame struct { 13 | // Make room for three PCs: the one we were asked for, what it called, 14 | // and possibly a PC for skipPleaseUseCallersFrames. See: 15 | // https://go.googlesource.com/go/+/032678e0fb/src/runtime/extern.go#169 16 | frames [3]uintptr 17 | } 18 | 19 | // Caller returns a Frame that describes a frame on the caller's stack. 20 | // The argument skip is the number of frames to skip over. 21 | // Caller(0) returns the frame for the caller of Caller. 22 | func Caller(skip int) Frame { 23 | var s Frame 24 | runtime.Callers(skip+1, s.frames[:]) 25 | return s 26 | } 27 | 28 | // location reports the file, line, and function of a frame. 29 | // 30 | // The returned function may be "" even if file and line are not. 31 | func (f Frame) location() (function, file string, line int) { 32 | frames := runtime.CallersFrames(f.frames[:]) 33 | if _, ok := frames.Next(); !ok { 34 | return "", "", 0 35 | } 36 | fr, ok := frames.Next() 37 | if !ok { 38 | return "", "", 0 39 | } 40 | return fr.Function, fr.File, fr.Line 41 | } 42 | 43 | // Format prints the stack as error detail. 44 | // It should be called from an error's Format implementation 45 | // after printing any other error detail. 46 | func (f Frame) Format(p Printer) { 47 | if p.Detail() { 48 | function, file, line := f.location() 49 | if function != "" { 50 | p.Printf("%s\n ", function) 51 | } 52 | if file != "" { 53 | p.Printf("%s:%d\n", file, line) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/go.mod: -------------------------------------------------------------------------------- 1 | module golang.org/x/xerrors 2 | 3 | go 1.11 4 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/internal/internal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package internal 6 | 7 | // EnableTrace indicates whether stack information should be recorded in errors. 8 | var EnableTrace = true 9 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/golang.org/x/xerrors/wrap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package xerrors 6 | 7 | import ( 8 | "reflect" 9 | ) 10 | 11 | // A Wrapper provides context around another error. 12 | type Wrapper interface { 13 | // Unwrap returns the next error in the error chain. 14 | // If there is no next error, Unwrap returns nil. 15 | Unwrap() error 16 | } 17 | 18 | // Opaque returns an error with the same error formatting as err 19 | // but that does not match err and cannot be unwrapped. 20 | func Opaque(err error) error { 21 | return noWrapper{err} 22 | } 23 | 24 | type noWrapper struct { 25 | error 26 | } 27 | 28 | func (e noWrapper) FormatError(p Printer) (next error) { 29 | if f, ok := e.error.(Formatter); ok { 30 | return f.FormatError(p) 31 | } 32 | p.Print(e.error) 33 | return nil 34 | } 35 | 36 | // Unwrap returns the result of calling the Unwrap method on err, if err implements 37 | // Unwrap. Otherwise, Unwrap returns nil. 38 | func Unwrap(err error) error { 39 | u, ok := err.(Wrapper) 40 | if !ok { 41 | return nil 42 | } 43 | return u.Unwrap() 44 | } 45 | 46 | // Is reports whether any error in err's chain matches target. 47 | // 48 | // An error is considered to match a target if it is equal to that target or if 49 | // it implements a method Is(error) bool such that Is(target) returns true. 50 | func Is(err, target error) bool { 51 | if target == nil { 52 | return err == target 53 | } 54 | for { 55 | if err == target { 56 | return true 57 | } 58 | if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) { 59 | return true 60 | } 61 | // TODO: consider supporing target.Is(err). This would allow 62 | // user-definable predicates, but also may allow for coping with sloppy 63 | // APIs, thereby making it easier to get away with them. 64 | if err = Unwrap(err); err == nil { 65 | return false 66 | } 67 | } 68 | } 69 | 70 | // As finds the first error in err's chain that matches the type to which target 71 | // points, and if so, sets the target to its value and returns true. An error 72 | // matches a type if it is assignable to the target type, or if it has a method 73 | // As(interface{}) bool such that As(target) returns true. As will panic if target 74 | // is not a non-nil pointer to a type which implements error or is of interface type. 75 | // 76 | // The As method should set the target to its value and return true if err 77 | // matches the type to which target points. 78 | func As(err error, target interface{}) bool { 79 | if target == nil { 80 | panic("errors: target cannot be nil") 81 | } 82 | val := reflect.ValueOf(target) 83 | typ := val.Type() 84 | if typ.Kind() != reflect.Ptr || val.IsNil() { 85 | panic("errors: target must be a non-nil pointer") 86 | } 87 | if e := typ.Elem(); e.Kind() != reflect.Interface && !e.Implements(errorType) { 88 | panic("errors: *target must be interface or implement error") 89 | } 90 | targetType := typ.Elem() 91 | for { 92 | if reflect.TypeOf(err).AssignableTo(targetType) { 93 | val.Elem().Set(reflect.ValueOf(err)) 94 | return true 95 | } 96 | if x, ok := err.(interface{ As(interface{}) bool }); ok && x.As(target) { 97 | return true 98 | } 99 | if err = Unwrap(err); err == nil { 100 | return false 101 | } 102 | } 103 | } 104 | 105 | var errorType = reflect.TypeOf((*error)(nil)).Elem() 106 | -------------------------------------------------------------------------------- /passes/wrapping/testdata/src/a/vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3 2 | golang.org/x/xerrors 3 | golang.org/x/xerrors/internal 4 | -------------------------------------------------------------------------------- /passes/wrapping/wrapping.go: -------------------------------------------------------------------------------- 1 | package wrapping 2 | 3 | import ( 4 | "fmt" 5 | "go/token" 6 | "go/types" 7 | "strings" 8 | "unicode" 9 | 10 | "golang.org/x/tools/go/analysis/passes/buildssa" 11 | "golang.org/x/tools/go/ssa" 12 | 13 | "golang.org/x/tools/go/analysis" 14 | ) 15 | 16 | var scope string 17 | var errType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) 18 | 19 | var Analyzer = &analysis.Analyzer{ 20 | Name: "wrapping", 21 | Doc: Doc, 22 | Run: run, 23 | Requires: []*analysis.Analyzer{ 24 | buildssa.Analyzer, 25 | }, 26 | } 27 | 28 | const Doc = "wrapping detect unwrapped error" 29 | const xerrorsPath = "golang.org/x/xerrors" 30 | const scopeAll = "all" 31 | const scopePublic = "public" 32 | 33 | func init() { 34 | Analyzer.Flags.StringVar(&scope, "scope", scopeAll, "scope of checking (public, all)") 35 | } 36 | 37 | func run(pass *analysis.Pass) (interface{}, error) { 38 | err := checkFlags() 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | srcFuncs := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA).SrcFuncs 44 | for _, srcFunc := range srcFuncs { 45 | positions := wrappingErrPositions(pass, srcFunc) 46 | for _, pos := range positions { 47 | pass.Reportf(pos, "wrap with xerrros.Errorf or xerrors.Opaque") 48 | } 49 | } 50 | 51 | return nil, nil 52 | } 53 | 54 | func checkFlags() error { 55 | if scope == scopeAll || scope == scopePublic { 56 | return nil 57 | } 58 | return fmt.Errorf("unknown scope '%s'", scope) 59 | } 60 | 61 | func wrappingErrPositions(pass *analysis.Pass, srcFunc *ssa.Function) []token.Pos { 62 | if scope == scopePublic && isPrivate(srcFunc) { 63 | return nil 64 | } 65 | 66 | if !isReturningErr(srcFunc) { 67 | return nil 68 | } 69 | 70 | var positions []token.Pos 71 | for _, block := range srcFunc.Blocks { 72 | for _, instr := range block.Instrs { 73 | val, ok := instr.(ssa.Value) 74 | if !ok { 75 | continue 76 | } 77 | 78 | if !isRange(val) && isErr(val.Type()) && !isCallingXerrors(val) && !isCallingXerrorsImplicitly(val) && isReachToReturn(val) { 79 | positions = append(positions, convertToOriginVal(val).Pos()) 80 | } 81 | } 82 | } 83 | 84 | return positions 85 | } 86 | 87 | func isRange(val ssa.Value) bool { 88 | _, ok := val.(*ssa.Range) 89 | return ok 90 | } 91 | 92 | func isPrivate(function *ssa.Function) bool { 93 | if function.Parent() != nil { 94 | return isPrivate(function.Parent()) 95 | } 96 | 97 | name := function.Name() 98 | return unicode.IsLower(rune(name[0])) 99 | } 100 | 101 | func isCallingXerrorsImplicitly(val ssa.Value) bool { 102 | phi, ok := val.(*ssa.Phi) 103 | if !ok { 104 | return false 105 | } 106 | 107 | for _, edge := range phi.Edges { 108 | if !isCallingXerrors(edge) { 109 | return false 110 | } 111 | } 112 | return true 113 | } 114 | 115 | func isCallingXerrors(val ssa.Value) bool { 116 | call, ok := val.(*ssa.Call) 117 | if !ok { 118 | return false 119 | } 120 | 121 | f := call.Common().StaticCallee() 122 | if f == nil { 123 | return false 124 | } 125 | 126 | return removeVendor(f.Pkg.Pkg.Path()) == xerrorsPath 127 | } 128 | 129 | func removeVendor(path string) string { 130 | s := strings.Split(path, "/") 131 | for i := range s { 132 | if s[i] == "vendor" { 133 | return strings.Join(s[i+1:], "/") 134 | } 135 | } 136 | return path 137 | } 138 | 139 | func isReachToReturn(val ssa.Value) bool { 140 | for _, ref := range *val.Referrers() { 141 | _, ok := ref.(*ssa.Return) 142 | if ok { 143 | return true 144 | } 145 | } 146 | return false 147 | } 148 | 149 | func isReturningErr(srcFunc *ssa.Function) bool { 150 | results := srcFunc.Signature.Results() 151 | for i := 0; i < results.Len(); i++ { 152 | v := results.At(i) 153 | if isErr(v.Type()) { 154 | return true 155 | } 156 | } 157 | return false 158 | } 159 | 160 | func convertToOriginVal(val ssa.Value) ssa.Value { 161 | switch v := val.(type) { 162 | case *ssa.Extract: 163 | return v.Tuple 164 | case *ssa.MakeInterface: 165 | if val.Pos() != 0 { 166 | return val 167 | } 168 | return v.X 169 | } 170 | return val 171 | } 172 | 173 | func isErr(v types.Type) bool { 174 | return types.AssignableTo(v, errType) 175 | } 176 | -------------------------------------------------------------------------------- /passes/wrapping/wrapping_test.go: -------------------------------------------------------------------------------- 1 | package wrapping_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/sachaos/xerrchk/passes/wrapping" 7 | "golang.org/x/tools/go/analysis/analysistest" 8 | ) 9 | 10 | func TestWrapping(t *testing.T) { 11 | testdata := analysistest.TestData() 12 | wrapping.Analyzer.Flags.Set("scope", "public") 13 | analysistest.Run(t, testdata, wrapping.Analyzer, "a") 14 | } 15 | 16 | func TestPublicOption(t *testing.T) { 17 | testdata := analysistest.TestData() 18 | wrapping.Analyzer.Flags.Set("scope", "public") 19 | analysistest.Run(t, testdata, wrapping.Analyzer, "a/option/public") 20 | } 21 | 22 | func TestAllOption(t *testing.T) { 23 | testdata := analysistest.TestData() 24 | wrapping.Analyzer.Flags.Set("scope", "all") 25 | analysistest.Run(t, testdata, wrapping.Analyzer, "a/option/all") 26 | } 27 | --------------------------------------------------------------------------------