Skip to content

Commit 4ccac53

Browse files
authored
Merge pull request #82 from wata727/checkstyle
Add checkstyle format
2 parents db43f76 + 36f7e83 commit 4ccac53

File tree

8 files changed

+156
-5
lines changed

8 files changed

+156
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Please show `tflint --help`
7878
```
7979
-h, --help show usage of TFLint. This page.
8080
-v, --version print version information.
81-
-f, --format <format> choose output format from "default" or "json"
81+
-f, --format <format> choose output format from "default", "json" or "checkstyle"
8282
-c, --config <file> specify config file. default is ".tflint.hcl"
8383
--ignore-module <source1,source2...> ignore module by specified source.
8484
--ignore-rule <rule1,rule2...> ignore rules.

cli.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func (cli *CLI) Run(args []string) int {
7171
flags.BoolVar(&help, "h", false, "alias for --help")
7272
flags.BoolVar(&configArgs.Debug, "debug", false, "enable debug mode.")
7373
flags.BoolVar(&configArgs.Debug, "d", false, "alias for --debug")
74-
flags.StringVar(&format, "format", "default", "choose output format from \"default\" or \"json\"")
74+
flags.StringVar(&format, "format", "default", "choose output format from \"default\", \"json\" or \"checkstyle\"")
7575
flags.StringVar(&format, "f", "default", "alias for --format")
7676
flags.StringVar(&configArgs.IgnoreModule, "ignore-module", "", "ignore module by specified source.")
7777
flags.StringVar(&configArgs.IgnoreRule, "ignore-rule", "", "ignore rules.")

cli_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,21 @@ func TestCLIRun(t *testing.T) {
279279
CLIOptions: defaultCLIOptions,
280280
},
281281
},
282+
{
283+
Name: "specify checkstyle format",
284+
Command: "./tflint --format checkstyle",
285+
LoaderGenerator: loaderDefaultBehavior,
286+
DetectorGenerator: detectorNoErrorNoIssuesBehavior,
287+
PrinterGenerator: func(ctrl *gomock.Controller) printer.PrinterIF {
288+
printer := mock.NewMockPrinterIF(ctrl)
289+
printer.EXPECT().Print([]*issue.Issue{}, "checkstyle")
290+
return printer
291+
},
292+
Result: Result{
293+
Status: ExitCodeOK,
294+
CLIOptions: defaultCLIOptions,
295+
},
296+
},
282297
{
283298
Name: "specify invalid format",
284299
Command: "./tflint --format awesome",

help.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Usage: tflint [<options>] <args>
77
Available Options:
88
-h, --help show usage of TFLint. This page.
99
-v, --version print version information.
10-
-f, --format <format> choose output format from "default" or "json"
10+
-f, --format <format> choose output format from "default", "json" or "checkstyle"
1111
-c, --config <file> specify config file. default is ".tflint.hcl"
1212
--ignore-module <source1,source2...> ignore module by specified source.
1313
--ignore-rule <rule1,rule2...> ignore rules.

printer/checkstyle.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package printer
2+
3+
import (
4+
"encoding/xml"
5+
"fmt"
6+
7+
"sort"
8+
9+
"github.com/wata727/tflint/issue"
10+
)
11+
12+
type Error struct {
13+
Line int `xml:"line,attr"`
14+
Severity string `xml:"severity,attr"`
15+
Message string `xml:"message,attr"`
16+
}
17+
18+
type File struct {
19+
Name string `xml:"name,attr"`
20+
Errors []Error `xml:"error"`
21+
}
22+
23+
type Checkstyle struct {
24+
XMLName xml.Name `xml:"checkstyle"`
25+
Files []File `xml:"file"`
26+
}
27+
28+
func (p *Printer) CheckstylePrint(issues []*issue.Issue) {
29+
sort.Sort(issue.ByFile{Issues: issue.Issues(issues)})
30+
31+
v := &Checkstyle{}
32+
33+
for _, i := range issues {
34+
if len(v.Files) == 0 || v.Files[len(v.Files)-1].Name != i.File {
35+
v.Files = append(v.Files, File{Name: i.File})
36+
}
37+
v.Files[len(v.Files)-1].Errors = append(v.Files[len(v.Files)-1].Errors, Error{Line: i.Line, Severity: toSeverity(i.Type), Message: i.Message})
38+
}
39+
40+
result, err := xml.MarshalIndent(v, "", " ")
41+
if err != nil {
42+
fmt.Fprint(p.stderr, err)
43+
}
44+
fmt.Fprint(p.stdout, xml.Header)
45+
fmt.Fprint(p.stdout, string(result))
46+
}
47+
48+
func toSeverity(lintType string) string {
49+
switch lintType {
50+
case issue.ERROR:
51+
return "error"
52+
case issue.WARNING:
53+
return "warning"
54+
case issue.NOTICE:
55+
return "info"
56+
default:
57+
return "unknown"
58+
}
59+
}

printer/checkstyle_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package printer
2+
3+
import (
4+
"testing"
5+
6+
"bytes"
7+
8+
"github.com/wata727/tflint/issue"
9+
)
10+
11+
func TestCheckstylePrint(t *testing.T) {
12+
cases := []struct {
13+
Name string
14+
Input []*issue.Issue
15+
Result string
16+
}{
17+
{
18+
Name: "no issues",
19+
Input: []*issue.Issue{},
20+
Result: `<?xml version="1.0" encoding="UTF-8"?>
21+
<checkstyle></checkstyle>`,
22+
},
23+
{
24+
Name: "multi files",
25+
Input: []*issue.Issue{
26+
{
27+
File: "template.tf",
28+
Line: 1,
29+
Type: "ERROR",
30+
Message: "example error message",
31+
},
32+
{
33+
File: "application.tf",
34+
Line: 10,
35+
Type: "NOTICE",
36+
Message: "example notice message",
37+
},
38+
{
39+
File: "template.tf",
40+
Line: 3,
41+
Type: "WARNING",
42+
Message: "example warning message",
43+
},
44+
},
45+
Result: `<?xml version="1.0" encoding="UTF-8"?>
46+
<checkstyle>
47+
<file name="application.tf">
48+
<error line="10" severity="info" message="example notice message"></error>
49+
</file>
50+
<file name="template.tf">
51+
<error line="1" severity="error" message="example error message"></error>
52+
<error line="3" severity="warning" message="example warning message"></error>
53+
</file>
54+
</checkstyle>`,
55+
},
56+
}
57+
58+
for _, tc := range cases {
59+
stdout := &bytes.Buffer{}
60+
stderr := &bytes.Buffer{}
61+
p := NewPrinter(stdout, stderr)
62+
p.CheckstylePrint(tc.Input)
63+
result := stdout.String()
64+
65+
if result != tc.Result {
66+
t.Fatalf("\nBad: %s\nExpected: %s\n\ntestcase: %s", result, tc.Result, tc.Name)
67+
}
68+
}
69+
}

printer/printer.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ type Printer struct {
1616
}
1717

1818
var validFormat = map[string]bool{
19-
"default": true,
20-
"json": true,
19+
"default": true,
20+
"json": true,
21+
"checkstyle": true,
2122
}
2223

2324
func NewPrinter(stdout io.Writer, stderr io.Writer) *Printer {
@@ -37,6 +38,8 @@ func (p *Printer) Print(issues []*issue.Issue, format string) {
3738
p.DefaultPrint(issues)
3839
case "json":
3940
p.JSONPrint(issues)
41+
case "checkstyle":
42+
p.CheckstylePrint(issues)
4043
default:
4144
p.DefaultPrint(issues)
4245
}

printer/printer_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ func TestValidateFormat(t *testing.T) {
2020
Input: "json",
2121
Result: true,
2222
},
23+
{
24+
Name: "checkstyle is valid format",
25+
Input: "checkstyle",
26+
Result: true,
27+
},
2328
{
2429
Name: "yaml is invalid format",
2530
Input: "yaml",

0 commit comments

Comments
 (0)