Skip to content

Commit 6550984

Browse files
authored
Configure path prefix via processor abstraction (#1226)
1 parent 916213c commit 6550984

File tree

8 files changed

+109
-4
lines changed

8 files changed

+109
-4
lines changed

.golangci.example.yml

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ output:
7272
# make issues output unique by line, default is true
7373
uniq-by-line: true
7474

75+
# add a prefix to the output file references; default is no prefix
76+
path-prefix: ""
77+
7578

7679
# all available settings of specific linters
7780
linters-settings:

pkg/commands/run.go

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, is
8181
fs.BoolVar(&oc.PrintLinterName, "print-linter-name", true, wh("Print linter name in issue line"))
8282
fs.BoolVar(&oc.UniqByLine, "uniq-by-line", true, wh("Make issues output unique by line"))
8383
fs.BoolVar(&oc.PrintWelcomeMessage, "print-welcome", false, wh("Print welcome message"))
84+
fs.StringVar(&oc.PathPrefix, "path-prefix", "", wh("Path prefix to add to output"))
8485
hideFlag("print-welcome") // no longer used
8586

8687
// Run config

pkg/config/config.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -516,10 +516,11 @@ type Config struct {
516516
Output struct {
517517
Format string
518518
Color string
519-
PrintIssuedLine bool `mapstructure:"print-issued-lines"`
520-
PrintLinterName bool `mapstructure:"print-linter-name"`
521-
UniqByLine bool `mapstructure:"uniq-by-line"`
522-
PrintWelcomeMessage bool `mapstructure:"print-welcome"`
519+
PrintIssuedLine bool `mapstructure:"print-issued-lines"`
520+
PrintLinterName bool `mapstructure:"print-linter-name"`
521+
UniqByLine bool `mapstructure:"uniq-by-line"`
522+
PrintWelcomeMessage bool `mapstructure:"print-welcome"`
523+
PathPrefix string `mapstructure:"path-prefix"`
523524
}
524525

525526
LintersSettings LintersSettings `mapstructure:"linters-settings"`

pkg/lint/runner.go

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lint
7979
processors.NewSourceCode(lineCache, log.Child("source_code")),
8080
processors.NewPathShortener(),
8181
getSeverityRulesProcessor(&cfg.Severity, log, lineCache),
82+
processors.NewPathPrefixer(cfg.Output.PathPrefix),
8283
},
8384
Log: log,
8485
}, nil
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package processors
2+
3+
import (
4+
"path"
5+
6+
"github.com/golangci/golangci-lint/pkg/result"
7+
)
8+
9+
// PathPrefixer adds a customizable prefix to every output path
10+
type PathPrefixer struct {
11+
prefix string
12+
}
13+
14+
var _ Processor = new(PathPrefixer)
15+
16+
// NewPathPrefixer returns a new path prefixer for the provided string
17+
func NewPathPrefixer(prefix string) *PathPrefixer {
18+
return &PathPrefixer{prefix: prefix}
19+
}
20+
21+
// Name returns the name of this processor
22+
func (*PathPrefixer) Name() string {
23+
return "path_prefixer"
24+
}
25+
26+
// Process adds the prefix to each path
27+
func (p *PathPrefixer) Process(issues []result.Issue) ([]result.Issue, error) {
28+
if p.prefix != "" {
29+
for i := range issues {
30+
issues[i].Pos.Filename = path.Join(p.prefix, issues[i].Pos.Filename)
31+
}
32+
}
33+
return issues, nil
34+
}
35+
36+
// Finish is implemented to satisfy the Processor interface
37+
func (*PathPrefixer) Finish() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package processors
2+
3+
import (
4+
"go/token"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
9+
"github.com/golangci/golangci-lint/pkg/result"
10+
)
11+
12+
func TestPathPrefixer_Process(t *testing.T) {
13+
paths := func(ps ...string) (issues []result.Issue) {
14+
for _, p := range ps {
15+
issues = append(issues, result.Issue{Pos: token.Position{Filename: p}})
16+
}
17+
return
18+
}
19+
for _, tt := range []struct {
20+
name, prefix string
21+
issues, want []result.Issue
22+
}{
23+
{"empty prefix", "", paths("some/path", "cool"), paths("some/path", "cool")},
24+
{"prefix", "ok", paths("some/path", "cool"), paths("ok/some/path", "ok/cool")},
25+
{"prefix slashed", "ok/", paths("some/path", "cool"), paths("ok/some/path", "ok/cool")},
26+
} {
27+
t.Run(tt.name, func(t *testing.T) {
28+
r := require.New(t)
29+
30+
p := NewPathPrefixer(tt.prefix) //nolint:scopelint
31+
got, err := p.Process(tt.issues) //nolint:scopelint
32+
r.NoError(err, "prefixer should never error")
33+
34+
r.Equal(got, tt.want) //nolint:scopelint
35+
})
36+
}
37+
}

test/run_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,22 @@ func TestDisallowedOptionsInConfig(t *testing.T) {
292292
r.RunWithYamlConfig(c.cfg, withCommonRunArgs(args...)...).ExpectExitCode(exitcodes.Failure)
293293
}
294294
}
295+
296+
func TestPathPrefix(t *testing.T) {
297+
for _, tt := range []struct {
298+
Name string
299+
Args []string
300+
Pattern string
301+
}{
302+
{"empty", nil, "^testdata/withTests/"},
303+
{"prefixed", []string{"--path-prefix=cool"}, "^cool/testdata/withTests"},
304+
} {
305+
t.Run(tt.Name, func(t *testing.T) {
306+
testshared.NewLintRunner(t).Run(
307+
append(tt.Args, getTestDataDir("withTests"))..., //nolint:scopelint
308+
).ExpectOutputRegexp(
309+
tt.Pattern, //nolint:scopelint
310+
)
311+
})
312+
}
313+
}

test/testshared/testshared.go

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ func (r *RunResult) ExpectExitCode(possibleCodes ...int) *RunResult {
6666
return r
6767
}
6868

69+
// ExpectOutputRegexp can be called with either a string or compiled regexp
70+
func (r *RunResult) ExpectOutputRegexp(s interface{}) *RunResult {
71+
assert.Regexp(r.t, s, r.output, "exit code is %d", r.exitCode)
72+
return r
73+
}
74+
6975
func (r *RunResult) ExpectOutputContains(s string) *RunResult {
7076
assert.Contains(r.t, r.output, s, "exit code is %d", r.exitCode)
7177
return r

0 commit comments

Comments
 (0)