diff --git a/src/snyk/snykOss/codeActions/vulnerabilityCodeActionProviderLS.ts b/src/snyk/snykOss/codeActions/vulnerabilityCodeActionProviderLS.ts new file mode 100644 index 000000000..de35e9bdb --- /dev/null +++ b/src/snyk/snykOss/codeActions/vulnerabilityCodeActionProviderLS.ts @@ -0,0 +1,80 @@ +import { IAnalytics } from '../../common/analytics/itly'; +import { OpenCommandIssueType, OpenIssueCommandArg } from '../../common/commands/types'; +import { SNYK_OPEN_ISSUE_COMMAND } from '../../common/constants/commands'; +import { IDE_NAME } from '../../common/constants/general'; +import { ICodeActionKindAdapter } from '../../common/vscode/codeAction'; +import { + CodeAction, + CodeActionContext, + CodeActionKind, + CodeActionProvider, + Command, + ProviderResult, + Range, + Selection, + TextDocument, +} from '../../common/vscode/types'; +import { DIAGNOSTICS_OSS_COLLECTION_NAME } from '../../snykCode/constants/analysis'; +import { messages } from '../messages/vulnerabilityCount'; +import { isResultCliError } from '../ossResult'; +import { OssService } from '../services/ossService'; +import { ModuleVulnerabilityCountProviderLS } from '../services/vulnerabilityCount/vulnerabilityCountProviderLS'; + +export class VulnerabilityCodeActionProviderLS implements CodeActionProvider { + public codeActionKinds: ReadonlyArray = [this.codeActionKindProvider.getQuickFix()]; + + constructor( + private readonly vulnerabilityCountProvider: ModuleVulnerabilityCountProviderLS, + private readonly codeActionKindProvider: ICodeActionKindAdapter, + private readonly analytics: IAnalytics, + ) {} + + async provideCodeActions( + document: TextDocument, + _: Range | Selection, + context: CodeActionContext, + ): Promise> { + const ossDiagnostics = context.diagnostics.filter(d => d.source === DIAGNOSTICS_OSS_COLLECTION_NAME); + if (!ossDiagnostics.length) { + return; + } + + const ossResult = this.vulnerabilityCountProvider.getResultArray(); + if (!ossResult) { + return; + } + + const fileResult = ossResult.find( + res => !isResultCliError(res) && this.vulnerabilityCountProvider.isFilePartOfOssTest(document.fileName, res), + ); + + if (!fileResult || isResultCliError(fileResult)) { + return; + } + + for (const diagnostic of ossDiagnostics) { + const vulnerability = fileResult.vulnerabilities.find(vuln => vuln.id === diagnostic.code); + if (!vulnerability) { + continue; + } + + const command: Command = { + command: SNYK_OPEN_ISSUE_COMMAND, + title: messages.showMostSevereVulnerability, + arguments: [ + { + issueType: OpenCommandIssueType.OssVulnerability, + issue: await OssService.getOssIssueCommandArg(vulnerability, fileResult.vulnerabilities), + } as OpenIssueCommandArg, + ], + }; + + this.analytics.logQuickFixIsDisplayed({ + quickFixType: ['Show Most Severe Vulnerability'], + ide: IDE_NAME, + }); + + return [command]; + } + } +} diff --git a/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountServiceLS.ts b/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountServiceLS.ts index c8159c81a..ab4b58355 100644 --- a/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountServiceLS.ts +++ b/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountServiceLS.ts @@ -1,6 +1,7 @@ import { Subscription } from 'rxjs'; import { IAnalytics } from '../../../common/analytics/itly'; import { IConfiguration } from '../../../common/configuration/configuration'; +import { HTML, JAVASCRIPT, PJSON, TYPESCRIPT } from '../../../common/constants/languageConsts'; import { ILog } from '../../../common/logger/interfaces'; import { getSupportedLanguage, isValidModuleName } from '../../../common/parsing'; import { ModuleParserProvider } from '../../../common/services/moduleParserProvider'; @@ -11,6 +12,7 @@ import { Diagnostic, DiagnosticCollection, Disposable, TextDocument } from '../. import { IVSCodeWindow } from '../../../common/vscode/window'; import { IVSCodeWorkspace } from '../../../common/vscode/workspace'; import { DIAGNOSTICS_OSS_COLLECTION_NAME } from '../../../snykCode/constants/analysis'; +import { VulnerabilityCodeActionProviderLS } from '../../codeActions/vulnerabilityCodeActionProviderLS'; import { EditorDecorator } from '../../editor/editorDecorator'; import { VulnerabilityCountHoverProvider } from '../../hoverProvider/vulnerabilityCountHoverProvider'; import { messages } from '../../messages/vulnerabilityCount'; @@ -67,19 +69,18 @@ export class OssVulnerabilityCountServiceLS implements Disposable { // Subscribe to OSS scan finished updates this.ossScanFinishedSubscription = this.ossService.newResultAvailable$.subscribe(() => this.processActiveEditor()); - // [JAVASCRIPT, TYPESCRIPT, PJSON, HTML].forEach(language => { - // const provider = new VulnerabilityCodeActionProvider( - // this.ossService, - // this.vulnerabilityCountProvider, - // this.codeActionKindProvider, - // this.analytics, - // ); - // this.disposables.push( - // this.languages.registerCodeActionsProvider(language, provider, { - // providedCodeActionKinds: provider.codeActionKinds, - // }), - // ); - //}); + [JAVASCRIPT, TYPESCRIPT, PJSON, HTML].forEach(language => { + const provider = new VulnerabilityCodeActionProviderLS( + this.vulnerabilityCountProvider, + this.codeActionKindProvider, + this.analytics, + ); + this.disposables.push( + this.languages.registerCodeActionsProvider(language, provider, { + providedCodeActionKinds: provider.codeActionKinds, + }), + ); + }); this.processActiveEditor();