@@ -14,17 +14,22 @@ import { killProcessTree } from './utils/processUtils';
14
14
import * as readline from 'readline' ;
15
15
import { URI } from 'vscode-uri' ;
16
16
import { promisify } from 'util' ;
17
+ import { runGoEnv } from './goModules' ;
18
+ import { ExecuteCommandParams , ExecuteCommandRequest } from 'vscode-languageserver-protocol' ;
17
19
18
20
export class VulncheckResultViewProvider implements vscode . CustomTextEditorProvider {
19
21
public static readonly viewType = 'vulncheck.view' ;
20
22
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 ) ;
23
28
subscriptions . push ( vscode . window . registerCustomEditorProvider ( VulncheckResultViewProvider . viewType , provider ) ) ;
24
29
return provider ;
25
30
}
26
31
27
- constructor ( private readonly extensionUri : vscode . Uri ) { }
32
+ constructor ( private readonly extensionUri : vscode . Uri , private readonly goCtx : GoExtensionContext ) { }
28
33
29
34
/**
30
35
* Called when our custom editor is opened.
@@ -39,7 +44,7 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
39
44
webviewPanel . webview . html = this . getHtmlForWebview ( webviewPanel . webview ) ;
40
45
41
46
// Receive message from the webview.
42
- webviewPanel . webview . onDidReceiveMessage ( this . handleMessage ) ;
47
+ webviewPanel . webview . onDidReceiveMessage ( this . handleMessage , this ) ;
43
48
44
49
function updateWebview ( ) {
45
50
webviewPanel . webview . postMessage ( { type : 'update' , text : document . getText ( ) } ) ;
@@ -105,7 +110,7 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
105
110
</html>` ;
106
111
}
107
112
108
- private handleMessage ( e : { type : string ; target ?: string } ) : void {
113
+ private async handleMessage ( e : { type : string ; target ?: string ; dir ?: string } ) : Promise < void > {
109
114
switch ( e . type ) {
110
115
case 'open' :
111
116
{
@@ -125,6 +130,16 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
125
130
}
126
131
}
127
132
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 ;
128
143
case 'snapshot-result' :
129
144
// response for `snapshot-request`.
130
145
return ;
@@ -134,6 +149,38 @@ export class VulncheckResultViewProvider implements vscode.CustomTextEditorProvi
134
149
}
135
150
}
136
151
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
+
137
184
export class VulncheckProvider {
138
185
static scheme = 'govulncheck' ;
139
186
static setup ( { subscriptions } : vscode . ExtensionContext , goCtx : GoExtensionContext ) {
0 commit comments