simple

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 25, 2021 License: MIT Imports: 22 Imported by: 234

Documentation

Overview

Package simple contains a linter for Go source code.

Index

Constants

This section is empty.

Variables

View Source
var Analyzers = lint.InitializeAnalyzers(Docs, map[string]*analysis.Analyzer{
	"S1000": {
		Run:      CheckSingleCaseSelect,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1001": {
		Run:      CheckLoopCopy,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1002": {
		Run:      CheckIfBoolCmp,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1003": {
		Run:      CheckStringsContains,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1004": {
		Run:      CheckBytesCompare,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1005": {
		Run:      CheckUnnecessaryBlank,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1006": {
		Run:      CheckForTrue,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1007": {
		Run:      CheckRegexpRaw,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1008": {
		Run:      CheckIfReturn,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1009": {
		Run:      CheckRedundantNilCheckWithLen,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1010": {
		Run:      CheckSlicing,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1011": {
		Run:      CheckLoopAppend,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1012": {
		Run:      CheckTimeSince,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1016": {
		Run:      CheckSimplerStructConversion,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1017": {
		Run:      CheckTrim,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1018": {
		Run:      CheckLoopSlide,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1019": {
		Run:      CheckMakeLenCap,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1020": {
		Run:      CheckAssertNotNil,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1021": {
		Run:      CheckDeclareAssign,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1023": {
		Run:      CheckRedundantBreak,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1024": {
		Run:      CheckTimeUntil,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1025": {
		Run:      CheckRedundantSprintf,
		Requires: []*analysis.Analyzer{buildir.Analyzer, inspect.Analyzer, facts.Generated},
	},
	"S1028": {
		Run:      CheckErrorsNewSprintf,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1029": {
		Run:      CheckRangeStringRunes,
		Requires: []*analysis.Analyzer{buildir.Analyzer},
	},
	"S1030": {
		Run:      CheckBytesBufferConversions,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1031": {
		Run:      CheckNilCheckAroundRange,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1032": {
		Run:      CheckSortHelpers,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1033": {
		Run:      CheckGuardedDelete,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1034": {
		Run:      CheckSimplifyTypeSwitch,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1035": {
		Run:      CheckRedundantCanonicalHeaderKey,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1036": {
		Run:      CheckUnnecessaryGuard,
		Requires: []*analysis.Analyzer{inspect.Analyzer},
	},
	"S1037": {
		Run:      CheckElaborateSleep,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1038": {
		Run:      CheckPrintSprintf,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1039": {
		Run:      CheckSprintLiteral,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
	"S1040": {
		Run:      CheckSameTypeTypeAssertion,
		Requires: []*analysis.Analyzer{inspect.Analyzer, facts.Generated},
	},
})
View Source
var Docs = lint.Markdownify(map[string]*lint.Documentation{
	"S1000": {
		Title: `Use plain channel send or receive instead of single-case select`,
		Text: `Select statements with a single case can be replaced with a simple
send or receive.

Before:

    select {
    case x := <-ch:
        fmt.Println(x)
    }

After:

    x := <-ch
    fmt.Println(x)`,
		Since: "2017.1",
	},

	"S1001": {
		Title: `Replace for loop with call to copy`,
		Text: `Use \'copy()\' for copying elements from one slice to another.

Before:

    for i, x := range src {
        dst[i] = x
    }

After:

    copy(dst, src)`,
		Since: "2017.1",
	},

	"S1002": {
		Title: `Omit comparison with boolean constant`,
		Text: `Before:

    if x == true {}

After:

    if x {}`,
		Since: "2017.1",
	},

	"S1003": {
		Title: "Replace call to `strings.Index` with `strings.Contains`",
		Text: `Before:

    if strings.Index(x, y) != -1 {}

After:

    if strings.Contains(x, y) {}`,
		Since: "2017.1",
	},

	"S1004": {
		Title: "Replace call to `bytes.Compare` with `bytes.Equal`",
		Text: `Before:

    if bytes.Compare(x, y) == 0 {}

After:

    if bytes.Equal(x, y) {}`,
		Since: "2017.1",
	},

	"S1005": {
		Title: `Drop unnecessary use of the blank identifier`,
		Text: `In many cases, assigning to the blank identifier is unnecessary.

Before:

    for _ = range s {}
    x, _ = someMap[key]
    _ = <-ch

After:

    for range s{}
    x = someMap[key]
    <-ch`,
		Since: "2017.1",
	},

	"S1006": {
		Title: "Use `for { ... }` for infinite loops",
		Text:  `For infinite loops, using \'for { ... }\' is the most idiomatic choice.`,
		Since: "2017.1",
	},

	"S1007": {
		Title: `Simplify regular expression by using raw string literal`,
		Text: `Raw string literals use \' instead of " and do not support
any escape sequences. This means that the backslash (\'\\') can be used
freely, without the need of escaping.

Since regular expressions have their own escape sequences, raw strings
can improve their readability.

Before:

    regexp.Compile("\\A(\\w+) profile: total \\d+\\n\\z")

After:

    regexp.Compile(` + "`" + `\A(\w+) profile: total \d+\n\z` + "`" + `)`,
		Since: "2017.1",
	},

	"S1008": {
		Title: `Simplify returning boolean expression`,
		Text: `Before:

    if <expr> {
        return true
    }
    return false

After:

    return <expr>`,
		Since: "2017.1",
	},

	"S1009": {
		Title: `Omit redundant nil check on slices`,
		Text: `The \'len\' function is defined for all slices, even nil ones, which have
a length of zero. It is not necessary to check if a slice is not nil
before checking that its length is not zero.

Before:

    if x != nil && len(x) != 0 {}

After:

    if len(x) != 0 {}`,
		Since: "2017.1",
	},

	"S1010": {
		Title: `Omit default slice index`,
		Text: `When slicing, the second index defaults to the length of the value,
making \'s[n:len(s)]\' and \'s[n:]\' equivalent.`,
		Since: "2017.1",
	},

	"S1011": {
		Title: "Use a single `append` to concatenate two slices",
		Text: `Before:

    for _, e := range y {
        x = append(x, e)
    }

After:

    x = append(x, y...)`,
		Since: "2017.1",
	},

	"S1012": {
		Title: "Replace `time.Now().Sub(x)` with `time.Since(x)`",
		Text: `The \'time.Since\' helper has the same effect as using \'time.Now().Sub(x)\'
but is easier to read.

Before:

    time.Now().Sub(x)

After:

    time.Since(x)`,
		Since: "2017.1",
	},

	"S1016": {
		Title: `Use a type conversion instead of manually copying struct fields`,
		Text: `Two struct types with identical fields can be converted between each
other. In older versions of Go, the fields had to have identical
struct tags. Since Go 1.8, however, struct tags are ignored during
conversions. It is thus not necessary to manually copy every field
individually.

Before:

    var x T1
    y := T2{
        Field1: x.Field1,
        Field2: x.Field2,
    }

After:

    var x T1
    y := T2(x)`,
		Since: "2017.1",
	},

	"S1017": {
		Title: "Replace manual trimming with `strings.TrimPrefix`",
		Text: `Instead of using \'strings.HasPrefix\' and manual slicing, use the
\'strings.TrimPrefix\' function. If the string doesn't start with the
prefix, the original string will be returned. Using \'strings.TrimPrefix\'
reduces complexity, and avoids common bugs, such as off-by-one
mistakes.

Before:

    if strings.HasPrefix(str, prefix) {
        str = str[len(prefix):]
    }

After:

    str = strings.TrimPrefix(str, prefix)`,
		Since: "2017.1",
	},

	"S1018": {
		Title: "Use `copy` for sliding elements",
		Text: `\'copy()\' permits using the same source and destination slice, even with
overlapping ranges. This makes it ideal for sliding elements in a
slice.

Before:

    for i := 0; i < n; i++ {
        bs[i] = bs[offset+i]
    }

After:

    copy(bs[:n], bs[offset:])`,
		Since: "2017.1",
	},

	"S1019": {
		Title: "Simplify `make` call by omitting redundant arguments",
		Text: `The \'make\' function has default values for the length and capacity
arguments. For channels and maps, the length defaults to zero.
Additionally, for slices the capacity defaults to the length.`,
		Since: "2017.1",
	},

	"S1020": {
		Title: `Omit redundant nil check in type assertion`,
		Text: `Before:

    if _, ok := i.(T); ok && i != nil {}

After:

    if _, ok := i.(T); ok {}`,
		Since: "2017.1",
	},

	"S1021": {
		Title: `Merge variable declaration and assignment`,
		Text: `Before:

    var x uint
    x = 1

After:

    var x uint = 1`,
		Since: "2017.1",
	},

	"S1023": {
		Title: `Omit redundant control flow`,
		Text: `Functions that have no return value do not need a return statement as
the final statement of the function.

Switches in Go do not have automatic fallthrough, unlike languages
like C. It is not necessary to have a break statement as the final
statement in a case block.`,
		Since: "2017.1",
	},

	"S1024": {
		Title: "Replace `x.Sub(time.Now())` with `time.Until(x)`",
		Text: `The \'time.Until\' helper has the same effect as using \'x.Sub(time.Now())\'
but is easier to read.

Before:

    x.Sub(time.Now())

After:

    time.Until(x)`,
		Since: "2017.1",
	},

	"S1025": {
		Title: "Don't use `fmt.Sprintf(\"%s\", x)` unnecessarily",
		Text: `In many instances, there are easier and more efficient ways of getting
a value's string representation. Whenever a value's underlying type is
a string already, or the type has a String method, they should be used
directly.

Given the following shared definitions

    type T1 string
    type T2 int

    func (T2) String() string { return "Hello, world" }

    var x string
    var y T1
    var z T2

we can simplify the following

    fmt.Sprintf("%s", x)
    fmt.Sprintf("%s", y)
    fmt.Sprintf("%s", z)

to

    x
    string(y)
    z.String()`,
		Since: "2017.1",
	},

	"S1028": {
		Title: "Simplify error construction with `fmt.Errorf`",
		Text: `Before:

    errors.New(fmt.Sprintf(...))

After:

    fmt.Errorf(...)`,
		Since: "2017.1",
	},

	"S1029": {
		Title: `Range over the string directly`,
		Text: `Ranging over a string will yield byte offsets and runes. If the offset
isn't used, this is functionally equivalent to converting the string
to a slice of runes and ranging over that. Ranging directly over the
string will be more performant, however, as it avoids allocating a new
slice, the size of which depends on the length of the string.

Before:

    for _, r := range []rune(s) {}

After:

    for _, r := range s {}`,
		Since: "2017.1",
	},

	"S1030": {
		Title: "Use `bytes.Buffer.String` or `bytes.Buffer.Bytes`",
		Text: `\'bytes.Buffer\' has both a \'String\' and a \'Bytes\' method. It is almost never
necessary to use \'string(buf.Bytes())\' or \'[]byte(buf.String())\' – simply
use the other method.

The only exception to this are map lookups. Due to a compiler optimization,
\'m[string(buf.Bytes())]\' is more efficient than \'m[buf.String()]\'.
`,
		Since: "2017.1",
	},

	"S1031": {
		Title: `Omit redundant nil check around loop`,
		Text: `You can use range on nil slices and maps, the loop will simply never
execute. This makes an additional nil check around the loop
unnecessary.

Before:

    if s != nil {
        for _, x := range s {
            ...
        }
    }

After:

    for _, x := range s {
        ...
    }`,
		Since: "2017.1",
	},

	"S1032": {
		Title: "Use `sort.Ints(x)`, `sort.Float64s(x)`, and `sort.Strings(x)`",
		Text: `The \'sort.Ints\', \'sort.Float64s\' and \'sort.Strings\' functions are easier to
read than \'sort.Sort(sort.IntSlice(x))\', \'sort.Sort(sort.Float64Slice(x))\'
and \'sort.Sort(sort.StringSlice(x))\'.

Before:

    sort.Sort(sort.StringSlice(x))

After:

    sort.Strings(x)`,
		Since: "2019.1",
	},

	"S1033": {
		Title: "Unnecessary guard around call to `delete`",
		Text:  `Calling \'delete\' on a nil map is a no-op.`,
		Since: "2019.2",
	},

	"S1034": {
		Title: `Use result of type assertion to simplify cases`,
		Since: "2019.2",
	},

	"S1035": {
		Title: "Redundant call to `net/http.CanonicalHeaderKey` in method call on `net/http.Header`",
		Text: `The methods on \'net/http.Header\', namely \'Add\', \'Del\', \'Get\' and \'Set\', already
canonicalize the given header name.`,
		Since: "2020.1",
	},

	"S1036": {
		Title: `Unnecessary guard around map access`,

		Text: `When accessing a map key that doesn't exist yet, one
receives a zero value. Often, the zero value is a suitable value, for example when using append or doing integer math.

The following

    if _, ok := m["foo"]; ok {
        m["foo"] = append(m["foo"], "bar")
    } else {
        m["foo"] = []string{"bar"}
    }

can be simplified to

    m["foo"] = append(m["foo"], "bar")

and

    if _, ok := m2["k"]; ok {
        m2["k"] += 4
    } else {
        m2["k"] = 4
    }

can be simplified to

    m["k"] += 4
`,
		Since: "2020.1",
	},

	"S1037": {
		Title: `Elaborate way of sleeping`,
		Text: `Using a select statement with a single case receiving
from the result of \'time.After\' is a very elaborate way of sleeping that
can much simpler be expressed with a simple call to time.Sleep.`,
		Since: "2020.1",
	},

	"S1038": {
		Title: "Unnecessarily complex way of printing formatted string",
		Text:  `Instead of using \'fmt.Print(fmt.Sprintf(...))\', one can use \'fmt.Printf(...)\'.`,
		Since: "2020.1",
	},

	"S1039": {
		Title: "Unnecessary use of `fmt.Sprint`",
		Text:  `Calling \'fmt.Sprint\' with a single string argument is unnecessary and identical to using the string directly.`,
		Since: "2020.1",
	},
	"S1040": {
		Title: "Type assertion to current type",
		Text: `The type assertion \'x.(SomeInterface)\', when \'x\' already has type
\'SomeInterface\', can only fail if \'x\' is nil. Usually, this is
left-over code from when \'x\' had a different type and you can safely
delete the type assertion. If you want to check that \'x\' is not nil,
consider being explicit and using an actual \'if x == nil\' comparison
instead of relying on the type assertion panicking.`,
		Since: "2021.1",
	},
})

Functions

func CheckAssertNotNil

func CheckAssertNotNil(pass *analysis.Pass) (interface{}, error)

func CheckBytesBufferConversions

func CheckBytesBufferConversions(pass *analysis.Pass) (interface{}, error)

func CheckBytesCompare

func CheckBytesCompare(pass *analysis.Pass) (interface{}, error)

func CheckDeclareAssign

func CheckDeclareAssign(pass *analysis.Pass) (interface{}, error)

func CheckElaborateSleep

func CheckElaborateSleep(pass *analysis.Pass) (interface{}, error)

func CheckErrorsNewSprintf

func CheckErrorsNewSprintf(pass *analysis.Pass) (interface{}, error)

func CheckForTrue

func CheckForTrue(pass *analysis.Pass) (interface{}, error)

func CheckGuardedDelete

func CheckGuardedDelete(pass *analysis.Pass) (interface{}, error)

func CheckIfBoolCmp

func CheckIfBoolCmp(pass *analysis.Pass) (interface{}, error)

func CheckIfReturn

func CheckIfReturn(pass *analysis.Pass) (interface{}, error)

func CheckLoopAppend

func CheckLoopAppend(pass *analysis.Pass) (interface{}, error)

func CheckLoopCopy

func CheckLoopCopy(pass *analysis.Pass) (interface{}, error)

func CheckLoopSlide

func CheckLoopSlide(pass *analysis.Pass) (interface{}, error)

func CheckMakeLenCap

func CheckMakeLenCap(pass *analysis.Pass) (interface{}, error)

func CheckNilCheckAroundRange

func CheckNilCheckAroundRange(pass *analysis.Pass) (interface{}, error)

func CheckPrintSprintf

func CheckPrintSprintf(pass *analysis.Pass) (interface{}, error)

func CheckRangeStringRunes

func CheckRangeStringRunes(pass *analysis.Pass) (interface{}, error)

func CheckRedundantBreak

func CheckRedundantBreak(pass *analysis.Pass) (interface{}, error)

func CheckRedundantCanonicalHeaderKey

func CheckRedundantCanonicalHeaderKey(pass *analysis.Pass) (interface{}, error)

func CheckRedundantNilCheckWithLen

func CheckRedundantNilCheckWithLen(pass *analysis.Pass) (interface{}, error)

CheckRedundantNilCheckWithLen checks for the following redundant nil-checks:

if x == nil || len(x) == 0 {}
if x != nil && len(x) != 0 {}
if x != nil && len(x) == N {} (where N != 0)
if x != nil && len(x) > N {}
if x != nil && len(x) >= N {} (where N != 0)

func CheckRedundantSprintf

func CheckRedundantSprintf(pass *analysis.Pass) (interface{}, error)

func CheckRegexpRaw

func CheckRegexpRaw(pass *analysis.Pass) (interface{}, error)

func CheckSameTypeTypeAssertion added in v0.2.0

func CheckSameTypeTypeAssertion(pass *analysis.Pass) (interface{}, error)

func CheckSimplerStructConversion

func CheckSimplerStructConversion(pass *analysis.Pass) (interface{}, error)

func CheckSimplifyTypeSwitch

func CheckSimplifyTypeSwitch(pass *analysis.Pass) (interface{}, error)

func CheckSingleCaseSelect

func CheckSingleCaseSelect(pass *analysis.Pass) (interface{}, error)

func CheckSlicing

func CheckSlicing(pass *analysis.Pass) (interface{}, error)

func CheckSortHelpers

func CheckSortHelpers(pass *analysis.Pass) (interface{}, error)

func CheckSprintLiteral

func CheckSprintLiteral(pass *analysis.Pass) (interface{}, error)

func CheckStringsContains

func CheckStringsContains(pass *analysis.Pass) (interface{}, error)

func CheckTimeSince

func CheckTimeSince(pass *analysis.Pass) (interface{}, error)

func CheckTimeUntil

func CheckTimeUntil(pass *analysis.Pass) (interface{}, error)

func CheckTrim

func CheckTrim(pass *analysis.Pass) (interface{}, error)

func CheckUnnecessaryBlank

func CheckUnnecessaryBlank(pass *analysis.Pass) (interface{}, error)

func CheckUnnecessaryGuard

func CheckUnnecessaryGuard(pass *analysis.Pass) (interface{}, error)

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL