From 89cbe8f80b68e135b40b032dc5c0ac9ca4690632 Mon Sep 17 00:00:00 2001 From: carlos-snyk <50542733+carlos-snyk@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:46:50 +0100 Subject: [PATCH] refactor: remove unused exports/variables (#446) * refactor: remove unused exports/variables * chore: remove empty file --------- Co-authored-by: Bastian Doetsch --- src/snyk/base/messages/loginMessages.ts | 4 - src/snyk/base/modules/interfaces.ts | 3 - src/snyk/cli/process.ts | 99 ------- src/snyk/cli/services/cliService.ts | 161 ---------- src/snyk/cli/supportedPlatforms.ts | 6 +- src/snyk/common/api/headers.ts | 5 - src/snyk/common/commands/types.ts | 9 - src/snyk/common/constants/commands.ts | 1 - src/snyk/common/constants/general.ts | 10 +- src/snyk/common/constants/globalState.ts | 1 - src/snyk/common/constants/languageConsts.ts | 2 - src/snyk/common/constants/views.ts | 1 - src/snyk/common/languageServer/middleware.ts | 2 +- src/snyk/common/languageServer/settings.ts | 13 - .../languageServer/supportedPlatforms.ts | 4 - src/snyk/common/languageServer/types.ts | 3 +- src/snyk/common/proxy.ts | 2 +- src/snyk/common/services/learnService.ts | 2 +- .../common/services/viewManagerService.ts | 4 +- src/snyk/common/views/treeNode.ts | 4 +- src/snyk/common/vscode/commands.ts | 2 +- src/snyk/common/vscode/env.ts | 2 +- src/snyk/common/vscode/hover.ts | 12 - src/snyk/common/vscode/languages.ts | 2 +- src/snyk/common/vscode/secretStorage.ts | 2 +- src/snyk/common/vscode/types.ts | 6 - src/snyk/common/vscode/window.ts | 2 +- src/snyk/snykCode/codeSettings.ts | 2 +- src/snyk/snykCode/constants/analysis.ts | 16 - .../snykCode/hoverProvider/hoverProvider.ts | 49 --- src/snyk/snykCode/interfaces.ts | 60 +--- src/snyk/snykCode/utils/analysisUtils.ts | 278 ------------------ src/snyk/snykCode/utils/issueUtils.ts | 2 +- src/snyk/snykOss/interfaces.ts | 12 +- .../vulnerabilityCount/importedModule.ts | 2 +- .../ossVulnerabilityCountService.ts | 7 - .../parsers/packageJsonParser.ts | 6 +- .../snykOss/watchers/manifestFileWatcher.ts | 59 ---- src/test/unit/cli/process.test.ts | 91 ------ src/test/unit/cli/services/cliService.test.ts | 139 --------- .../common/languageServer/settings.test.ts | 16 +- src/test/unit/mocks/uri.mock.ts | 4 +- src/test/unit/mocks/workspace.mock.ts | 8 - .../unit/snykCode/utils/analysisUtils.test.ts | 104 +------ 44 files changed, 29 insertions(+), 1190 deletions(-) delete mode 100644 src/snyk/base/messages/loginMessages.ts delete mode 100644 src/snyk/cli/process.ts delete mode 100644 src/snyk/common/api/headers.ts delete mode 100644 src/snyk/common/vscode/hover.ts delete mode 100644 src/snyk/snykCode/hoverProvider/hoverProvider.ts delete mode 100644 src/snyk/snykOss/watchers/manifestFileWatcher.ts delete mode 100644 src/test/unit/cli/process.test.ts delete mode 100644 src/test/unit/cli/services/cliService.test.ts diff --git a/src/snyk/base/messages/loginMessages.ts b/src/snyk/base/messages/loginMessages.ts deleted file mode 100644 index f5711678e..000000000 --- a/src/snyk/base/messages/loginMessages.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const messages = { - loginFailed: 'Login of new user has failed', - sessionCheckFailed: 'Failed to check user session on server', -}; diff --git a/src/snyk/base/modules/interfaces.ts b/src/snyk/base/modules/interfaces.ts index e43446fbb..a3a5d5f9c 100644 --- a/src/snyk/base/modules/interfaces.ts +++ b/src/snyk/base/modules/interfaces.ts @@ -29,6 +29,3 @@ export interface IExtension extends IBaseSnykModule, ISnykLib { activate(context: VSCodeExtensionContext): void; restartLanguageServer(): Promise; } - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type errorType = Error | any; diff --git a/src/snyk/cli/process.ts b/src/snyk/cli/process.ts deleted file mode 100644 index fdc7c9334..000000000 --- a/src/snyk/cli/process.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { ChildProcessWithoutNullStreams, spawn } from 'child_process'; -import { OAuthToken } from '../base/services/authenticationService'; -import { Configuration, IConfiguration } from '../common/configuration/configuration'; -import { ILog } from '../common/logger/interfaces'; -import { getVsCodeProxy } from '../common/proxy'; -import { IVSCodeWorkspace } from '../common/vscode/workspace'; -import { CLI_INTEGRATION_NAME } from './contants/integration'; -import { CliError } from './services/cliService'; - -export class CliProcess { - private runningProcess: ChildProcessWithoutNullStreams | null; - - constructor( - private readonly logger: ILog, - private readonly config: IConfiguration, - private readonly workspace: IVSCodeWorkspace, - ) {} - - /** - * Returns CLI output given provided arguments. - */ - async spawn(cliPath: string, cwd: string, args: readonly string[]): Promise { - const processEnv = await this.getProcessEnv(); - - return new Promise((resolve, reject) => { - let output = ''; - - // file deepcode ignore ArrayMethodOnNonArray: readonly string[] is an array of strings - this.logger.info(`Running "${cliPath} ${args.join(' ')}".`); - - this.runningProcess = spawn(cliPath, args, { env: { ...process.env, ...processEnv }, cwd }); - - this.runningProcess.stdout.setEncoding('utf8'); - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - this.runningProcess.stdout.on('data', (data: string | Buffer) => (output += data)); - - this.runningProcess.on('error', err => { - this.cleanupProcess(); - reject(err); - }); - this.runningProcess.on('close', (_, signal) => { - this.cleanupProcess(); - - // Cancellation process kill was issued - if (signal === 'SIGTERM') { - return reject(new CliError('', '', true)); - } - - // Treat as succesful termination - resolve(output); - }); - }); - } - - kill(): boolean { - return !this.runningProcess || this.runningProcess.kill('SIGTERM'); - } - - async getProcessEnv(): Promise { - let env = { - SNYK_INTEGRATION_NAME: CLI_INTEGRATION_NAME, - SNYK_INTEGRATION_VERSION: await Configuration.getVersion(), - SNYK_API: this.config.snykOssApiEndpoint, - SNYK_CFG_ORG: this.config.organization, - } as NodeJS.ProcessEnv; - - const vscodeProxy = getVsCodeProxy(this.workspace); - if (vscodeProxy && !process.env.HTTP_PROXY && !process.env.HTTPS_PROXY) { - env = { - ...env, - HTTP_PROXY: vscodeProxy, - HTTPS_PROXY: vscodeProxy, - }; - } - - const token = await this.config.getToken(); - if (token && this.config.snykOssApiEndpoint.indexOf('snykgov.io') > 1) { - const oauthToken = JSON.parse(token) as OAuthToken; - env = { - ...env, - SNYK_OAUTH_TOKEN: oauthToken.access_token, - }; - } else { - env = { - ...env, - SNYK_TOKEN: token, - }; - } - - return env; - } - - private cleanupProcess() { - if (this.runningProcess) { - this.runningProcess.removeAllListeners(); - this.runningProcess = null; - } - } -} diff --git a/src/snyk/cli/services/cliService.ts b/src/snyk/cli/services/cliService.ts index d4dbc4130..6b6a821a7 100644 --- a/src/snyk/cli/services/cliService.ts +++ b/src/snyk/cli/services/cliService.ts @@ -1,164 +1,3 @@ -import { firstValueFrom } from 'rxjs'; -import parseArgsStringToArgv from 'string-argv'; -import { AnalysisStatusProvider } from '../../common/analysis/statusProvider'; -import { IConfiguration } from '../../common/configuration/configuration'; -import { IWorkspaceTrust } from '../../common/configuration/trustedFolders'; -import { ErrorHandler } from '../../common/error/errorHandler'; -import { ILanguageServer } from '../../common/languageServer/languageServer'; -import { ILog } from '../../common/logger/interfaces'; -import { messages as analysisMessages } from '../../common/messages/analysisMessages'; -import { DownloadService } from '../../common/services/downloadService'; -import { ExtensionContext } from '../../common/vscode/extensionContext'; -import { IVSCodeWorkspace } from '../../common/vscode/workspace'; -import { CliExecutable } from '../cliExecutable'; -import { CliProcess } from '../process'; - export class CliError { constructor(public error: string | Error | unknown, public path?: string, public isCancellation = false) {} } - -export abstract class CliService extends AnalysisStatusProvider { - protected abstract readonly command: string[]; - protected result: CliResult | CliError | undefined; - - private cliProcess?: CliProcess; - private _isCliReady: boolean; - private _isAnyWorkspaceFolderTrusted = true; - - constructor( - protected readonly extensionContext: ExtensionContext, - protected readonly logger: ILog, - protected readonly config: IConfiguration, - protected readonly workspace: IVSCodeWorkspace, - protected readonly downloadService: DownloadService, - protected readonly languageServer: ILanguageServer, - protected readonly workspaceTrust: IWorkspaceTrust, - ) { - super(); - } - - get isCliReady(): boolean { - return this._isCliReady; - } - - get isAnyWorkspaceFolderTrusted(): boolean { - return this._isAnyWorkspaceFolderTrusted; - } - - async test(manualTrigger: boolean, reportTriggeredEvent: boolean): Promise { - this.ensureDependencies(); - - const currentCliPath = CliExecutable.getPath(this.extensionContext.extensionPath, this.config.getCliPath()); - const currentCliPathExists = await CliExecutable.exists( - this.extensionContext.extensionPath, - this.config.getCliPath(), - ); - await this.synchronizeCliPathIfNeeded(currentCliPath, currentCliPathExists); - if (currentCliPathExists) { - const cliPath = this.config.getCliPath(); - if (!cliPath) { - throw new Error('CLI path is not set, probably failed migration.'); - } - - this.logger.info(`Using CLI path ${cliPath}`); - this.languageServer.cliReady$.next(cliPath); - } - - // Prevent from CLI scan until Language Server downloads the CLI. - const cliPath = await firstValueFrom(this.languageServer.cliReady$); - this._isCliReady = true; - - const workspaceFolders = this.workspace.getWorkspaceFolders(); - if (workspaceFolders.length == 0) { - throw new Error('No workspace was opened.'); - } - - const foldersToTest = this.workspaceTrust.getTrustedFolders(this.config, workspaceFolders); - if (foldersToTest.length == 0) { - this.handleNoTrustedFolders(); - this.logger.info(`Skipping Open Source scan. ${analysisMessages.noWorkspaceTrustDescription}`); - return; - } - this._isAnyWorkspaceFolderTrusted = true; - - // Start test - this.analysisStarted(); - this.beforeTest(manualTrigger, reportTriggeredEvent); - this.result = undefined; - - if (this.cliProcess) { - const killed = this.cliProcess.kill(); - if (!killed) this.logger.error('Failed to kill an already running CLI instance.'); - } - - this.cliProcess = new CliProcess(this.logger, this.config, this.workspace); - const args = this.buildArguments(foldersToTest); - - let output: string; - try { - output = await this.cliProcess.spawn(cliPath, foldersToTest[0], args); - } catch (spawnError) { - if (spawnError instanceof CliError) { - return spawnError; - } - - const result = new CliError(spawnError, ''); - this.finalizeTest(result); - return result; - } - - const mappedResult = this.mapToResultType(output); - this.finalizeTest(mappedResult); - - return mappedResult; - } - - // Synchronizes user configuration with CLI path passed to the Snyk LS. - // TODO: Remove in VS Code + Language Server feature cleanup. - private async synchronizeCliPathIfNeeded(cliPath: string, cliPathExists: boolean) { - if (!this.config.getCliPath() && cliPathExists) { - this.logger.info("Synchronising extension's CLI path with Language Server"); - try { - await this.config.setCliPath(cliPath); - } catch (e) { - ErrorHandler.handle(e, this.logger, "Failed to synchronize extension's CLI path with Language Server"); - } - } - - return cliPath; - } - - protected abstract mapToResultType(rawCliResult: string): CliResult; - - protected abstract ensureDependencies(): void; - - protected abstract beforeTest(manualTrigger: boolean, reportTriggeredEvent: boolean): void; - protected abstract afterTest(result: CliResult | CliError): void; - - handleNoTrustedFolders() { - this._isAnyWorkspaceFolderTrusted = false; - } - - private buildArguments(foldersToTest: ReadonlyArray): string[] { - const args = []; - - args.push(...this.command); - args.push(...foldersToTest); - args.push('--json'); - - const additionalParams = this.config.getAdditionalCliParameters(); - if (additionalParams) { - args.push(...parseArgsStringToArgv(additionalParams.trim())); - } - - return args; - } - - // To be called to finalise the analysis - public finalizeTest(result: CliResult | CliError): void { - this.result = result; - - this.analysisFinished(); - this.afterTest(result); - } -} diff --git a/src/snyk/cli/supportedPlatforms.ts b/src/snyk/cli/supportedPlatforms.ts index 73fbe5bae..4fb3e84c1 100644 --- a/src/snyk/cli/supportedPlatforms.ts +++ b/src/snyk/cli/supportedPlatforms.ts @@ -1,6 +1,2 @@ -export const SupportedCliPlatformsList = ['linux', 'win32', 'darwin'] as const; +const SupportedCliPlatformsList = ['linux', 'win32', 'darwin'] as const; export type CliSupportedPlatform = typeof SupportedCliPlatformsList[number]; - -export function isPlatformSupported(platform: NodeJS.Platform): boolean { - return SupportedCliPlatformsList.find(p => p === platform) !== undefined; -} diff --git a/src/snyk/common/api/headers.ts b/src/snyk/common/api/headers.ts deleted file mode 100644 index 9b9bec6f0..000000000 --- a/src/snyk/common/api/headers.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const DEFAULT_API_HEADERS: Readonly> = { - Accept: 'application/json', - 'Content-Type': 'application/json; charset=utf-8', - 'Accept-Encoding': 'gzip', -}; diff --git a/src/snyk/common/commands/types.ts b/src/snyk/common/commands/types.ts index 2fee394d9..66df6f6aa 100644 --- a/src/snyk/common/commands/types.ts +++ b/src/snyk/common/commands/types.ts @@ -1,8 +1,6 @@ -import { completeFileSuggestionType } from '../../snykCode/interfaces'; import { CodeIssueCommandArg } from '../../snykCode/views/interfaces'; import { IacIssueCommandArg } from '../../snykIac/views/interfaces'; import { OssIssueCommandArg } from '../../snykOss/interfaces'; -import { CodeIssueData, Issue } from '../languageServer/types'; export enum OpenCommandIssueType { CodeIssue, @@ -14,10 +12,3 @@ export type OpenIssueCommandArg = { issue: CodeIssueCommandArg | IacIssueCommandArg | OssIssueCommandArg; issueType: OpenCommandIssueType; }; - -export const isCodeIssue = ( - _issue: completeFileSuggestionType | Issue | OssIssueCommandArg, - issueType: OpenCommandIssueType, -): _issue is Issue => { - return issueType === OpenCommandIssueType.CodeIssue; -}; diff --git a/src/snyk/common/constants/commands.ts b/src/snyk/common/constants/commands.ts index 7dbbb9c19..7ca96feff 100644 --- a/src/snyk/common/constants/commands.ts +++ b/src/snyk/common/constants/commands.ts @@ -2,7 +2,6 @@ export const VSCODE_GO_TO_SETTINGS_COMMAND = 'workbench.action.openSettings'; export const VSCODE_VIEW_CONTAINER_COMMAND = 'workbench.view.extension.snyk'; export const VSCODE_ADD_COMMENT_COMMAND = 'editor.action.addCommentLine'; -export const VSCODE_VIEW_OSS_VIEW_COMMAND = 'snyk.views.analysis.oss.focus'; // custom Snyk commands export const SNYK_START_COMMAND = 'snyk.start'; diff --git a/src/snyk/common/constants/general.ts b/src/snyk/common/constants/general.ts index c8b596a64..f2229f563 100644 --- a/src/snyk/common/constants/general.ts +++ b/src/snyk/common/constants/general.ts @@ -1,19 +1,11 @@ // Changing this requires changing display name in package.json. export const SNYK_NAME = 'Snyk Security'; export const SNYK_TOKEN_KEY = 'snyk.token'; -export const SNYK_UNIQUE_EXTENSION_NAME = 'Snyk Vulnerability Scanner'; +const SNYK_UNIQUE_EXTENSION_NAME = 'Snyk Vulnerability Scanner'; export const SNYK_PUBLISHER = 'snyk-security'; export const SNYK_NAME_EXTENSION = SNYK_UNIQUE_EXTENSION_NAME.toLowerCase().replace(/[()]/g, '').replace(/\s/g, '-'); -export const MAX_CONNECTION_RETRIES = 5; // max number of automatic retries before showing an error -export const IDE_NAME = 'Visual Studio Code'; export const IDE_NAME_SHORT = 'vscode'; export const COMMAND_DEBOUNCE_INTERVAL = 200; // 200 milliseconds export const DEFAULT_SCAN_DEBOUNCE_INTERVAL = 1000; // 1 second export const DEFAULT_LS_DEBOUNCE_INTERVAL = 1000; // 1 second -export const EXECUTION_THROTTLING_INTERVAL = 1000 * 10; // * 60 * 30; // 30 minutes -export const EXECUTION_PAUSE_INTERVAL = 1000 * 60 * 30; // 30 minutes export const REFRESH_VIEW_DEBOUNCE_INTERVAL = 200; // 200 milliseconds -// If CONNECTION_ERROR_RETRY_INTERVAL is smaller than EXECUTION_DEBOUNCE_INTERVAL it might get swallowed by the debouncer -export const CONNECTION_ERROR_RETRY_INTERVAL = DEFAULT_SCAN_DEBOUNCE_INTERVAL * 2 + 1000 * 3; - -export const SNYK_LEARN_API_CACHE_DURATION_IN_MS = 1000 * 60 * 60 * 24; // 1 day diff --git a/src/snyk/common/constants/globalState.ts b/src/snyk/common/constants/globalState.ts index cb62ac2eb..ff12e3a06 100644 --- a/src/snyk/common/constants/globalState.ts +++ b/src/snyk/common/constants/globalState.ts @@ -1,4 +1,3 @@ -export const MEMENTO_FIRST_INSTALL_DATE_KEY = 'snyk.firstInstallDate'; export const MEMENTO_ANONYMOUS_ID = 'snyk.anonymousId'; export const MEMENTO_LS_LAST_UPDATE_DATE = 'snyk.lsLastUpdateDate'; export const MEMENTO_LS_PROTOCOL_VERSION = 'snyk.lsProtocolVersion'; diff --git a/src/snyk/common/constants/languageConsts.ts b/src/snyk/common/constants/languageConsts.ts index 45d5b3ea9..e0f1bef36 100644 --- a/src/snyk/common/constants/languageConsts.ts +++ b/src/snyk/common/constants/languageConsts.ts @@ -7,5 +7,3 @@ export const JAVASCRIPT = 'javascript'; export const JAVASCRIPT_REACT = 'javascriptreact'; export const HTML = 'html'; export const PJSON = 'json'; - -export const SupportedLanguageIds = [TYPESCRIPT, TYPESCRIPT_REACT, JAVASCRIPT, JAVASCRIPT_REACT, HTML, PJSON]; diff --git a/src/snyk/common/constants/views.ts b/src/snyk/common/constants/views.ts index 6616a1ef5..d2e6819fb 100644 --- a/src/snyk/common/constants/views.ts +++ b/src/snyk/common/constants/views.ts @@ -1,5 +1,4 @@ export const SNYK_VIEW_WELCOME = 'snyk.views.welcome'; -export const SNYK_VIEW_FEATURES = 'snyk.views.features'; export const SNYK_VIEW_ANALYSIS_CODE_ENABLEMENT = 'snyk.views.analysis.code.enablement'; export const SNYK_VIEW_ANALYSIS_CODE_SECURITY = 'snyk.views.analysis.code.security'; export const SNYK_VIEW_ANALYSIS_CODE_QUALITY = 'snyk.views.analysis.code.quality'; diff --git a/src/snyk/common/languageServer/middleware.ts b/src/snyk/common/languageServer/middleware.ts index 1b695dc38..ed0dd6385 100644 --- a/src/snyk/common/languageServer/middleware.ts +++ b/src/snyk/common/languageServer/middleware.ts @@ -10,7 +10,7 @@ import type { } from '../vscode/types'; import { LanguageServerSettings, ServerSettings } from './settings'; -export type LanguageClientWorkspaceMiddleware = Partial & { +type LanguageClientWorkspaceMiddleware = Partial & { configuration: ( params: ConfigurationParams, token: CancellationToken, diff --git a/src/snyk/common/languageServer/settings.ts b/src/snyk/common/languageServer/settings.ts index 50b34e04e..eb7809ca6 100644 --- a/src/snyk/common/languageServer/settings.ts +++ b/src/snyk/common/languageServer/settings.ts @@ -40,19 +40,6 @@ export type ServerSettings = { deviceId?: string; }; -/** - * Transforms a boolean or undefined value into a string representation. - * It guarantees that undefined values are represented as 'true'. - * This utility is used to ensure feature flags are enabled by default - * when not explicitly set to false. - * - * @param {boolean | undefined} value - The value to transform. - * @returns {string} - The string 'true' if the value is undefined or truthy, 'false' if the value is false. - */ -export const defaultToTrue = (value: boolean | undefined): string => { - return `${value !== undefined ? value : true}`; -}; - export class LanguageServerSettings { static async fromConfiguration(configuration: IConfiguration, user: User): Promise { const featuresConfiguration = configuration.getFeaturesConfiguration(); diff --git a/src/snyk/common/languageServer/supportedPlatforms.ts b/src/snyk/common/languageServer/supportedPlatforms.ts index 8bc66a87a..7eaa14b6c 100644 --- a/src/snyk/common/languageServer/supportedPlatforms.ts +++ b/src/snyk/common/languageServer/supportedPlatforms.ts @@ -8,8 +8,4 @@ export const SupportedLsPlatformsList = [ 'windowsAmd64', ] as const; -export function isPlatformSupported(platform: string): boolean { - return SupportedLsPlatformsList.find(p => p === platform) !== undefined; -} - export type LsSupportedPlatform = typeof SupportedLsPlatformsList[number]; diff --git a/src/snyk/common/languageServer/types.ts b/src/snyk/common/languageServer/types.ts index fe995d829..e598be7c9 100644 --- a/src/snyk/common/languageServer/types.ts +++ b/src/snyk/common/languageServer/types.ts @@ -4,7 +4,6 @@ export enum ScanProduct { InfrastructureAsCode = 'iac', } -export type InProgress = 'inProgress'; export enum ScanStatus { InProgress = 'inProgress', Success = 'success', @@ -100,7 +99,7 @@ export type OssIssueData = { details: string; }; -export type Identifiers = { +type Identifiers = { CWE: string[]; CVE: string[]; }; diff --git a/src/snyk/common/proxy.ts b/src/snyk/common/proxy.ts index 7ae4f5cf0..76bf22b0e 100644 --- a/src/snyk/common/proxy.ts +++ b/src/snyk/common/proxy.ts @@ -62,7 +62,7 @@ export async function getProxyOptions( }; } -export function getVsCodeProxy(workspace: IVSCodeWorkspace): string | undefined { +function getVsCodeProxy(workspace: IVSCodeWorkspace): string | undefined { return workspace.getConfiguration('http', 'proxy'); } diff --git a/src/snyk/common/services/learnService.ts b/src/snyk/common/services/learnService.ts index fde6fd070..259bd9bec 100644 --- a/src/snyk/common/services/learnService.ts +++ b/src/snyk/common/services/learnService.ts @@ -2,7 +2,7 @@ import { SNYK_GET_LESSON_COMMAND } from '../constants/commands'; import { CodeIssueData, Issue } from '../languageServer/types'; import { IVSCodeCommands } from '../vscode/commands'; -export type Lesson = { +type Lesson = { url: string; title: string; }; diff --git a/src/snyk/common/services/viewManagerService.ts b/src/snyk/common/services/viewManagerService.ts index c1706b149..e003d109d 100644 --- a/src/snyk/common/services/viewManagerService.ts +++ b/src/snyk/common/services/viewManagerService.ts @@ -5,9 +5,9 @@ import { configuration } from '../configuration/instance'; import { REFRESH_VIEW_DEBOUNCE_INTERVAL } from '../constants/general'; import { TreeNode } from '../views/treeNode'; -export type ViewType = TreeView; +type ViewType = TreeView; -export class ViewContainer { +class ViewContainer { private container = new Map(); get(key: string): T | undefined { diff --git a/src/snyk/common/views/treeNode.ts b/src/snyk/common/views/treeNode.ts index d46e0a58d..9ecdf8893 100644 --- a/src/snyk/common/views/treeNode.ts +++ b/src/snyk/common/views/treeNode.ts @@ -38,7 +38,7 @@ export type InternalType = { isError?: boolean; }; -export interface INodeOptions { +interface INodeOptions { text: string; description?: string; descriptionTail?: string; @@ -56,7 +56,7 @@ export interface INodeOptions { internal?: InternalType; } -export type INode = TreeItem & { +type INode = TreeItem & { readonly internal: InternalType; }; diff --git a/src/snyk/common/vscode/commands.ts b/src/snyk/common/vscode/commands.ts index ad29c18ee..31933ee00 100644 --- a/src/snyk/common/vscode/commands.ts +++ b/src/snyk/common/vscode/commands.ts @@ -4,7 +4,7 @@ export interface IVSCodeCommands { executeCommand(command: string, ...rest: unknown[]): Thenable; } -export class VSCodeCommands implements IVSCodeCommands { +class VSCodeCommands implements IVSCodeCommands { executeCommand(command: string, ...rest: unknown[]): Thenable { return vscode.commands.executeCommand(command, ...rest); } diff --git a/src/snyk/common/vscode/env.ts b/src/snyk/common/vscode/env.ts index 736f95328..00f111f0a 100644 --- a/src/snyk/common/vscode/env.ts +++ b/src/snyk/common/vscode/env.ts @@ -7,7 +7,7 @@ export interface IVSCodeEnv { getAppHost(): string | undefined; } -export class VSCodeEnv implements IVSCodeEnv { +class VSCodeEnv implements IVSCodeEnv { getUiKind(): string { return vscode.UIKind[vscode.env.uiKind]; } diff --git a/src/snyk/common/vscode/hover.ts b/src/snyk/common/vscode/hover.ts deleted file mode 100644 index 4518ecc66..000000000 --- a/src/snyk/common/vscode/hover.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as vscode from 'vscode'; -import { Hover, MarkdownString, Range } from './types'; - -export interface IHoverAdapter { - create(contents: MarkdownString | MarkdownString[], range?: Range): Hover; -} - -export class HoverAdapter implements IHoverAdapter { - create(contents: vscode.MarkdownString | MarkdownString[], range?: Range): Hover { - return new vscode.Hover(contents, range); - } -} diff --git a/src/snyk/common/vscode/languages.ts b/src/snyk/common/vscode/languages.ts index 3deb382e0..7200ee976 100644 --- a/src/snyk/common/vscode/languages.ts +++ b/src/snyk/common/vscode/languages.ts @@ -31,7 +31,7 @@ export interface IVSCodeLanguages { ): Disposable; } -export class VSCodeLanguages implements IVSCodeLanguages { +class VSCodeLanguages implements IVSCodeLanguages { registerHoverProvider(selector: DocumentSelector, provider: HoverProvider): Disposable { return vscode.languages.registerHoverProvider(selector, provider); } diff --git a/src/snyk/common/vscode/secretStorage.ts b/src/snyk/common/vscode/secretStorage.ts index d9c81d003..5725b3e7e 100644 --- a/src/snyk/common/vscode/secretStorage.ts +++ b/src/snyk/common/vscode/secretStorage.ts @@ -1,6 +1,6 @@ import { ExtensionContext, Event, SecretStorage, SecretStorageChangeEvent } from './types'; -export interface ISecretStorageAdapter { +interface ISecretStorageAdapter { get(key: string): Promise; store(key: string, value: string): Promise; delete(key: string): Promise; diff --git a/src/snyk/common/vscode/types.ts b/src/snyk/common/vscode/types.ts index 0ce5f0664..c8564f23d 100644 --- a/src/snyk/common/vscode/types.ts +++ b/src/snyk/common/vscode/types.ts @@ -16,23 +16,18 @@ export enum DiagnosticSeverity { // map of vscode.DiagnosticSeverity } export type DocumentSelector = vscode.DocumentSelector; -export type DocumentFilter = vscode.DocumentFilter; export type HoverProvider = vscode.HoverProvider; -export type ProviderResult = vscode.ProviderResult; export type TextEditor = vscode.TextEditor; export type TextDocument = vscode.TextDocument; export type TextDocumentShowOptions = vscode.TextDocumentShowOptions; export type ViewColumn = vscode.ViewColumn; export type Position = vscode.Position; export type Range = vscode.Range; -export type Selection = vscode.Selection; export type SecretStorage = vscode.SecretStorage; export type SecretStorageChangeEvent = vscode.SecretStorageChangeEvent; export type Event = vscode.Event; export type Uri = vscode.Uri; -export type MarkedString = vscode.MarkedString; export type MarkdownString = vscode.MarkdownString; -export type Hover = vscode.Hover; export type CodeAction = vscode.CodeAction; export type CodeActionKind = vscode.CodeActionKind; export type CodeActionProvider = vscode.CodeActionProvider; @@ -58,6 +53,5 @@ export type ConfigurationParams = lsc.ConfigurationParams; export type CancellationToken = lsc.CancellationToken; export type ConfigurationRequestHandlerSignature = lsc.ConfigurationRequest.HandlerSignature; export type ResponseError = lsc.ResponseError; -export type InlineValueContext = lsc.InlineValueContext; export type InlineValueText = lsc.InlineValueText; export type LSPTextDocument = lst.TextDocument; diff --git a/src/snyk/common/vscode/window.ts b/src/snyk/common/vscode/window.ts index 7b63aa7e8..c38ae9104 100644 --- a/src/snyk/common/vscode/window.ts +++ b/src/snyk/common/vscode/window.ts @@ -38,7 +38,7 @@ export interface IVSCodeWindow { /** * A wrapper class for the vscode.window to provide centralised access to dealing with the current window of the editor. */ -export class VSCodeWindow implements IVSCodeWindow { +class VSCodeWindow implements IVSCodeWindow { getActiveTextEditor(): vscode.TextEditor | undefined { return vscode.window.activeTextEditor; } diff --git a/src/snyk/snykCode/codeSettings.ts b/src/snyk/snykCode/codeSettings.ts index face46032..d05b173f5 100644 --- a/src/snyk/snykCode/codeSettings.ts +++ b/src/snyk/snykCode/codeSettings.ts @@ -13,7 +13,7 @@ export interface ICodeSettings { getSastSettings(): Promise; } -export type SastSettings = { +type SastSettings = { sastEnabled: boolean; localCodeEngine: { enabled: boolean; diff --git a/src/snyk/snykCode/constants/analysis.ts b/src/snyk/snykCode/constants/analysis.ts index 814b590c9..c2d86b29f 100644 --- a/src/snyk/snykCode/constants/analysis.ts +++ b/src/snyk/snykCode/constants/analysis.ts @@ -1,28 +1,12 @@ -export const SNYK_SEVERITIES: { [key: string]: number } = { - information: 1, - warning: 2, - error: 3, -}; - export const IGNORE_ISSUE_BASE_COMMENT_TEXT = 'deepcode ignore'; export const FILE_IGNORE_ISSUE_BASE_COMMENT_TEXT = `file ${IGNORE_ISSUE_BASE_COMMENT_TEXT}`; export const IGNORE_ISSUE_REASON_TIP = ''; -export const SHOW_ISSUE_ACTION_NAME = 'Show this suggestion (Snyk)'; export const IGNORE_ISSUE_ACTION_NAME = 'Ignore this particular suggestion (Snyk)'; export const FILE_IGNORE_ACTION_NAME = 'Ignore this suggestion in current file (Snyk)'; -export const IGNORE_TIP_FOR_USER = "To ignore this issue for Snyk choose 'Ignore this issue' in QuickFix dropdown"; - -export const ISSUES_MARKERS_DECORATION_TYPE: { [key: string]: string } = { - border: '1px', - borderColor: 'green', - borderStyle: 'none none dashed none', -}; -export const DIAGNOSTICS_CODE_SECURITY_COLLECTION_NAME = 'Snyk Code Security'; -export const DIAGNOSTICS_CODE_QUALITY_COLLECTION_NAME = 'Snyk Code Quality'; export const DIAGNOSTICS_OSS_COLLECTION_NAME = 'Snyk Open Source Security'; export const DIAGNOSTICS_OSS_COLLECTION_NAME_LS = 'Snyk Open Source'; diff --git a/src/snyk/snykCode/hoverProvider/hoverProvider.ts b/src/snyk/snykCode/hoverProvider/hoverProvider.ts deleted file mode 100644 index 401252bc9..000000000 --- a/src/snyk/snykCode/hoverProvider/hoverProvider.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ILog } from '../../common/logger/interfaces'; -import { IHoverAdapter } from '../../common/vscode/hover'; -import { IVSCodeLanguages } from '../../common/vscode/languages'; -import { IMarkdownStringAdapter } from '../../common/vscode/markdownString'; -import { DiagnosticCollection, Disposable, Hover, Position, TextDocument } from '../../common/vscode/types'; -import { IGNORE_TIP_FOR_USER } from '../constants/analysis'; -import { ISnykCodeAnalyzer } from '../interfaces'; -import { IssueUtils } from '../utils/issueUtils'; - -export class DisposableHoverProvider implements Disposable { - private hoverProvider: Disposable | undefined; - - constructor( - private readonly analyzer: ISnykCodeAnalyzer, - private readonly logger: ILog, - private readonly vscodeLanguages: IVSCodeLanguages, - private readonly markdownStringAdapter: IMarkdownStringAdapter, - ) {} - - register(snykReview: DiagnosticCollection | undefined, hoverAdapter: IHoverAdapter): Disposable { - this.hoverProvider = this.vscodeLanguages.registerHoverProvider( - { scheme: 'file', language: '*' }, - { - provideHover: this.getHover(snykReview, hoverAdapter), - }, - ); - return this; - } - - getHover(snykReview: DiagnosticCollection | undefined, hoverAdapter: IHoverAdapter) { - return (document: TextDocument, position: Position): Hover | undefined => { - if (!snykReview || !snykReview.has(document.uri)) { - return undefined; - } - const currentFileReviewIssues = snykReview.get(document.uri); - const issue = IssueUtils.findIssueWithRange(position, currentFileReviewIssues); - if (issue) { - const ignoreMarkdown = this.markdownStringAdapter.get(IGNORE_TIP_FOR_USER); - return hoverAdapter.create(ignoreMarkdown); - } - }; - } - - dispose(): void { - if (this.hoverProvider) { - this.hoverProvider.dispose(); - } - } -} diff --git a/src/snyk/snykCode/interfaces.ts b/src/snyk/snykCode/interfaces.ts index 482a99ca2..e8dcc8fae 100644 --- a/src/snyk/snykCode/interfaces.ts +++ b/src/snyk/snykCode/interfaces.ts @@ -1,16 +1,4 @@ -import { AnalysisResultLegacy, FilePath, FileSuggestion, Suggestion } from '@snyk/code-client'; -import * as vscode from 'vscode'; -import { DiagnosticCollection, TextDocument } from 'vscode'; -import { IExtension } from '../base/modules/interfaces'; -import { IHoverAdapter } from '../common/vscode/hover'; -import { IMarkdownStringAdapter } from '../common/vscode/markdownString'; -import { Disposable } from '../common/vscode/types'; - -// TODO: remove after Code move to LS. -export type completeFileSuggestionType = ICodeSuggestion & - FileSuggestion & { - uri: string; - }; +import { TextDocument } from 'vscode'; export type openedTextEditorType = { fullPath: string; @@ -22,49 +10,3 @@ export type openedTextEditorType = { contentChanges: any[]; document: TextDocument; }; - -export interface IIssuesListOptions { - fileIssuesList: FilePath; - suggestions: Readonly; - fileUri: vscode.Uri; -} - -export type ICodeSuggestion = Suggestion & { - isSecurityType: boolean; -}; - -interface ICodeSuggestions { - [suggestionIndex: string]: Readonly; -} - -export interface ISnykCodeResult extends AnalysisResultLegacy { - suggestions: Readonly; -} - -export interface ISnykCodeAnalyzer extends Disposable { - codeSecurityReview: DiagnosticCollection | undefined; - codeQualityReview: DiagnosticCollection | undefined; - - registerHoverProviders( - codeSecurityHoverAdapter: IHoverAdapter, - codeQualityHoverAdapter: IHoverAdapter, - markdownStringAdapter: IMarkdownStringAdapter, - ): void; - registerCodeActionProviders( - codeSecurityCodeActionsProvider: Disposable, - codeQualityCodeActionsProvider: Disposable, - ): void; - - setAnalysisResults(results: AnalysisResultLegacy): void; - getAnalysisResults(): Readonly; - findSuggestion(diagnostic: vscode.Diagnostic): Readonly; - getFullSuggestion( - suggestionId: string, - uri: vscode.Uri, - position: vscode.Range, - ): Readonly; - checkFullSuggestion(suggestion: completeFileSuggestionType): boolean; - createReviewResults(): void; - updateReviewResultsPositions(extension: IExtension, updatedFile: openedTextEditorType): Promise; - refreshDiagnostics(): void; -} diff --git a/src/snyk/snykCode/utils/analysisUtils.ts b/src/snyk/snykCode/utils/analysisUtils.ts index f311ce96a..8c5e02cfd 100644 --- a/src/snyk/snykCode/utils/analysisUtils.ts +++ b/src/snyk/snykCode/utils/analysisUtils.ts @@ -2,297 +2,19 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import { AnalysisResultLegacy, FilePath, FileSuggestion, Marker, Suggestion } from '@snyk/code-client'; import path from 'path'; -import { IVSCodeLanguages } from '../../common/vscode/languages'; -import { - DecorationOptions, - Diagnostic, - DiagnosticRelatedInformation, - DiagnosticSeverity, - Range, - Uri, -} from '../../common/vscode/types'; -import { IUriAdapter } from '../../common/vscode/uri'; import { IVSCodeWorkspace } from '../../common/vscode/workspace'; import { FILE_IGNORE_ISSUE_BASE_COMMENT_TEXT, IGNORE_ISSUE_BASE_COMMENT_TEXT, IGNORE_ISSUE_REASON_TIP, - SNYK_SEVERITIES, } from '../constants/analysis'; -import { completeFileSuggestionType, ICodeSuggestion, ISnykCodeResult, openedTextEditorType } from '../interfaces'; -import { IssuePlacementPosition, IssueUtils } from './issueUtils'; - -export const createSnykSeveritiesMap = (): { [x: number]: { name: DiagnosticSeverity } } => { - const { information, error, warning } = SNYK_SEVERITIES; - - return { - [information]: { - name: DiagnosticSeverity.Information, - }, - [warning]: { name: DiagnosticSeverity.Warning }, - [error]: { name: DiagnosticSeverity.Error }, - }; -}; - -export const getVSCodeSeverity = (snykSeverity: number): DiagnosticSeverity => { - const { information, error, warning } = SNYK_SEVERITIES; - return ( - { - [information]: DiagnosticSeverity.Information, - [warning]: DiagnosticSeverity.Warning, - [error]: DiagnosticSeverity.Error, - }[snykSeverity] || DiagnosticSeverity.Information - ); -}; - -export const getSnykSeverity = (vscodeSeverity: DiagnosticSeverity): number => { - const { information, error, warning } = SNYK_SEVERITIES; - return { - [DiagnosticSeverity.Information]: information, - [DiagnosticSeverity.Warning]: warning, - [DiagnosticSeverity.Error]: error, - [DiagnosticSeverity.Hint]: information, - }[vscodeSeverity]; -}; - -export const createSnykProgress = (progress: number): number => { - const progressOffset = 100; - return Math.round(progress * progressOffset); -}; - -export const createIssueRange = (position: IssuePlacementPosition, languages: IVSCodeLanguages): Range => { - return languages.createRange( - Math.max(0, position.rows.start), - Math.max(0, position.cols.start), - Math.max(0, position.rows.end), - Math.max(0, position.cols.end), - ); -}; - -// todo: remove when Snyk Code uses LS. -export const createIssueCorrectRange = (issuePosition: FileSuggestion, languages: IVSCodeLanguages): Range => { - return createIssueRange( - { - ...IssueUtils.createCorrectIssuePlacement(issuePosition), - }, - languages, - ); -}; - -export const updateFileReviewResultsPositions = ( - analysisResults: AnalysisResultLegacy, - updatedFile: openedTextEditorType, -): FilePath => { - const changesRange = updatedFile.contentChanges[0].range; - const changesText = updatedFile.contentChanges[0].text; - const goToNewLine = '\n'; - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands - const offsetedline = changesRange.start.line + 1; - const charOffset = 1; - - const fileIssuesList = { - ...analysisResults.files[updatedFile.fullPath], - }; - for (const issue in fileIssuesList) { - if (!Object.prototype.hasOwnProperty.call(fileIssuesList, issue)) { - continue; - } - - for (const [index, position] of fileIssuesList[issue].entries()) { - const currentLineIsOnEdgeOfIssueRange = offsetedline === position.rows[0] || offsetedline === position.rows[1]; - - for (const row in position.rows) { - if (offsetedline < position.rows[row]) { - position.rows[row] += updatedFile.lineCount.prevOffset; - } else if (offsetedline === position.rows[row]) { - if (changesRange.start.character < position.rows[row]) { - position.rows[row] += updatedFile.lineCount.prevOffset; - } - } - } - - if (currentLineIsOnEdgeOfIssueRange || (offsetedline > position.rows[0] && offsetedline < position.rows[1])) { - // when chars are added - if (changesText.length && changesText !== goToNewLine && currentLineIsOnEdgeOfIssueRange) { - if (changesRange.start.character < position.cols[0] && !changesText.includes(goToNewLine)) { - for (const col in position.cols) { - if (!Object.prototype.hasOwnProperty.call(position.cols, col)) continue; - position.cols[col] += changesText.length; - } - } - // if char is inside issue range - if (changesRange.start.character >= position.cols[0] && changesRange.start.character <= position.cols[1]) { - position.cols[1] += changesText.length; - } - } - // when chars are deleted - if (updatedFile.contentChanges[0].rangeLength && currentLineIsOnEdgeOfIssueRange) { - if (updatedFile.lineCount.prevOffset < 0 && !changesText) { - continue; - } - if (changesRange.start.character < position.cols[0] && !changesText.includes(goToNewLine)) { - for (const char in position.cols) { - if (!Object.prototype.hasOwnProperty.call(position.cols, char)) continue; - position.cols[char] = - position.cols[char] > 0 ? position.cols[char] - updatedFile.contentChanges[0].rangeLength : 0; - } - } - // if char is in issue range - if (changesRange.start.character >= position.cols[0] && changesRange.start.character <= position.cols[1]) { - position.cols[1] = position.cols[1] > 0 ? position.cols[1] - updatedFile.contentChanges[0].rangeLength : 0; - } - } - // hide issue - if (position.cols[0] - charOffset === position.cols[1]) { - fileIssuesList[issue].splice(index, 1); - } - position.cols[0] = position.cols[0] > 0 ? position.cols[0] : 0; - position.cols[1] = position.cols[1] > 0 ? position.cols[1] : 0; - } - } - } - return fileIssuesList; -}; - -export const createIssueMarkerMsg = (originalMsg: string, [markerStartIdx, markerEndIdx]: number[]): string => { - return originalMsg.substring(markerStartIdx, markerEndIdx + 1); -}; - -export const createIssuesMarkersDecorationOptions = ( - currentFileReviewIssues: readonly Diagnostic[] | undefined, -): DecorationOptions[] => { - if (!currentFileReviewIssues) { - return []; - } - const issueMarkersDecorationOptions = currentFileReviewIssues.reduce((markersRanges, issue) => { - if (issue.relatedInformation) { - for (const markerInfo of issue.relatedInformation) { - markersRanges.push({ - range: markerInfo.location.range, - hoverMessage: markerInfo.message, - }); - } - } - return markersRanges; - }, Array()); - return issueMarkersDecorationOptions; -}; - -export const createIssueRelatedInformation = ( - markersList: Marker[], - fileUriPath: string, - message: string, - languages: IVSCodeLanguages, - workspace: IVSCodeWorkspace, - uriAdapter: IUriAdapter, -): DiagnosticRelatedInformation[] => { - return markersList.reduce((res, marker) => { - const { msg: markerMsgIdxs, pos: positions } = marker; - - positions.forEach(position => { - const positionUri = getAbsoluteMarkerFilePath(workspace, position.file, fileUriPath); - const relatedInfo = languages.createDiagnosticRelatedInformation( - uriAdapter.file(positionUri), - createIssueCorrectRange(position, languages), - createIssueMarkerMsg(message, markerMsgIdxs), - ); - res.push(relatedInfo); - }); - - return res; - }, Array()); -}; - -export const findCompleteSuggestion = ( - analysisResults: ISnykCodeResult, - suggestionId: string, - uri: Uri, - position: Range, - languages: IVSCodeLanguages, -): completeFileSuggestionType | undefined => { - const filePath = uri.fsPath; - if (!analysisResults.files[filePath]) return; - const file: FilePath = analysisResults.files[filePath]; - let fileSuggestion: FileSuggestion | undefined; - let suggestionIndex: string | number | undefined = Object.keys(file).find(i => { - const index = parseInt(i, 10); - if (analysisResults.suggestions[index].id !== suggestionId) return false; - const pos = file[index].find(fs => { - const r = createIssueCorrectRange(fs, languages); - return ( - r.start.character === position.start.character && - r.start.line === position.start.line && - r.end.character === position.end.character && - r.end.line === position.end.line - ); - }); - if (pos) { - fileSuggestion = pos; - return true; - } - return false; - }); - if (!fileSuggestion || !suggestionIndex) return; - suggestionIndex = parseInt(suggestionIndex, 10); - const suggestion = analysisResults.suggestions[suggestionIndex]; - if (!suggestion) return; - // eslint-disable-next-line consistent-return - return { - uri: uri.toString(), - ...suggestion, - ...fileSuggestion, - }; -}; - -export const checkCompleteSuggestion = ( - analysisResults: AnalysisResultLegacy, - suggestion: completeFileSuggestionType, - uriAdapter: IUriAdapter, -): boolean => { - const filePath = uriAdapter.parse(suggestion.uri).fsPath; - if (!analysisResults.files[filePath]) return false; - const file: FilePath = analysisResults.files[filePath]; - const suggestionIndex: string | undefined = Object.keys(file).find(i => { - const index = parseInt(i, 10); - if ( - analysisResults.suggestions[index].id !== suggestion.id || - analysisResults.suggestions[index].message !== suggestion.message - ) - return false; - const found = file[index].find(fs => { - let equal = true; - for (const dir of ['cols', 'rows']) { - for (const ind of [0, 1]) { - equal = equal && fs[dir][ind] === suggestion[dir][ind]; - } - } - return equal; - }); - return !!found; - }); - return !!suggestionIndex; -}; - -export const findSuggestionByMessage = ( - analysisResults: ISnykCodeResult, - suggestionName: string, -): ICodeSuggestion | undefined => { - return Object.values(analysisResults.suggestions).find( - (suggestion: ICodeSuggestion) => suggestion.message === suggestionName, - ); -}; export const ignoreIssueCommentText = (issueId: string, isFileIgnore?: boolean): string => { const snykComment = isFileIgnore ? FILE_IGNORE_ISSUE_BASE_COMMENT_TEXT : IGNORE_ISSUE_BASE_COMMENT_TEXT; return `${snykComment} ${issueId}: ${IGNORE_ISSUE_REASON_TIP}`; }; -export const isSecurityTypeSuggestion = (suggestion: Suggestion): boolean => { - return suggestion.categories.includes('Security'); -}; - export const getAbsoluteMarkerFilePath = ( workspace: IVSCodeWorkspace, markerFilePath: string, diff --git a/src/snyk/snykCode/utils/issueUtils.ts b/src/snyk/snykCode/utils/issueUtils.ts index 34f8f46dd..04f23dfda 100644 --- a/src/snyk/snykCode/utils/issueUtils.ts +++ b/src/snyk/snykCode/utils/issueUtils.ts @@ -4,7 +4,7 @@ import { CodeIssueData, IssueSeverity } from '../../common/languageServer/types' import { IVSCodeLanguages } from '../../common/vscode/languages'; import { Diagnostic, Position, Range } from '../../common/vscode/types'; -export type IssuePlacementPosition = { +type IssuePlacementPosition = { cols: { start: number; end: number; diff --git a/src/snyk/snykOss/interfaces.ts b/src/snyk/snykOss/interfaces.ts index fde681716..793165d52 100644 --- a/src/snyk/snykOss/interfaces.ts +++ b/src/snyk/snykOss/interfaces.ts @@ -13,8 +13,6 @@ export type OssIssueCommandArg = Issue & { folderPath: string; }; -export type OssResult = OssFileResult[] | OssFileResult; - export type OssFileResult = OssResultBody | CliError; export type OssResultBody = { @@ -49,27 +47,23 @@ export type OssVulnerability = { isUpgradable: boolean; }; -export type Identifiers = { +type Identifiers = { CWE: string[]; CVE: string[]; }; -export enum OssSeverity { +enum OssSeverity { Low = 'low', Medium = 'medium', High = 'high', Critical = 'critical', } -export function capitalizeOssSeverity(ossSeverity: OssSeverity): Capitalize { - return _.capitalize(ossSeverity) as Capitalize; -} - export function isResultCliError(fileResult: OssFileResult): fileResult is CliError { return (fileResult as CliError).error !== undefined; } -export function convertSeverity(severity: IssueSeverity): OssSeverity { +function convertSeverity(severity: IssueSeverity): OssSeverity { switch (severity) { case IssueSeverity.Low: return OssSeverity.Low; diff --git a/src/snyk/snykOss/services/vulnerabilityCount/importedModule.ts b/src/snyk/snykOss/services/vulnerabilityCount/importedModule.ts index 0fe3843f2..809699fe6 100644 --- a/src/snyk/snykOss/services/vulnerabilityCount/importedModule.ts +++ b/src/snyk/snykOss/services/vulnerabilityCount/importedModule.ts @@ -24,7 +24,7 @@ export enum ModuleVulnerabilityCountSeverity { Critical = 'critical', } -export type SeverityCounts = { +type SeverityCounts = { [s in ModuleVulnerabilityCountSeverity]: number; }; diff --git a/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountService.ts b/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountService.ts index 8f1311f2f..0477b1b04 100644 --- a/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountService.ts +++ b/src/snyk/snykOss/services/vulnerabilityCount/ossVulnerabilityCountService.ts @@ -22,13 +22,6 @@ import { OssVulnerabilityCountProvider } from '../../providers/ossVulnerabilityC import { ImportedModule, ModuleVulnerabilityCount, ModuleVulnerabilityCountSeverity } from './importedModule'; import { VulnerabilityCountEmitter, VulnerabilityCountEvents } from './vulnerabilityCountEmitter'; -export enum SupportedLanguage { - TypeScript, - JavaScript, - HTML, - PJSON, -} - export class OssVulnerabilityCountService implements Disposable { protected disposables: Disposable[] = []; protected ossScanFinishedSubscription: Subscription; diff --git a/src/snyk/snykOss/services/vulnerabilityCount/parsers/packageJsonParser.ts b/src/snyk/snykOss/services/vulnerabilityCount/parsers/packageJsonParser.ts index 62be33178..f4142c5cd 100644 --- a/src/snyk/snykOss/services/vulnerabilityCount/parsers/packageJsonParser.ts +++ b/src/snyk/snykOss/services/vulnerabilityCount/parsers/packageJsonParser.ts @@ -2,16 +2,16 @@ import { ILog } from '../../../../common/logger/interfaces'; import { ImportedModule, OssRange } from '../../../../common/types'; import { ModuleParser } from './moduleParser'; -export type PackageJsonDependencies = { +type PackageJsonDependencies = { [dependency: string]: string; }; -export interface PackageJson { +interface PackageJson { dependencies: PackageJsonDependencies; devDependencies: PackageJsonDependencies; } -export interface DependencyLines { +interface DependencyLines { lines: string[]; offset: number; } diff --git a/src/snyk/snykOss/watchers/manifestFileWatcher.ts b/src/snyk/snykOss/watchers/manifestFileWatcher.ts deleted file mode 100644 index d022125c3..000000000 --- a/src/snyk/snykOss/watchers/manifestFileWatcher.ts +++ /dev/null @@ -1,59 +0,0 @@ -import * as vscode from 'vscode'; -import { IExtension } from '../../base/modules/interfaces'; -import { IConfiguration } from '../../common/configuration/configuration'; -import { IVSCodeWorkspace } from '../../common/vscode/workspace'; - -// to be kept in sync with Snyk CLI support list -// copied from https://github.com/snyk/snyk/blob/93ec5896282e3ba1389dc5604589d2773a4bf517/src/lib/package-managers.ts#L21 -enum SUPPORTED_MANIFEST_FILES { - GEMFILE = 'Gemfile', - GEMFILE_LOCK = 'Gemfile.lock', - GEMSPEC = '*.gemspec', - PACKAGE_LOCK_JSON = 'package-lock.json', - POM_XML = 'pom.xml', - JAR = '*.jar', - WAR = '*.war', - BUILD_GRADLE = 'build.gradle', - BUILD_GRADLE_KTS = 'build.gradle.kts', - BUILD_SBT = 'build.sbt', - YARN_LOCK = 'yarn.lock', - PACKAGE_JSON = 'package.json', - PIPFILE = 'Pipfile', - SETUP_PY = 'setup.py', - REQUIREMENTS_TXT = 'requirements.txt', - GOPKG_LOCK = 'Gopkg.lock', - GO_MOD = 'go.mod', - VENDOR_JSON = 'vendor.json', - PROJECT_ASSETS_JSON = 'project.assets.json', - PACKAGES_CONFIG = 'packages.config', - PROJECT_JSON = 'project.json', - PAKET_DEPENDENCIES = 'paket.dependencies', - COMPOSER_LOCK = 'composer.lock', - PODFILE_LOCK = 'Podfile.lock', - COCOAPODS_PODFILE_YAML = 'CocoaPods.podfile.yaml', - COCOAPODS_PODFILE = 'CocoaPods.podfile', - PODFILE = 'Podfile', - POETRY_LOCK = 'poetry.lock', - MIX_EXS = 'mix.exs', -} - -export default function createManifestFileWatcher( - extension: IExtension, - workspace: IVSCodeWorkspace, - configuration: IConfiguration, -): vscode.FileSystemWatcher { - const globPattern = `**/{${Object.values(SUPPORTED_MANIFEST_FILES).join(',')}}`; - const watcher = workspace.createFileSystemWatcher(globPattern); - - watcher.onDidChange(() => runScan()); - watcher.onDidDelete(() => runScan()); - watcher.onDidCreate(() => runScan()); - - function runScan() { - if (configuration.shouldAutoScanOss) { - void extension.runScan(); - } - } - - return watcher; -} diff --git a/src/test/unit/cli/process.test.ts b/src/test/unit/cli/process.test.ts deleted file mode 100644 index 31a260e05..000000000 --- a/src/test/unit/cli/process.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { strictEqual } from 'assert'; -import sinon from 'sinon'; -import { CLI_INTEGRATION_NAME } from '../../../snyk/cli/contants/integration'; -import { CliProcess } from '../../../snyk/cli/process'; -import { Configuration, IConfiguration } from '../../../snyk/common/configuration/configuration'; -import { ILog } from '../../../snyk/common/logger/interfaces'; -import { IVSCodeWorkspace } from '../../../snyk/common/vscode/workspace'; -import { LoggerMock } from '../mocks/logger.mock'; -import { OAuthToken } from '../../../snyk/base/services/authenticationService'; - -suite('CliProcess', () => { - let logger: ILog; - const snykOssApiEndpoint = 'https://snykgov.io/api/'; - const emptyWorkspace = { - getConfiguration: () => undefined, - } as unknown as IVSCodeWorkspace; - - setup(() => { - logger = new LoggerMock(); - }); - - test('Sets correct integration name, version, token, API endpoint and organization', async () => { - const token = 'fake-token'; - const snykOssApiEndpoint = 'https://snyk.io/api/'; - const organization = 'test-org'; - const process = new CliProcess( - logger, - { - getToken: () => Promise.resolve(token), - snykOssApiEndpoint: snykOssApiEndpoint, - organization: organization, - } as IConfiguration, - emptyWorkspace, - ); - - const envVars = await process.getProcessEnv(); - - strictEqual(envVars['SNYK_INTEGRATION_NAME'], CLI_INTEGRATION_NAME); - strictEqual(envVars['SNYK_INTEGRATION_VERSION'], await Configuration.getVersion()); - strictEqual(envVars['SNYK_TOKEN'], token); - strictEqual(envVars['SNYK_API'], snykOssApiEndpoint); - strictEqual(envVars['SNYK_CFG_ORG'], organization); - }); - - test('Sets correct token if oauth authentication', async () => { - const token = '{"access_token": "fake-token"}'; - const snykOssApiEndpoint = 'https://snykgov.io/api/'; - const organization = 'test-org'; - const process = new CliProcess( - logger, - { - getToken: () => Promise.resolve(token), - snykOssApiEndpoint: snykOssApiEndpoint, - organization: organization, - } as IConfiguration, - emptyWorkspace, - ); - - const envVars = await process.getProcessEnv(); - const oauthToken = JSON.parse(token) as OAuthToken; - strictEqual(envVars['SNYK_TOKEN'], undefined); - strictEqual(envVars['SNYK_OAUTH_TOKEN'], oauthToken.access_token); - strictEqual(envVars['SNYK_API'], snykOssApiEndpoint); - strictEqual(envVars['SNYK_CFG_ORG'], organization); - }); - - test('Sets correct proxy variable', async () => { - // arrange - const proxy = 'http://my.proxy.com:8080'; - const getConfiguration = sinon.stub(); - getConfiguration.withArgs('http', 'proxy').returns(proxy); - - const process = new CliProcess( - logger, - { - getToken: () => Promise.resolve(), - snykOssApiEndpoint: snykOssApiEndpoint, - } as IConfiguration, - { - getConfiguration: getConfiguration, - } as unknown as IVSCodeWorkspace, - ); - - // act - const vars = await process.getProcessEnv(); - - // assert - strictEqual(vars['HTTPS_PROXY'], proxy); - strictEqual(vars['HTTP_PROXY'], proxy); - }); -}); diff --git a/src/test/unit/cli/services/cliService.test.ts b/src/test/unit/cli/services/cliService.test.ts deleted file mode 100644 index d92429ecc..000000000 --- a/src/test/unit/cli/services/cliService.test.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { deepStrictEqual, ok } from 'assert'; -import { ReplaySubject } from 'rxjs'; -import sinon from 'sinon'; -import { CliProcess } from '../../../../snyk/cli/process'; -import { CliError, CliService } from '../../../../snyk/cli/services/cliService'; -import { IConfiguration } from '../../../../snyk/common/configuration/configuration'; -import { WorkspaceTrust } from '../../../../snyk/common/configuration/trustedFolders'; -import { ILanguageServer } from '../../../../snyk/common/languageServer/languageServer'; -import { ILog } from '../../../../snyk/common/logger/interfaces'; -import { DownloadService } from '../../../../snyk/common/services/downloadService'; -import { ExtensionContext } from '../../../../snyk/common/vscode/extensionContext'; -import { IVSCodeWorkspace } from '../../../../snyk/common/vscode/workspace'; -import { LoggerMock } from '../../mocks/logger.mock'; - -type TestCliResult = - | { - success: boolean; - } - | CliError; - -class TestCliService extends CliService { - protected command: string[] = ['']; - protected mapToResultType(rawCliResult: string): TestCliResult { - return JSON.parse(rawCliResult) as TestCliResult; - } - protected beforeTest(): void { - return; - } - protected afterTest(_result: TestCliResult): void { - return; - } - protected ensureDependencies(): void { - return; - } -} - -suite('CliService', () => { - const extensionPath = 'test/path'; - let logger: ILog; - let testCliService: TestCliService; - let extensionContext: ExtensionContext; - let downloadService: DownloadService; - let configuration: IConfiguration; - - setup(() => { - logger = new LoggerMock(); - - extensionContext = { - extensionPath: extensionPath, - getGlobalStateValue: () => undefined, - } as unknown as ExtensionContext; - - const testFolderPath = 'test-folder'; - configuration = { - getAdditionalCliParameters: () => '', - isAutomaticDependencyManagementEnabled: () => true, - getCliPath: () => undefined, - getTrustedFolders: () => [testFolderPath], - } as unknown as IConfiguration; - - downloadService = { - download: () => false, - isCliInstalled: () => true, - } as unknown as DownloadService; - - const ls = { - cliReady$: new ReplaySubject(1), - } as unknown as ILanguageServer; - ls.cliReady$.next(''); - - testCliService = new TestCliService( - extensionContext, - logger, - configuration, - { - getWorkspaceFolders: () => [testFolderPath], - } as IVSCodeWorkspace, - downloadService, - ls, - new WorkspaceTrust(), - ); - }); - - teardown(() => { - sinon.restore(); - }); - - test('Test returns mapped result when CLI succeeds', async () => { - const cliOutput = { success: true } as TestCliResult; - sinon.stub(CliProcess.prototype, 'spawn').resolves(JSON.stringify(cliOutput)); - const result = await testCliService.test(false, false); - - deepStrictEqual(result, cliOutput); - }); - - test('Test returns error when CLI execution fails with error JSON', async () => { - const cliError = { - ok: false, - error: 'Authentication failed. Please check the API token on https://snyk.io', - path: '/Users/snyk/Git/goof', - }; - - sinon.stub(CliProcess.prototype, 'spawn').resolves(JSON.stringify(cliError)); - - const result = (await testCliService.test(false, false)) as CliError; - - deepStrictEqual(result.error, cliError.error); - deepStrictEqual(result.path, cliError.path); - }); - - test('Test returns error when CLI execution fails without error JSON', async () => { - const errOutput = new Error('Failed to run snyk command.'); - sinon.stub(CliProcess.prototype, 'spawn').rejects(errOutput); - const result = await testCliService.test(false, false); - - ok(result instanceof CliError); - deepStrictEqual(result.error, errOutput); - }); - - test('Test passes cwd and additional CLI arguments from settings', async () => { - const testFolder = 'test-folder'; - const additionalParameters = `--exclude="folder with spaces" --configuration-matching="iamaRegex" --sub-project=snyk`; - sinon.stub(configuration, 'getAdditionalCliParameters').returns(additionalParameters); - - const spawnSpy = sinon.spy(CliProcess.prototype, 'spawn'); - await testCliService.test(false, false); - - const expectedArgs = [ - '', - testFolder, - '--json', - '--exclude="folder with spaces"', - '--configuration-matching="iamaRegex"', - '--sub-project=snyk', - ]; - deepStrictEqual(spawnSpy.calledWith(sinon.match.any, testFolder, expectedArgs), true); - }); -}); diff --git a/src/test/unit/common/languageServer/settings.test.ts b/src/test/unit/common/languageServer/settings.test.ts index 9dadf634c..1d72d991c 100644 --- a/src/test/unit/common/languageServer/settings.test.ts +++ b/src/test/unit/common/languageServer/settings.test.ts @@ -1,23 +1,9 @@ import assert from 'assert'; import { IConfiguration } from '../../../../snyk/common/configuration/configuration'; -import { LanguageServerSettings, defaultToTrue } from '../../../../snyk/common/languageServer/settings'; +import { LanguageServerSettings } from '../../../../snyk/common/languageServer/settings'; import { User } from '../../../../snyk/common/user'; suite('LanguageServerSettings', () => { - suite('defaultToTrue', () => { - test('should return "true" for undefined values', () => { - assert.strictEqual(defaultToTrue(undefined), 'true'); - }); - - test('should return "true" for truthy values', () => { - assert.strictEqual(defaultToTrue(true), 'true'); - }); - - test('should return "false" for false values', () => { - assert.strictEqual(defaultToTrue(false), 'false'); - }); - }); - suite('fromConfiguration', () => { test('should generate server settings with default true values for undefined feature toggles', async () => { const mockUser = { anonymousId: 'anonymous-id' } as User; diff --git a/src/test/unit/mocks/uri.mock.ts b/src/test/unit/mocks/uri.mock.ts index 3104acb39..929b380a2 100644 --- a/src/test/unit/mocks/uri.mock.ts +++ b/src/test/unit/mocks/uri.mock.ts @@ -1,7 +1,7 @@ import { Uri } from '../../../snyk/common/vscode/types'; import { IUriAdapter } from '../../../snyk/common/vscode/uri'; -export class UriAdapterMock implements IUriAdapter { +class UriAdapterMock implements IUriAdapter { file(path: string): Uri { return { path: path, @@ -14,5 +14,3 @@ export class UriAdapterMock implements IUriAdapter { } as Uri; } } - -export const uriAdapterMock = new UriAdapterMock(); diff --git a/src/test/unit/mocks/workspace.mock.ts b/src/test/unit/mocks/workspace.mock.ts index 04a04df08..a46d64348 100644 --- a/src/test/unit/mocks/workspace.mock.ts +++ b/src/test/unit/mocks/workspace.mock.ts @@ -10,11 +10,3 @@ export function stubWorkspaceConfiguration(configSetting: string, returnValue }, } as IVSCodeWorkspace; } - -export const workspaceMock = { - getWorkspaceFolders() { - return [workspaceFolder]; - }, -} as IVSCodeWorkspace; - -export const workspaceFolder = path.join(os.homedir(), 'snyk/project'); diff --git a/src/test/unit/snykCode/utils/analysisUtils.test.ts b/src/test/unit/snykCode/utils/analysisUtils.test.ts index d7755d2bb..0baa75654 100644 --- a/src/test/unit/snykCode/utils/analysisUtils.test.ts +++ b/src/test/unit/snykCode/utils/analysisUtils.test.ts @@ -1,67 +1,19 @@ -import { Marker } from '@snyk/code-client'; -import { deepStrictEqual, strictEqual } from 'assert'; +import { strictEqual } from 'assert'; import path from 'path'; import sinon from 'sinon'; -import { IVSCodeLanguages } from '../../../../snyk/common/vscode/languages'; import { IVSCodeWorkspace } from '../../../../snyk/common/vscode/workspace'; -import { - createIssueRange, - createIssueRelatedInformation, - getAbsoluteMarkerFilePath, -} from '../../../../snyk/snykCode/utils/analysisUtils'; -import { IssuePlacementPosition } from '../../../../snyk/snykCode/utils/issueUtils'; -import { languagesMock } from '../../mocks/languages.mock'; -import { uriAdapterMock } from '../../mocks/uri.mock'; -import { workspaceFolder, workspaceMock } from '../../mocks/workspace.mock'; +import { getAbsoluteMarkerFilePath } from '../../../../snyk/snykCode/utils/analysisUtils'; suite('Snyk Code Analysis Utils', () => { const createRangeMock = sinon.mock(); - let languages: IVSCodeLanguages; let workspace: IVSCodeWorkspace; setup(() => { - languages = { - createRange: createRangeMock, - } as unknown as IVSCodeLanguages; workspace = {} as IVSCodeWorkspace; }); teardown(() => createRangeMock.reset()); - test('Create issue range copes with non-negative values', () => { - const position: IssuePlacementPosition = { - cols: { - start: 1, - end: 1, - }, - rows: { - start: 1, - end: 1, - }, - }; - - createIssueRange(position, languages); - - sinon.assert.calledOnceWithExactly(createRangeMock, 1, 1, 1, 1); - }); - - test('Create issue range copes with negative values', () => { - const position: IssuePlacementPosition = { - cols: { - start: -1, - end: -1, - }, - rows: { - start: -1, - end: -1, - }, - }; - - createIssueRange(position, languages); - - sinon.assert.calledOnceWithExactly(createRangeMock, 0, 0, 0, 0); - }); - test('Returns correct absolute path if no marker file path provided', () => { // arrange const suggestionFilePath = '/Users/snyk/goof/test.js'; @@ -104,56 +56,4 @@ suite('Snyk Code Analysis Utils', () => { // assert strictEqual(absoluteFilePath, path.resolve(workspaceFolder, relativeMarkerFilePath)); }); - - test('Creates correct related information for inter-file issues', () => { - const file1Uri = 'file1.js'; - const file2Uri = 'file2.js'; - - const markers: Marker[] = [ - { - msg: [0, 16], - pos: [ - { - file: file1Uri, - rows: [1, 1], - cols: [1, 1], - }, - { - file: file2Uri, - rows: [2, 2], - cols: [10, 10], - }, - ], - }, - ]; - - const message = - 'Unsanitized input from data from a remote resource flows into bypassSecurityTrustHtml, where it is used to render an HTML page returned to the user. This may result in a Cross-Site Scripting attack (XSS).'; - - const information = createIssueRelatedInformation( - markers, - file2Uri, - message, - languagesMock, - workspaceMock, - uriAdapterMock, - ); - - deepStrictEqual(information, [ - { - message: 'Unsanitized input', - location: { - uri: { path: path.join(workspaceFolder, file1Uri) }, - range: { start: { line: 0, character: 0 }, end: { line: 0, character: 1 } }, - }, - }, - { - message: 'Unsanitized input', - location: { - uri: { path: path.join(workspaceFolder, file2Uri) }, - range: { start: { line: 1, character: 9 }, end: { line: 1, character: 10 } }, - }, - }, - ]); - }); });