1
1
package commands
2
2
3
3
import (
4
+ "encoding/json"
4
5
"fmt"
5
6
"slices"
6
7
"sort"
@@ -17,9 +18,25 @@ import (
17
18
"github.com/golangci/golangci-lint/pkg/logutils"
18
19
)
19
20
21
+ type linterHelp struct {
22
+ Name string `json:"name"`
23
+ Desc string `json:"description"`
24
+ Fast bool `json:"fast"`
25
+ AutoFix bool `json:"autoFix"`
26
+ Presets []string `json:"presets"`
27
+ EnabledByDefault bool `json:"enabledByDefault"`
28
+ Deprecated bool `json:"deprecated"`
29
+ }
30
+
31
+ type helpOptions struct {
32
+ JSON bool
33
+ }
34
+
20
35
type helpCommand struct {
21
36
cmd * cobra.Command
22
37
38
+ opts helpOptions
39
+
23
40
dbManager * lintersdb.Manager
24
41
25
42
log logutils.Log
@@ -37,16 +54,21 @@ func newHelpCommand(logger logutils.Log) *helpCommand {
37
54
},
38
55
}
39
56
40
- helpCmd .AddCommand (
41
- & cobra.Command {
42
- Use : "linters" ,
43
- Short : "Help about linters" ,
44
- Args : cobra .NoArgs ,
45
- ValidArgsFunction : cobra .NoFileCompletions ,
46
- Run : c .execute ,
47
- PreRunE : c .preRunE ,
48
- },
49
- )
57
+ lintersCmd := & cobra.Command {
58
+ Use : "linters" ,
59
+ Short : "Help about linters" ,
60
+ Args : cobra .NoArgs ,
61
+ ValidArgsFunction : cobra .NoFileCompletions ,
62
+ RunE : c .execute ,
63
+ PreRunE : c .preRunE ,
64
+ }
65
+
66
+ helpCmd .AddCommand (lintersCmd )
67
+
68
+ fs := lintersCmd .Flags ()
69
+ fs .SortFlags = false // sort them as they are defined here
70
+
71
+ fs .BoolVar (& c .opts .JSON , "json" , true , color .GreenString ("Display as JSON" ))
50
72
51
73
c .cmd = helpCmd
52
74
@@ -66,7 +88,39 @@ func (c *helpCommand) preRunE(_ *cobra.Command, _ []string) error {
66
88
return nil
67
89
}
68
90
69
- func (c * helpCommand ) execute (_ * cobra.Command , _ []string ) {
91
+ func (c * helpCommand ) execute (_ * cobra.Command , _ []string ) error {
92
+ if c .opts .JSON {
93
+ return c .printJSON ()
94
+ }
95
+
96
+ c .print ()
97
+
98
+ return nil
99
+ }
100
+
101
+ func (c * helpCommand ) printJSON () error {
102
+ var linters []linterHelp
103
+
104
+ for _ , lc := range c .dbManager .GetAllSupportedLinterConfigs () {
105
+ if lc .Internal {
106
+ continue
107
+ }
108
+
109
+ linters = append (linters , linterHelp {
110
+ Name : lc .Name (),
111
+ Desc : formatDescription (lc .Linter .Desc ()),
112
+ Fast : ! lc .IsSlowLinter (),
113
+ AutoFix : lc .CanAutoFix ,
114
+ Presets : lc .InPresets ,
115
+ EnabledByDefault : lc .EnabledByDefault ,
116
+ Deprecated : lc .IsDeprecated (),
117
+ })
118
+ }
119
+
120
+ return json .NewEncoder (c .cmd .OutOrStdout ()).Encode (linters )
121
+ }
122
+
123
+ func (c * helpCommand ) print () {
70
124
var enabledLCs , disabledLCs []* linter.Config
71
125
for _ , lc := range c .dbManager .GetAllSupportedLinterConfigs () {
72
126
if lc .Internal {
@@ -126,22 +180,7 @@ func printLinters(lcs []*linter.Config) {
126
180
})
127
181
128
182
for _ , lc := range lcs {
129
- desc := lc .Linter .Desc ()
130
-
131
- // If the linter description spans multiple lines, truncate everything following the first newline
132
- endFirstLine := strings .IndexRune (desc , '\n' )
133
- if endFirstLine > 0 {
134
- desc = desc [:endFirstLine ]
135
- }
136
-
137
- rawDesc := []rune (desc )
138
-
139
- r , _ := utf8 .DecodeRuneInString (desc )
140
- rawDesc [0 ] = unicode .ToUpper (r )
141
-
142
- if rawDesc [len (rawDesc )- 1 ] != '.' {
143
- rawDesc = append (rawDesc , '.' )
144
- }
183
+ desc := formatDescription (lc .Linter .Desc ())
145
184
146
185
deprecatedMark := ""
147
186
if lc .IsDeprecated () {
@@ -162,6 +201,25 @@ func printLinters(lcs []*linter.Config) {
162
201
}
163
202
164
203
_ , _ = fmt .Fprintf (logutils .StdOut , "%s%s: %s%s\n " ,
165
- color .YellowString (lc .Name ()), deprecatedMark , string (rawDesc ), capability )
204
+ color .YellowString (lc .Name ()), deprecatedMark , desc , capability )
205
+ }
206
+ }
207
+
208
+ func formatDescription (desc string ) string {
209
+ // If the linter description spans multiple lines, truncate everything following the first newline
210
+ endFirstLine := strings .IndexRune (desc , '\n' )
211
+ if endFirstLine > 0 {
212
+ desc = desc [:endFirstLine ]
166
213
}
214
+
215
+ rawDesc := []rune (desc )
216
+
217
+ r , _ := utf8 .DecodeRuneInString (desc )
218
+ rawDesc [0 ] = unicode .ToUpper (r )
219
+
220
+ if rawDesc [len (rawDesc )- 1 ] != '.' {
221
+ rawDesc = append (rawDesc , '.' )
222
+ }
223
+
224
+ return string (rawDesc )
167
225
}
0 commit comments