@@ -14,17 +14,22 @@ import { killProcessTree } from './utils/processUtils';
1414import * as readline from 'readline' ;
1515import { URI } from 'vscode-uri' ;
1616import { promisify } from 'util' ;
17+ import { runGoEnv } from './goModules' ;
18+ import { ExecuteCommandParams , ExecuteCommandRequest } from 'vscode-languageserver-protocol' ;
1719
1820export class VulncheckResultViewProvider implements vscode . CustomTextEditorProvider {
1921 public static readonly viewType = 'vulncheck.view' ;
2022
21- public static register ( { extensionUri, subscriptions } : vscode . ExtensionContext ) : VulncheckResultViewProvider {
22- const provider = new VulncheckResultViewProvider ( extensionUri ) ;
23+ public static register (
24+ { extensionUri, subscriptions } : vscode . ExtensionContext ,
25+ goCtx : GoExtensionContext
26+ ) : VulncheckResultViewProvider {
27+ const provider = new VulncheckResultViewProvider ( extensionUri , goCtx ) ;
2328 subscriptions . push ( vscode . window . registerCustomEditorProvider ( VulncheckResultViewProvider . viewType , provider ) ) ;
2429 return provider ;
2530 }
2631
27- constructor ( private readonly extensionUri : vscode . Uri ) { }
32+ constructor ( private readonly extensionUri : vscode . Uri , private readonly goCtx : GoExtensionContext ) { }
2833
2934 /**
3035 * Called when our custom editor is opened.
@@ -39,7 +44,7 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
3944 webviewPanel . webview . html = this . getHtmlForWebview ( webviewPanel . webview ) ;
4045
4146 // Receive message from the webview.
42- webviewPanel . webview . onDidReceiveMessage ( this . handleMessage ) ;
47+ webviewPanel . webview . onDidReceiveMessage ( this . handleMessage , this ) ;
4348
4449 function updateWebview ( ) {
4550 webviewPanel . webview . postMessage ( { type : 'update' , text : document . getText ( ) } ) ;
@@ -105,7 +110,7 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
105110 </html>` ;
106111 }
107112
108- private handleMessage ( e : { type : string ; target ?: string } ) : void {
113+ private async handleMessage ( e : { type : string ; target ?: string ; dir ?: string } ) : Promise < void > {
109114 switch ( e . type ) {
110115 case 'open' :
111116 {
@@ -125,6 +130,16 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
125130 }
126131 }
127132 return ;
133+ case 'fix' :
134+ {
135+ if ( ! e . target || ! e . dir ) return ;
136+ const modFile = await getGoModFile ( vscode . Uri . file ( e . dir ) ) ;
137+ if ( modFile ) {
138+ await goplsUpgradeDependency ( this . goCtx , vscode . Uri . file ( modFile ) , [ e . target ] , false ) ;
139+ // TODO: run go mod tidy?
140+ }
141+ }
142+ return ;
128143 case 'snapshot-result' :
129144 // response for `snapshot-request`.
130145 return ;
@@ -134,6 +149,38 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
134149 }
135150}
136151
152+ const GOPLS_UPGRADE_DEPENDENCY = 'gopls.upgrade_dependency' ;
153+ async function goplsUpgradeDependency (
154+ goCtx : GoExtensionContext ,
155+ goModFileUri : vscode . Uri ,
156+ goCmdArgs : string [ ] ,
157+ addRequire : boolean
158+ ) : Promise < void > {
159+ const { languageClient } = goCtx ;
160+ const uri = languageClient ?. code2ProtocolConverter . asUri ( goModFileUri ) ;
161+ const params : ExecuteCommandParams = {
162+ command : GOPLS_UPGRADE_DEPENDENCY ,
163+ arguments : [
164+ {
165+ URI : uri ,
166+ GoCmdArgs : goCmdArgs ,
167+ AddRequire : addRequire
168+ }
169+ ]
170+ } ;
171+ return await languageClient ?. sendRequest ( ExecuteCommandRequest . type , params ) ;
172+ }
173+
174+ async function getGoModFile ( dir : vscode . Uri ) : Promise < string | undefined > {
175+ try {
176+ const p = await runGoEnv ( dir , [ 'GOMOD' ] ) ;
177+ return p [ 'GOMOD' ] === '/dev/null' || p [ 'GOMOD' ] === 'NUL' ? '' : p [ 'GOMOD' ] ;
178+ } catch ( e ) {
179+ vscode . window . showErrorMessage ( `Failed to find 'go.mod' for ${ dir } : ${ e } ` ) ;
180+ }
181+ return ;
182+ }
183+
137184export class VulncheckProvider {
138185 static scheme = 'govulncheck' ;
139186 static setup ( { subscriptions } : vscode . ExtensionContext , goCtx : GoExtensionContext ) {
0 commit comments