@@ -55,11 +55,12 @@ enum CodeActionListItemKind {
55
55
interface CodeActionListItemCodeAction {
56
56
readonly kind : CodeActionListItemKind . CodeAction ;
57
57
readonly action : CodeActionItem ;
58
+ readonly group : CodeActionGroup ;
58
59
}
59
60
60
61
interface CodeActionListItemHeader {
61
62
readonly kind : CodeActionListItemKind . Header ;
62
- readonly headerTitle : string ;
63
+ readonly group : CodeActionGroup ;
63
64
}
64
65
65
66
type ICodeActionMenuItem = CodeActionListItemCodeAction | CodeActionListItemHeader ;
@@ -75,6 +76,24 @@ function stripNewlines(str: string): string {
75
76
return str . replace ( / \r \n | \r | \n / g, ' ' ) ;
76
77
}
77
78
79
+ interface CodeActionGroup {
80
+ readonly kind : CodeActionKind ;
81
+ readonly title : string ;
82
+ readonly icon : Codicon ;
83
+ readonly iconColor ?: string ;
84
+ }
85
+
86
+ const uncategorizedCodeActionGroup = Object . freeze < CodeActionGroup > ( { kind : CodeActionKind . Empty , title : localize ( 'codeAction.widget.id.more' , 'More Actions...' ) , icon : Codicon . lightBulb , iconColor : 'var(--vscode-editorLightBulb-foreground)' } ) ;
87
+
88
+ const codeActionGroups = Object . freeze < CodeActionGroup [ ] > ( [
89
+ { kind : CodeActionKind . QuickFix , title : localize ( 'codeAction.widget.id.quickfix' , 'Quick Fix...' ) , icon : Codicon . lightBulb , } ,
90
+ { kind : CodeActionKind . Extract , title : localize ( 'codeAction.widget.id.extract' , 'Extract...' ) , icon : Codicon . wrench , } ,
91
+ { kind : CodeActionKind . Convert , title : localize ( 'codeAction.widget.id.convert' , 'Convert...' ) , icon : Codicon . zap , iconColor : 'var(--vscode-editorLightBulbAutoFix-foreground)' } ,
92
+ { kind : CodeActionKind . SurroundWith , title : localize ( 'codeAction.widget.id.surround' , 'Surround With...' ) , icon : Codicon . symbolArray , } ,
93
+ { kind : CodeActionKind . Source , title : localize ( 'codeAction.widget.id.source' , 'Source Action...' ) , icon : Codicon . lightBulb , iconColor : 'var(--vscode-editorLightBulb-foreground)' } ,
94
+ uncategorizedCodeActionGroup ,
95
+ ] ) ;
96
+
78
97
class CodeActionItemRenderer implements IListRenderer < CodeActionListItemCodeAction , ICodeActionMenuTemplateData > {
79
98
constructor (
80
99
private readonly keybindingResolver : CodeActionKeybindingResolver ,
@@ -100,22 +119,8 @@ class CodeActionItemRenderer implements IListRenderer<CodeActionListItemCodeActi
100
119
}
101
120
102
121
renderElement ( element : CodeActionListItemCodeAction , _index : number , data : ICodeActionMenuTemplateData ) : void {
103
- // Icons and Label modification based on group
104
- const kind = element . action . action . kind ? new CodeActionKind ( element . action . action . kind ) : CodeActionKind . None ;
105
- if ( CodeActionKind . SurroundWith . contains ( kind ) ) {
106
- data . icon . className = Codicon . symbolArray . classNames ;
107
- } else if ( CodeActionKind . Extract . contains ( kind ) ) {
108
- data . icon . className = Codicon . wrench . classNames ;
109
- } else if ( CodeActionKind . Convert . contains ( kind ) ) {
110
- data . icon . className = Codicon . zap . classNames ;
111
- data . icon . style . color = `var(--vscode-editorLightBulbAutoFix-foreground)` ;
112
- } else if ( CodeActionKind . QuickFix . contains ( kind ) ) {
113
- data . icon . className = Codicon . lightBulb . classNames ;
114
- data . icon . style . color = `var(--vscode-editorLightBulb-foreground)` ;
115
- } else {
116
- data . icon . className = Codicon . lightBulb . classNames ;
117
- data . icon . style . color = `var(--vscode-editorLightBulb-foreground)` ;
118
- }
122
+ data . icon . className = element . group . icon . classNames ;
123
+ data . icon . style . color = element . group . iconColor ?? '' ;
119
124
120
125
data . text . textContent = stripNewlines ( element . action . action . title ) ;
121
126
@@ -160,7 +165,7 @@ class HeaderRenderer implements IListRenderer<CodeActionListItemHeader, HeaderTe
160
165
}
161
166
162
167
renderElement ( element : CodeActionListItemHeader , _index : number , templateData : HeaderTemplateData ) : void {
163
- templateData . text . textContent = element . headerTitle ;
168
+ templateData . text . textContent = element . group . title ;
164
169
}
165
170
166
171
disposeTemplate ( _templateData : HeaderTemplateData ) : void {
@@ -303,49 +308,28 @@ class CodeActionList extends Disposable {
303
308
304
309
private toMenuItems ( inputCodeActions : readonly CodeActionItem [ ] , showHeaders : boolean ) : ICodeActionMenuItem [ ] {
305
310
if ( ! showHeaders ) {
306
- return inputCodeActions . map ( ( action ) : ICodeActionMenuItem => ( { kind : CodeActionListItemKind . CodeAction , action } ) ) ;
311
+ return inputCodeActions . map ( ( action ) : ICodeActionMenuItem => ( { kind : CodeActionListItemKind . CodeAction , action, group : uncategorizedCodeActionGroup } ) ) ;
307
312
}
308
313
309
- // Groups code actions by their kind
310
- const quickfixGroup : CodeActionItem [ ] = [ ] ;
311
- const extractGroup : CodeActionItem [ ] = [ ] ;
312
- const convertGroup : CodeActionItem [ ] = [ ] ;
313
- const surroundGroup : CodeActionItem [ ] = [ ] ;
314
- const sourceGroup : CodeActionItem [ ] = [ ] ;
315
- const otherGroup : CodeActionItem [ ] = [ ] ;
314
+ // Group code actions
315
+ const menuEntries = codeActionGroups . map ( group => ( { group, actions : [ ] as CodeActionItem [ ] } ) ) ;
316
316
317
317
for ( const action of inputCodeActions ) {
318
318
const kind = action . action . kind ? new CodeActionKind ( action . action . kind ) : CodeActionKind . None ;
319
- if ( CodeActionKind . SurroundWith . contains ( kind ) ) {
320
- surroundGroup . push ( action ) ;
321
- } else if ( CodeActionKind . QuickFix . contains ( kind ) ) {
322
- quickfixGroup . push ( action ) ;
323
- } else if ( CodeActionKind . Extract . contains ( kind ) ) {
324
- extractGroup . push ( action ) ;
325
- } else if ( CodeActionKind . Convert . contains ( kind ) ) {
326
- convertGroup . push ( action ) ;
327
- } else if ( CodeActionKind . Source . contains ( kind ) ) {
328
- sourceGroup . push ( action ) ;
329
- } else {
330
- otherGroup . push ( action ) ;
319
+ for ( const menuEntry of menuEntries ) {
320
+ if ( menuEntry . group . kind . contains ( kind ) ) {
321
+ menuEntry . actions . push ( action ) ;
322
+ break ;
323
+ }
331
324
}
332
325
}
333
326
334
- const menuEntries : ReadonlyArray < { title : string ; actions : CodeActionItem [ ] } > = [
335
- { title : localize ( 'codeAction.widget.id.quickfix' , 'Quick Fix...' ) , actions : quickfixGroup } ,
336
- { title : localize ( 'codeAction.widget.id.extract' , 'Extract...' ) , actions : extractGroup } ,
337
- { title : localize ( 'codeAction.widget.id.convert' , 'Convert...' ) , actions : convertGroup } ,
338
- { title : localize ( 'codeAction.widget.id.surround' , 'Surround With...' ) , actions : surroundGroup } ,
339
- { title : localize ( 'codeAction.widget.id.source' , 'Source Action...' ) , actions : sourceGroup } ,
340
- { title : localize ( 'codeAction.widget.id.more' , 'More Actions...' ) , actions : otherGroup } ,
341
- ] ;
342
-
343
327
const allMenuItems : ICodeActionMenuItem [ ] = [ ] ;
344
328
for ( const menuEntry of menuEntries ) {
345
329
if ( menuEntry . actions . length ) {
346
- allMenuItems . push ( { kind : CodeActionListItemKind . Header , headerTitle : menuEntry . title } ) ;
330
+ allMenuItems . push ( { kind : CodeActionListItemKind . Header , group : menuEntry . group } ) ;
347
331
for ( const action of menuEntry . actions ) {
348
- allMenuItems . push ( { kind : CodeActionListItemKind . CodeAction , action } ) ;
332
+ allMenuItems . push ( { kind : CodeActionListItemKind . CodeAction , action, group : menuEntry . group } ) ;
349
333
}
350
334
}
351
335
}
0 commit comments