github.com/elek/golangci-lint@v1.42.2-0.20211208090441-c05b7fcb3a9a/pkg/config/issues.go (about) 1 package config 2 3 import ( 4 "fmt" 5 "regexp" 6 ) 7 8 const excludeRuleMinConditionsCount = 2 9 10 var DefaultExcludePatterns = []ExcludePattern{ 11 { 12 ID: "EXC0001", 13 Pattern: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close" + 14 "|.*Flush|os\\.Remove(All)?|.*print(f|ln)?|os\\.(Un)?Setenv). is not checked", 15 Linter: "errcheck", 16 Why: "Almost all programs ignore errors on these functions and in most cases it's ok", 17 }, 18 { 19 ID: "EXC0002", 20 Pattern: "(comment on exported (method|function|type|const)|" + 21 "should have( a package)? comment|comment should be of the form)", 22 Linter: "golint", 23 Why: "Annoying issue about not having a comment. The rare codebase has such comments", 24 }, 25 { 26 ID: "EXC0003", 27 Pattern: "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this", 28 Linter: "golint", 29 Why: "False positive when tests are defined in package 'test'", 30 }, 31 { 32 ID: "EXC0004", 33 Pattern: "(possible misuse of unsafe.Pointer|should have signature)", 34 Linter: "govet", 35 Why: "Common false positives", 36 }, 37 { 38 ID: "EXC0005", 39 Pattern: "ineffective break statement. Did you mean to break out of the outer loop", 40 Linter: "staticcheck", 41 Why: "Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore", 42 }, 43 { 44 ID: "EXC0006", 45 Pattern: "Use of unsafe calls should be audited", 46 Linter: "gosec", 47 Why: "Too many false-positives on 'unsafe' usage", 48 }, 49 { 50 ID: "EXC0007", 51 Pattern: "Subprocess launch(ed with variable|ing should be audited)", 52 Linter: "gosec", 53 Why: "Too many false-positives for parametrized shell calls", 54 }, 55 { 56 ID: "EXC0008", 57 Pattern: "(G104|G307)", 58 Linter: "gosec", 59 Why: "Duplicated errcheck checks", 60 }, 61 { 62 ID: "EXC0009", 63 Pattern: "(Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)", 64 Linter: "gosec", 65 Why: "Too many issues in popular repos", 66 }, 67 { 68 ID: "EXC0010", 69 Pattern: "Potential file inclusion via variable", 70 Linter: "gosec", 71 Why: "False positive is triggered by 'src, err := ioutil.ReadFile(filename)'", 72 }, 73 { 74 ID: "EXC0011", 75 Pattern: "(comment on exported (method|function|type|const)|" + 76 "should have( a package)? comment|comment should be of the form)", 77 Linter: "stylecheck", 78 Why: "Annoying issue about not having a comment. The rare codebase has such comments", 79 }, 80 { 81 ID: "EXC0012", 82 Pattern: `exported (.+) should have comment( \(or a comment on this block\))? or be unexported`, 83 Linter: "revive", 84 Why: "Annoying issue about not having a comment. The rare codebase has such comments", 85 }, 86 { 87 ID: "EXC0013", 88 Pattern: `package comment should be of the form "(.+)...`, 89 Linter: "revive", 90 Why: "Annoying issue about not having a comment. The rare codebase has such comments", 91 }, 92 { 93 ID: "EXC0014", 94 Pattern: `comment on exported (.+) should be of the form "(.+)..."`, 95 Linter: "revive", 96 Why: "Annoying issue about not having a comment. The rare codebase has such comments", 97 }, 98 { 99 ID: "EXC0015", 100 Pattern: `should have a package comment, unless it's in another file for this package`, 101 Linter: "revive", 102 Why: "Annoying issue about not having a comment. The rare codebase has such comments", 103 }, 104 } 105 106 type Issues struct { 107 IncludeDefaultExcludes []string `mapstructure:"include"` 108 ExcludeCaseSensitive bool `mapstructure:"exclude-case-sensitive"` 109 ExcludePatterns []string `mapstructure:"exclude"` 110 ExcludeRules []ExcludeRule `mapstructure:"exclude-rules"` 111 UseDefaultExcludes bool `mapstructure:"exclude-use-default"` 112 113 MaxIssuesPerLinter int `mapstructure:"max-issues-per-linter"` 114 MaxSameIssues int `mapstructure:"max-same-issues"` 115 116 DiffFromRevision string `mapstructure:"new-from-rev"` 117 DiffPatchFilePath string `mapstructure:"new-from-patch"` 118 Diff bool `mapstructure:"new"` 119 120 NeedFix bool `mapstructure:"fix"` 121 } 122 123 type ExcludeRule struct { 124 BaseRule `mapstructure:",squash"` 125 } 126 127 func (e ExcludeRule) Validate() error { 128 return e.BaseRule.Validate(excludeRuleMinConditionsCount) 129 } 130 131 type BaseRule struct { 132 Linters []string 133 Path string 134 Text string 135 Source string 136 } 137 138 func (b BaseRule) Validate(minConditionsCount int) error { 139 if err := validateOptionalRegex(b.Path); err != nil { 140 return fmt.Errorf("invalid path regex: %v", err) 141 } 142 if err := validateOptionalRegex(b.Text); err != nil { 143 return fmt.Errorf("invalid text regex: %v", err) 144 } 145 if err := validateOptionalRegex(b.Source); err != nil { 146 return fmt.Errorf("invalid source regex: %v", err) 147 } 148 nonBlank := 0 149 if len(b.Linters) > 0 { 150 nonBlank++ 151 } 152 if b.Path != "" { 153 nonBlank++ 154 } 155 if b.Text != "" { 156 nonBlank++ 157 } 158 if b.Source != "" { 159 nonBlank++ 160 } 161 if nonBlank < minConditionsCount { 162 return fmt.Errorf("at least %d of (text, source, path, linters) should be set", minConditionsCount) 163 } 164 return nil 165 } 166 167 func validateOptionalRegex(value string) error { 168 if value == "" { 169 return nil 170 } 171 _, err := regexp.Compile(value) 172 return err 173 } 174 175 type ExcludePattern struct { 176 ID string 177 Pattern string 178 Linter string 179 Why string 180 } 181 182 func GetDefaultExcludePatternsStrings() []string { 183 ret := make([]string, len(DefaultExcludePatterns)) 184 for i, p := range DefaultExcludePatterns { 185 ret[i] = p.Pattern 186 } 187 return ret 188 } 189 190 func GetExcludePatterns(include []string) []ExcludePattern { 191 includeMap := make(map[string]bool, len(include)) 192 for _, inc := range include { 193 includeMap[inc] = true 194 } 195 196 var ret []ExcludePattern 197 for _, p := range DefaultExcludePatterns { 198 if !includeMap[p.ID] { 199 ret = append(ret, p) 200 } 201 } 202 203 return ret 204 }