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