@@ -44,6 +44,12 @@ export interface ProblemDiagnosticActionResult {
4444 code ?: NonNullable < vscode . Diagnostic [ 'code' ] > ;
4545}
4646
47+ type ProblemActionDescriptor =
48+ | { kind : 'merge' ; localPath : string ; updateLevel : MergeUpdateLevel ; componentId ?: string }
49+ | { kind : 'run-generator' ; generator : string ; context : string }
50+ | { kind : 'manage-components' ; query : string }
51+ | { kind : 'find-in-files' ; query : string } ;
52+
4753const mergeMessagePatterns = [
4854 {
4955 pattern : / u p d a t e \s + ( r e q u i r e d | r e c o m m e n d e d | s u g g e s t e d | m a n d a t o r y ) \s + f o r \s + f i l e \s + ' ( [ ^ ' ] + ) ' / i,
@@ -53,7 +59,10 @@ const mergeMessagePatterns = [
5359] as const ;
5460
5561const mergeComponentRegex = / (?: f o r | f r o m ) \s + c o m p o n e n t \s + ' ( [ ^ ' ] + ) ' / i;
56- const generatorMissingPattern = / c g e n f i l e w a s n o t f o u n d , \s * r u n g e n e r a t o r ' ( [ ^ ' ] + ) ' f o r c o n t e x t ' ( [ ^ ' ] + ) ' / i;
62+ const generatorMissingPatterns : readonly RegExp [ ] = [
63+ / c g e n f i l e w a s n o t f o u n d , \s * r u n g e n e r a t o r ' ( [ ^ ' ] + ) ' f o r c o n t e x t ' ( [ ^ ' ] + ) ' / i,
64+ / (?: c g e n \s + f i l e \s + .* \s + ) ? r u n g e n e r a t o r ' ( [ ^ ' ] + ) ' f o r c o n t e x t ' ( [ ^ ' ] + ) ' / i,
65+ ] ;
5766
5867const queryActionPatterns : ReadonlyArray < { pattern : RegExp ; action : 'components-packs' | 'find-in-files' } > = [
5968 { pattern : / d e p e n d e n c y v a l i d a t i o n f o r c o n t e x t ' ( [ ^ ' ] + ) ' f a i l e d : / , action : 'components-packs' } ,
@@ -65,63 +74,93 @@ const queryActionPatterns: ReadonlyArray<{ pattern: RegExp; action: 'components-
6574
6675export class ProblemDiagnosticActionResolver {
6776 public resolve ( context : ProblemDiagnosticActionContext ) : ProblemDiagnosticActionResult | undefined {
77+ const descriptor = this . resolveDescriptor ( context ) ;
78+ if ( ! descriptor ) {
79+ return undefined ;
80+ }
81+ return this . toDiagnosticAction ( descriptor ) ;
82+ }
83+
84+ private resolveDescriptor ( context : ProblemDiagnosticActionContext ) : ProblemActionDescriptor | undefined {
6885 return this . resolveMergeAction ( context )
6986 ?? this . resolveGeneratorMissingAction ( context )
7087 ?? this . resolveManageComponentsAction ( context )
7188 ?? this . resolveGenericSearchAction ( context ) ;
7289 }
7390
74- public createMergeDiagnosticAction ( message : string , diagnosticFilePath : string ) : ProblemDiagnosticActionResult | undefined {
75- const merge = this . parseMergeMessage ( message ) ;
76- if ( ! merge ) {
77- return undefined ;
91+ private toDiagnosticAction ( descriptor : ProblemActionDescriptor ) : ProblemDiagnosticActionResult {
92+ if ( descriptor . kind === 'merge' ) {
93+ return {
94+ message : this . createMergeDiagnosticMessage ( descriptor . localPath , descriptor . updateLevel , descriptor . componentId ) ,
95+ code : {
96+ value : MERGE_VIEW_LINK_LABEL ,
97+ target : this . createMergeCommandUri ( descriptor . localPath ) ,
98+ } ,
99+ } ;
78100 }
79101
80- const componentId = mergeComponentRegex . exec ( message ) ?. [ 1 ] ;
81- const localPath = this . isAbsoluteFilePath ( merge . localPath ) ? merge . localPath : diagnosticFilePath ;
102+ if ( descriptor . kind === 'run-generator' ) {
103+ return {
104+ code : {
105+ value : 'Run Generator' ,
106+ target : this . createRunGeneratorCommandUri ( descriptor . generator , descriptor . context ) ,
107+ } ,
108+ } ;
109+ }
82110
111+ if ( descriptor . kind === 'manage-components' ) {
112+ const args = this . encodeCommandArgs ( [ { type : 'context' , value : descriptor . query } ] ) ;
113+ return {
114+ code : {
115+ value : 'Manage Components' ,
116+ target : vscode . Uri . parse ( `command:${ MANAGE_COMPONENTS_PACKS_COMMAND_ID } ?${ args } ` ) ,
117+ } ,
118+ } ;
119+ }
120+
121+ const args = this . encodeFindInFilesArgs ( descriptor . query ) ;
83122 return {
84- message : this . createMergeDiagnosticMessage ( localPath , merge . updateLevel , componentId ) ,
85123 code : {
86- value : MERGE_VIEW_LINK_LABEL ,
87- target : this . createMergeCommandUri ( localPath ) ,
124+ value : 'Find in Files' ,
125+ target : vscode . Uri . parse ( `command:workbench.action.findInFiles? ${ args } ` ) ,
88126 } ,
89127 } ;
90128 }
91129
92- public createMergeCommandUri ( localPath : string ) : vscode . Uri {
93- const args = this . encodeCommandArgs ( [ localPath ] ) ;
94- return vscode . Uri . parse ( `command:${ MERGE_FILE_COMMAND_ID } ?${ args } ` ) ;
95- }
96-
97- public isAbsoluteFilePath ( filePath : string ) : boolean {
98- return path . isAbsolute ( filePath ) || path . win32 . isAbsolute ( filePath ) ;
99- }
130+ private resolveMergeAction ( context : ProblemDiagnosticActionContext ) : ProblemActionDescriptor | undefined {
131+ const merge = this . parseMergeMessage ( context . message ) ;
132+ if ( ! merge ) {
133+ return undefined ;
134+ }
100135
101- private resolveMergeAction ( context : ProblemDiagnosticActionContext ) : ProblemDiagnosticActionResult | undefined {
102- return this . createMergeDiagnosticAction ( context . message , context . diagnosticFilePath ) ;
136+ const componentId = mergeComponentRegex . exec ( context . message ) ?. [ 1 ] ;
137+ const localPath = this . isAbsoluteFilePath ( merge . localPath ) ? merge . localPath : context . diagnosticFilePath ;
138+ return {
139+ kind : 'merge' ,
140+ localPath,
141+ updateLevel : merge . updateLevel ,
142+ componentId,
143+ } ;
103144 }
104145
105- private resolveGeneratorMissingAction ( context : ProblemDiagnosticActionContext ) : ProblemDiagnosticActionResult | undefined {
146+ private resolveGeneratorMissingAction ( context : ProblemDiagnosticActionContext ) : ProblemActionDescriptor | undefined {
106147 if ( context . hasLocation ) {
107148 return undefined ;
108149 }
109150
110- const match = context . message . match ( generatorMissingPattern ) ;
111- if ( ! match ) {
151+ const request = this . parseGeneratorRequest ( context . message ) ;
152+ if ( ! request ) {
112153 return undefined ;
113154 }
114155
115- const [ , generator , generatorContext ] = match ;
116156 return {
117- code : {
118- value : 'Run Generator' ,
119- target : this . createRunGeneratorCommandUri ( generator , generatorContext ) ,
120- } ,
157+ kind : 'run-generator' ,
158+ generator : request . generator ,
159+ context : request . context ,
121160 } ;
122161 }
123162
124- private resolveManageComponentsAction ( context : ProblemDiagnosticActionContext ) : ProblemDiagnosticActionResult | undefined {
163+ private resolveManageComponentsAction ( context : ProblemDiagnosticActionContext ) : ProblemActionDescriptor | undefined {
125164 if ( context . hasLocation ) {
126165 return undefined ;
127166 }
@@ -131,16 +170,13 @@ export class ProblemDiagnosticActionResolver {
131170 return undefined ;
132171 }
133172
134- const args = this . encodeCommandArgs ( [ { type : 'context' , value : queryAction . query } ] ) ;
135173 return {
136- code : {
137- value : 'Manage Components' ,
138- target : vscode . Uri . parse ( `command:${ MANAGE_COMPONENTS_PACKS_COMMAND_ID } ?${ args } ` ) ,
139- } ,
174+ kind : 'manage-components' ,
175+ query : queryAction . query ,
140176 } ;
141177 }
142178
143- private resolveGenericSearchAction ( context : ProblemDiagnosticActionContext ) : ProblemDiagnosticActionResult | undefined {
179+ private resolveGenericSearchAction ( context : ProblemDiagnosticActionContext ) : ProblemActionDescriptor | undefined {
144180 if ( context . hasLocation ) {
145181 return undefined ;
146182 }
@@ -150,15 +186,26 @@ export class ProblemDiagnosticActionResolver {
150186 return undefined ;
151187 }
152188
153- const args = this . encodeFindInFilesArgs ( queryAction . query ) ;
154189 return {
155- code : {
156- value : 'Find in Files' ,
157- target : vscode . Uri . parse ( `command:workbench.action.findInFiles?${ args } ` ) ,
158- } ,
190+ kind : 'find-in-files' ,
191+ query : queryAction . query ,
159192 } ;
160193 }
161194
195+ private parseGeneratorRequest ( message : string ) : { generator : string ; context : string } | undefined {
196+ for ( const pattern of generatorMissingPatterns ) {
197+ const match = message . match ( pattern ) ;
198+ if ( ! match ) {
199+ continue ;
200+ }
201+
202+ const [ , generator , context ] = match ;
203+ return { generator, context } ;
204+ }
205+
206+ return undefined ;
207+ }
208+
162209 private parseMergeMessage ( message : string ) : MergeMessageMatch | undefined {
163210 for ( const item of mergeMessagePatterns ) {
164211 const match = item . pattern . exec ( message ) ;
@@ -201,11 +248,20 @@ export class ProblemDiagnosticActionResolver {
201248 return `update ${ updateLevel } for config file '${ fileName } ' from component '${ componentDisplayName } '.` ;
202249 }
203250
251+ private createMergeCommandUri ( localPath : string ) : vscode . Uri {
252+ const args = this . encodeCommandArgs ( [ localPath ] ) ;
253+ return vscode . Uri . parse ( `command:${ MERGE_FILE_COMMAND_ID } ?${ args } ` ) ;
254+ }
255+
204256 private createRunGeneratorCommandUri ( generator : string , context : string ) : vscode . Uri {
205257 const args = this . encodeCommandArgs ( [ { generator, context } ] ) ;
206258 return vscode . Uri . parse ( `command:${ RUN_GENERATOR_COMMAND_ID } ?${ args } ` ) ;
207259 }
208260
261+ private isAbsoluteFilePath ( filePath : string ) : boolean {
262+ return path . isAbsolute ( filePath ) || path . win32 . isAbsolute ( filePath ) ;
263+ }
264+
209265 private encodeFindInFilesArgs ( query : string ) : string {
210266 const args = {
211267 query : query ,
0 commit comments