Remove vendoring

This commit is contained in:
nakabonne 2020-04-22 08:58:24 +09:00
parent 9442a4132c
commit 37f0e44dfa
6 changed files with 0 additions and 331 deletions

View File

@ -1,16 +0,0 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
/nestif
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/

View File

@ -1,25 +0,0 @@
BSD 2-Clause License
Copyright (c) 2020, Ryo Nakao
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,122 +0,0 @@
# nestif
[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/nakabonne/nestif)
Reports deeply nested if statements in Go code, by calculating its complexities based on the rules defined by the [Cognitive Complexity white paper by G. Ann Campbell](https://www.sonarsource.com/docs/CognitiveComplexity.pdf).
It helps you find if statements that make your code hard to read, and clarifies which parts to refactor.
## Installation
```
go get github.com/nakabonne/nestif/cmd/nestif
```
## Usage
### Quick Start
```bash
nestif
```
The `...` glob operator is supported, and the above is an equivalent of:
```bash
nestif ./...
```
One or more files and directories can be specified in a single command:
```bash
nestif dir/foo.go dir2 dir3/...
```
Packages can be specified as well:
```bash
nestif github.com/foo/bar example.com/bar/baz
```
### Options
```
usage: nestif [<flag> ...] <Go files or directories or packages> ...
-e, --exclude-dirs strings regexps of directories to be excluded for checking; comma-separated list
--json emit json format
--min int minimum complexity to show (default 1)
--top int show only the top N most complex if statements (default 10)
-v, --verbose verbose output
```
### Example
Let's say you write:
```go
package main
func _() {
if foo {
if bar {
}
}
if baz == "baz" {
if qux {
if quux {
}
}
}
}
```
And give it to nestif:
```console
$ nestif foo.go
foo.go:9:2: `if baz == "baz"` is nested (complexity: 3)
foo.go:4:2: `if foo` is nested (complexity: 1)
```
Note that the results are sorted in descending order of complexity. In addition, it shows only the top 10 most complex if statements by default, and you can specify how many to show with `-top` flag.
### Rules
It calculates the complexities of if statements according to the nesting rules of Cognitive Complexity.
Since the more deeply-nested your code gets, the harder it can be to reason about, it assesses a nesting increment for it:
```go
if condition1 {
if condition2 { // +1
if condition3 { // +2
if condition4 { // +3
}
}
}
}
```
`else` and `else if` increase complexity by one wherever they are because the mental cost has already been paid when reading the if:
```go
if condition1 {
if condition2 { // +1
if condition3 { // +2
} else if condition4 { // +1
} else { // +1
if condition5 { // +3
}
}
}
}
```
## Inspired by
- [uudashr/gocognit](https://github.com/uudashr/gocognit)
- [fzipp/gocyclo](https://github.com/fzipp/gocyclo)
## Further reading
Please see the [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf) white paper by G. Ann Campbell for more detail on Cognitive Complexity.

View File

@ -1,8 +0,0 @@
module github.com/nakabonne/nestif
go 1.13
require (
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.4.0
)

View File

@ -1,12 +0,0 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,148 +0,0 @@
// Copyright 2020 Ryo Nakao <nakabonne@gmail.com>.
//
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package nestif provides an API to detect deeply nested if statements.
package nestif
import (
"bytes"
"fmt"
"go/ast"
"go/printer"
"go/token"
"io"
)
// Issue represents an issue of root if statement that has nested ifs.
type Issue struct {
Pos token.Position
Complexity int
Message string
}
// Checker represents a checker that finds nested if statements.
type Checker struct {
// Minimum complexity to report.
MinComplexity int
// For debug mode.
debugWriter io.Writer
issues []Issue
}
// Check inspects a single file and returns found issues.
func (c *Checker) Check(f *ast.File, fset *token.FileSet) []Issue {
c.issues = []Issue{} // refresh
ast.Inspect(f, func(n ast.Node) bool {
fn, ok := n.(*ast.FuncDecl)
if !ok || fn.Body == nil {
return true
}
for _, stmt := range fn.Body.List {
c.checkFunc(&stmt, fset)
}
return true
})
return c.issues
}
// checkFunc inspects a function and sets a list of issues if there are.
func (c *Checker) checkFunc(stmt *ast.Stmt, fset *token.FileSet) {
ast.Inspect(*stmt, func(n ast.Node) bool {
ifStmt, ok := n.(*ast.IfStmt)
if !ok {
return true
}
c.checkIf(ifStmt, fset)
return false
})
}
// checkIf inspects a if statement and sets an issue if there is.
func (c *Checker) checkIf(stmt *ast.IfStmt, fset *token.FileSet) {
v := newVisitor()
ast.Walk(v, stmt)
if v.complexity < c.MinComplexity {
return
}
pos := fset.Position(stmt.Pos())
c.issues = append(c.issues, Issue{
Pos: pos,
Complexity: v.complexity,
Message: c.makeMessage(v.complexity, stmt.Cond, fset),
})
}
type visitor struct {
complexity int
nesting int
// To avoid adding complexity including nesting level to `else if`.
elseifs map[*ast.IfStmt]bool
}
func newVisitor() *visitor {
return &visitor{
elseifs: make(map[*ast.IfStmt]bool),
}
}
// Visit traverses an AST in depth-first order by calling itself
// recursively, and calculates the complexities of if statements.
func (v *visitor) Visit(n ast.Node) ast.Visitor {
ifStmt, ok := n.(*ast.IfStmt)
if !ok {
return v
}
v.incComplexity(ifStmt)
v.nesting++
ast.Walk(v, ifStmt.Body)
v.nesting--
switch t := ifStmt.Else.(type) {
case *ast.BlockStmt:
v.complexity++
v.nesting++
ast.Walk(v, t)
v.nesting--
case *ast.IfStmt:
v.elseifs[t] = true
ast.Walk(v, t)
}
return nil
}
func (v *visitor) incComplexity(n *ast.IfStmt) {
// In case of `else if`, increase by 1.
if v.elseifs[n] {
v.complexity++
} else {
v.complexity += v.nesting
}
}
func (c *Checker) makeMessage(complexity int, cond ast.Expr, fset *token.FileSet) string {
p := &printer.Config{}
b := new(bytes.Buffer)
if err := p.Fprint(b, fset, cond); err != nil {
c.debug("failed to convert condition into string: %v", err)
}
return fmt.Sprintf("`if %s` is deeply nested (complexity: %d)", b.String(), complexity)
}
// DebugMode makes it possible to emit debug logs.
func (c *Checker) DebugMode(w io.Writer) {
c.debugWriter = w
}
func (c *Checker) debug(format string, a ...interface{}) {
if c.debugWriter != nil {
fmt.Fprintf(c.debugWriter, format, a...)
}
}