diff --git a/pkg/fsutils/path_unix.go b/pkg/fsutils/path_unix.go new file mode 100644 index 000000000000..2a171ecc0c85 --- /dev/null +++ b/pkg/fsutils/path_unix.go @@ -0,0 +1,8 @@ +//go:build !windows + +package fsutils + +// NormalizePathInRegex it's a noop function on Unix. +func NormalizePathInRegex(path string) string { + return path +} diff --git a/pkg/fsutils/path_windows.go b/pkg/fsutils/path_windows.go new file mode 100644 index 000000000000..650aae1e16eb --- /dev/null +++ b/pkg/fsutils/path_windows.go @@ -0,0 +1,28 @@ +//go:build windows + +package fsutils + +import ( + "path/filepath" + "regexp" + "strings" +) + +var separatorToReplace = regexp.QuoteMeta(string(filepath.Separator)) + +// NormalizePathInRegex normalizes path in regular expressions. +// noop on Unix. +// This replacing should be safe because "/" are disallowed in Windows +// https://docs.microsoft.com/windows/win32/fileio/naming-a-file +func NormalizePathInRegex(path string) string { + // remove redundant character escape "\/" https://github.com/golangci/golangci-lint/issues/3277 + clean := regexp.MustCompile(`\\+/`). + ReplaceAllStringFunc(path, func(s string) string { + if strings.Count(s, "\\")%2 == 0 { + return s + } + return s[1:] + }) + + return strings.ReplaceAll(clean, "/", separatorToReplace) +} diff --git a/pkg/golinters/depguard.go b/pkg/golinters/depguard.go index 3e0171f5c919..eb7b0f3304b2 100644 --- a/pkg/golinters/depguard.go +++ b/pkg/golinters/depguard.go @@ -2,8 +2,6 @@ package golinters import ( "fmt" - "path/filepath" - "regexp" "strings" "sync" @@ -12,6 +10,7 @@ import ( "golang.org/x/tools/go/loader" //nolint:staticcheck // require changes in github.com/OpenPeeDeeP/depguard "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/fsutils" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" "github.com/golangci/golangci-lint/pkg/lint/linter" "github.com/golangci/golangci-lint/pkg/result" @@ -106,16 +105,6 @@ func (d depGuard) run(pass *analysis.Pass) ([]goanalysis.Issue, error) { return resIssues, nil } -var separatorToReplace = regexp.QuoteMeta(string(filepath.Separator)) - -// normalizePathInRegex normalizes path in regular expressions. -// noop on Unix. -// This replacing should be safe because "/" are disallowed in Windows -// https://docs.microsoft.com/windows/win32/fileio/naming-a-file -func normalizePathInRegex(path string) string { - return strings.ReplaceAll(path, "/", separatorToReplace) -} - type guardian struct { *depguard.Depguard pkgsWithErrorMessage map[string]string @@ -124,7 +113,7 @@ type guardian struct { func newGuardian(settings *config.DepGuardSettings) (*guardian, error) { var ignoreFileRules []string for _, rule := range settings.IgnoreFileRules { - ignoreFileRules = append(ignoreFileRules, normalizePathInRegex(rule)) + ignoreFileRules = append(ignoreFileRules, fsutils.NormalizePathInRegex(rule)) } dg := &depguard.Depguard{ diff --git a/pkg/result/processors/exclude_rules.go b/pkg/result/processors/exclude_rules.go index e9f474b98c54..62533b811533 100644 --- a/pkg/result/processors/exclude_rules.go +++ b/pkg/result/processors/exclude_rules.go @@ -44,7 +44,7 @@ func createRules(rules []ExcludeRule, prefix string) []excludeRule { parsedRule.source = regexp.MustCompile(prefix + rule.Source) } if rule.Path != "" { - path := normalizePathInRegex(rule.Path) + path := fsutils.NormalizePathInRegex(rule.Path) parsedRule.path = regexp.MustCompile(path) } parsedRules = append(parsedRules, parsedRule) diff --git a/pkg/result/processors/path_unix.go b/pkg/result/processors/path_unix.go deleted file mode 100644 index b0c7c33826cb..000000000000 --- a/pkg/result/processors/path_unix.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !windows - -package processors - -// normalizePathInRegex it's a noop function on Unix. -func normalizePathInRegex(path string) string { - return path -} diff --git a/pkg/result/processors/path_windows.go b/pkg/result/processors/path_windows.go deleted file mode 100644 index 7f3e3622bb75..000000000000 --- a/pkg/result/processors/path_windows.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build windows - -package processors - -import ( - "path/filepath" - "regexp" - "strings" -) - -var separatorToReplace = regexp.QuoteMeta(string(filepath.Separator)) - -// normalizePathInRegex normalizes path in regular expressions. -// noop on Unix. -// This replacing should be safe because "/" are disallowed in Windows -// https://docs.microsoft.com/windows/win32/fileio/naming-a-file -func normalizePathInRegex(path string) string { - return strings.ReplaceAll(path, "/", separatorToReplace) -} diff --git a/pkg/result/processors/severity_rules.go b/pkg/result/processors/severity_rules.go index 4077b34057d1..85c1866a21d9 100644 --- a/pkg/result/processors/severity_rules.go +++ b/pkg/result/processors/severity_rules.go @@ -49,7 +49,7 @@ func createSeverityRules(rules []SeverityRule, prefix string) []severityRule { parsedRule.source = regexp.MustCompile(prefix + rule.Source) } if rule.Path != "" { - path := normalizePathInRegex(rule.Path) + path := fsutils.NormalizePathInRegex(rule.Path) parsedRule.path = regexp.MustCompile(path) } parsedRules = append(parsedRules, parsedRule) diff --git a/pkg/result/processors/skip_dirs.go b/pkg/result/processors/skip_dirs.go index d657c5a04d00..11ab99104f79 100644 --- a/pkg/result/processors/skip_dirs.go +++ b/pkg/result/processors/skip_dirs.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" + "github.com/golangci/golangci-lint/pkg/fsutils" "github.com/golangci/golangci-lint/pkg/logutils" "github.com/golangci/golangci-lint/pkg/result" ) @@ -31,7 +32,7 @@ const goFileSuffix = ".go" func NewSkipDirs(patterns []string, log logutils.Log, runArgs []string) (*SkipDirs, error) { var patternsRe []*regexp.Regexp for _, p := range patterns { - p = normalizePathInRegex(p) + p = fsutils.NormalizePathInRegex(p) patternRe, err := regexp.Compile(p) if err != nil { return nil, errors.Wrapf(err, "can't compile regexp %q", p) diff --git a/pkg/result/processors/skip_files.go b/pkg/result/processors/skip_files.go index 1e2ca7aebf5c..b7b86bed06ce 100644 --- a/pkg/result/processors/skip_files.go +++ b/pkg/result/processors/skip_files.go @@ -4,6 +4,7 @@ import ( "fmt" "regexp" + "github.com/golangci/golangci-lint/pkg/fsutils" "github.com/golangci/golangci-lint/pkg/result" ) @@ -16,7 +17,7 @@ var _ Processor = (*SkipFiles)(nil) func NewSkipFiles(patterns []string) (*SkipFiles, error) { var patternsRe []*regexp.Regexp for _, p := range patterns { - p = normalizePathInRegex(p) + p = fsutils.NormalizePathInRegex(p) patternRe, err := regexp.Compile(p) if err != nil { return nil, fmt.Errorf("can't compile regexp %q: %s", p, err) diff --git a/test/testshared/runner.go b/test/testshared/runner.go index 70e2533bc23a..329411a9cbec 100644 --- a/test/testshared/runner.go +++ b/test/testshared/runner.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" "github.com/golangci/golangci-lint/pkg/exitcodes" + "github.com/golangci/golangci-lint/pkg/fsutils" "github.com/golangci/golangci-lint/pkg/logutils" ) @@ -304,7 +305,7 @@ func (r *RunnerResult) ExpectExitCode(possibleCodes ...int) *RunnerResult { func (r *RunnerResult) ExpectOutputRegexp(s string) *RunnerResult { r.tb.Helper() - assert.Regexp(r.tb, normalizePathInRegex(s), r.output, "exit code is %d", r.exitCode) + assert.Regexp(r.tb, fsutils.NormalizePathInRegex(s), r.output, "exit code is %d", r.exitCode) return r } diff --git a/test/testshared/runner_unix.go b/test/testshared/runner_unix.go index c36669b1c6b6..edba71d54537 100644 --- a/test/testshared/runner_unix.go +++ b/test/testshared/runner_unix.go @@ -29,8 +29,3 @@ func defaultBinaryName() string { func normalizeFilePath(in string) string { return in } - -// normalizePathInRegex it's a noop function on Unix. -func normalizePathInRegex(path string) string { - return path -} diff --git a/test/testshared/runner_windows.go b/test/testshared/runner_windows.go index 69afec9c5bca..d6aa865ea182 100644 --- a/test/testshared/runner_windows.go +++ b/test/testshared/runner_windows.go @@ -41,11 +41,3 @@ func normalizeFilePath(in string) string { return strings.ReplaceAll(s, "/", "\\") }) } - -// normalizePathInRegex normalizes path in regular expressions. -// Replace all `/` with `\\`. -// This replacing should be safe because "/" are disallowed in Windows -// https://docs.microsoft.com/windows/win32/fileio/naming-a-file -func normalizePathInRegex(path string) string { - return strings.ReplaceAll(path, "/", regexp.QuoteMeta(string(filepath.Separator))) -}