diff --git a/src/events/onOpenFile.ts b/src/events/onOpenFile.ts index d248126..77ec081 100644 --- a/src/events/onOpenFile.ts +++ b/src/events/onOpenFile.ts @@ -4,6 +4,7 @@ import { AnalyticsService } from '../services/analyticsService'; import { AbstractExecutor } from '../services/checkov/executors/abstractExecutor'; export class OnOpenFile { + public static async handle(document: vscode.TextDocument) { if (document && document.uri.scheme === 'file' && !AbstractExecutor.isScanInProgress) { const startTime = new Date(); @@ -14,4 +15,4 @@ export class OnOpenFile { } } } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 094ea66..bf99645 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,36 +1,40 @@ import * as vscode from 'vscode'; -import {registerCommands} from './commands'; -import {CONFIG} from './config'; -import {COMMAND} from './constants'; -import {registerWindowEvents, registerWorkspaceEvents} from './events'; -import logger, {initiateLogger} from './logger'; -import {initializeServices} from './services'; -import {initializeAnalyticsService} from './services/analyticsService'; -import {initializeAuthenticationService} from './services/authenticationService'; -import {CustomersModulesService, initializeCustomersModulesService} from './services/customersModulesService'; -import {lineClickDisposable, registerCustomHighlight} from './services/customPopupService'; -import {initializeInstallationId} from './utils'; -import {registerCheckovResultView} from './views/interface/checkovResult'; -import {registerSidebar} from './views/interface/primarySidebar'; +import { registerCommands } from './commands'; +import { CONFIG } from './config'; +import { COMMAND } from './constants'; +import { registerWindowEvents, registerWorkspaceEvents } from './events'; +import logger, { initiateLogger } from './logger'; +import { initializeServices } from './services'; +import { initializeAnalyticsService } from './services/analyticsService'; +import { initializeAuthenticationService } from './services/authenticationService'; +import { CustomersModulesService, initializeCustomersModulesService } from './services/customersModulesService'; +import { lineClickDisposable, registerCustomHighlight } from './services/customPopupService'; +import { initializeInstallationId } from './utils'; +import { registerCheckovResultView } from './views/interface/checkovResult'; +import { registerSidebar } from './views/interface/primarySidebar'; export async function activate(context: vscode.ExtensionContext) { - initiateLogger(context.logUri.fsPath); - logger.info(`Initiating Prisma Cloud VS Code extension version ${vscode.extensions.getExtension(CONFIG.extensionId)?.packageJSON.version}`); - logger.info(`Plugin path: ${context.extensionPath}`); - initializeInstallationId(context); - CustomersModulesService.loadCachedData(context); - await initializeAuthenticationService(context); - await initializeCustomersModulesService(context); - initializeAnalyticsService(context); - registerCommands(context); - initializeServices(context); - registerWindowEvents(); - registerWorkspaceEvents(); - registerSidebar(); - registerCheckovResultView(context); - registerCustomHighlight(context); - vscode.commands.executeCommand(COMMAND.CHECKOV_INSTALL, [context]); + try { + initiateLogger(context.logUri.fsPath); + logger.info(`Initiating Prisma Cloud VS Code extension version ${vscode.extensions.getExtension(CONFIG.extensionId)?.packageJSON.version}`); + logger.info(`Plugin path: ${context.extensionPath}`); + initializeInstallationId(context); + CustomersModulesService.loadCachedData(context); + await initializeAuthenticationService(context); + await initializeCustomersModulesService(context); + initializeAnalyticsService(context); + registerCommands(context); + initializeServices(context); + registerWindowEvents(); + registerWorkspaceEvents(); + registerSidebar(); + registerCheckovResultView(context); + registerCustomHighlight(context); + vscode.commands.executeCommand(COMMAND.CHECKOV_INSTALL, [context]); + } catch (e) { + logger.crit('Failed to initialize extension', e); + } } export function deactivate() { diff --git a/src/services/filesService.ts b/src/services/filesService.ts index 34a93f2..4ca609c 100644 --- a/src/services/filesService.ts +++ b/src/services/filesService.ts @@ -4,11 +4,6 @@ import { CheckovResult } from '../types'; import { formatWindowsAbsoluteFilePath, isWindows } from '../utils'; export class FilesService { - private static context: vscode.ExtensionContext; - - public static initialize(context: vscode.ExtensionContext) { - FilesService.context = context; - } public static async openResult(result: CheckovResult, line: number = 1) { if (line < 1) { @@ -17,11 +12,22 @@ export class FilesService { if (!vscode.window.activeTextEditor) { vscode.commands.executeCommand('workbench.action.previousEditor'); } - let filePath; + try { + return await this.openFile(result.file_abs_path, line); + } catch (e: any) { + // There's a bug in Checkov that returns file_abs_path as a relative path instead of absolute path on full scans + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]; + if (workspaceFolder) { + logger.warn(`Failed to open file ${result.file_abs_path}, will try to open relative to workspace`); + return this.openFile(workspaceFolder.uri.fsPath + result.file_abs_path, line); + } + logger.error(`Failed to open file ${result.file_abs_path}: ${e.message}`, e); + } + } + + private static openFile(filePath: string, line: number) { if (isWindows()) { - filePath = formatWindowsAbsoluteFilePath(result.file_abs_path); - } else { - filePath = result.file_abs_path; + filePath = formatWindowsAbsoluteFilePath(filePath); } logger.info(`Opening file at ${filePath}`); return vscode.window.showTextDocument(vscode.Uri.file(filePath), { selection: new vscode.Range(line - 1, 0, line - 1, 0) }); diff --git a/src/services/index.ts b/src/services/index.ts index 98736ac..56831e3 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -1,17 +1,15 @@ import * as vscode from 'vscode'; -import { ResultsService, FilesService, DiagnosticsService } from './'; +import {DiagnosticsService, ResultsService} from './'; export function initializeServices(context: vscode.ExtensionContext) { DiagnosticsService.initialize(context); ResultsService.initialize(context); - FilesService.initialize(context); } -export * from './checkov'; export * from './categoriesService'; -export * from './resultsService'; -export * from './filesService'; +export * from './checkov'; export * from './diagnosticsService'; -export * from './suppresService'; -export * from './fixService'; \ No newline at end of file +export * from './fixService'; +export * from './resultsService'; +export * from './suppresService'; \ No newline at end of file diff --git a/src/services/resultsService.ts b/src/services/resultsService.ts index d79f8d5..45feadd 100644 --- a/src/services/resultsService.ts +++ b/src/services/resultsService.ts @@ -70,12 +70,7 @@ export class ResultsService { public static getByFilePath(filePath: string) { const results = ResultsService.get(); - return results.filter(result => { - if (isWindows()) { - return formatWindowsAbsoluteFilePath(result.file_abs_path) === formatWindowsAbsoluteFilePath(filePath); - } - return result.file_abs_path === filePath; - }); + return results.filter(result => this.isSameFilePath(filePath, result)); } public static store(results: CheckovResult[]) { @@ -86,18 +81,23 @@ export class ResultsService { public static storeByFiles(files: string[], results: CheckovResult[]) { const storedResults = ResultsService.get(); const updatedResults = [ - ...storedResults.filter((result) => { - if (isWindows()) { - return !files.some(file => formatWindowsAbsoluteFilePath(file) === formatWindowsAbsoluteFilePath(result.file_abs_path)); - } - return !files.includes(result.file_abs_path); - }), + ...storedResults.filter((result) => !files.some(file => this.isSameFilePath(file, result))), ...results, ]; return ResultsService.store(updatedResults); } + private static isSameFilePath(filePath: string, result: CheckovResult) { + // There's a bug in Checkov that returns file_abs_path as a relative path instead of absolute path on full scans + const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + if (isWindows()) { + return formatWindowsAbsoluteFilePath(result.file_abs_path) === formatWindowsAbsoluteFilePath(filePath) || + formatWindowsAbsoluteFilePath(workspaceFolder + result.file_abs_path) === formatWindowsAbsoluteFilePath(filePath); + } + return result.file_abs_path === filePath || workspaceFolder + result.file_abs_path === filePath; + } + public static clear() { ResultsService.context.workspaceState.update(CONFIG.storage.resultsKey, undefined); } diff --git a/src/utils/index.ts b/src/utils/index.ts index b35f947..310a36d 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -25,7 +25,7 @@ export const formatWindowsFilePath = (path: string): string => { }; export const formatWindowsAbsoluteFilePath = (path: string): string => { - const splitPath = path.replace(/\\/g, '/').replace(/^\/+/g, '').split('/'); + const splitPath = path.replace(/\\/g, '/').replace(/\/+/g, '/').replace(/^\/+/g, '').split('/'); splitPath[0] = splitPath[0].toLocaleUpperCase() + (splitPath[0].endsWith(':') ? '' : ':'); return splitPath.join('/'); }; diff --git a/src/views/interface/checkovResult/messages/focusString.ts b/src/views/interface/checkovResult/messages/focusString.ts index abde020..40b31b4 100644 --- a/src/views/interface/checkovResult/messages/focusString.ts +++ b/src/views/interface/checkovResult/messages/focusString.ts @@ -1,13 +1,13 @@ -import { FilesService } from '../../../../services'; -import { CheckovResult } from '../../../../types'; +import {CheckovResult} from '../../../../types'; +import {FilesService} from "../../../../services/filesService"; export class FocusString { + public static async handle({ result, row }: { result: CheckovResult, row: number }) { if (result && row) { await FilesService.openResult(result, row); return; } - throw new Error('There is no repo file path of file line to focus'); } } \ No newline at end of file diff --git a/src/views/interface/primarySidebar/dataProviders/resultTreeDataProvider.ts b/src/views/interface/primarySidebar/dataProviders/resultTreeDataProvider.ts index 832f890..35180c9 100644 --- a/src/views/interface/primarySidebar/dataProviders/resultTreeDataProvider.ts +++ b/src/views/interface/primarySidebar/dataProviders/resultTreeDataProvider.ts @@ -1,12 +1,13 @@ import * as vscode from 'vscode'; -import {getPrismaApiUrl} from '../../../../config/configUtils'; -import {CHECKOV_RESULT_CATEGORY} from '../../../../constants'; +import { getPrismaApiUrl } from '../../../../config/configUtils'; +import { CHECKOV_RESULT_CATEGORY } from '../../../../constants'; import logger from '../../../../logger'; -import {CategoriesService, FilesService, ResultsService} from '../../../../services'; -import {CheckovResult} from '../../../../types'; -import {CheckovResultWebviewPanel} from '../../checkovResult'; -import {TreeService} from '../services/treeService'; +import { CategoriesService, ResultsService } from '../../../../services'; +import { FilesService } from '../../../../services/filesService'; +import { CheckovResult } from '../../../../types'; +import { CheckovResultWebviewPanel } from '../../checkovResult'; +import { TreeService } from '../services/treeService'; export class ResultTreeDataProvider implements vscode.TreeDataProvider {