Skip to content

Commit

Permalink
Merge pull request #16 from Gehbt/patch-1
Browse files Browse the repository at this point in the history
feat: fix action add lock installed version and upgrade single package
  • Loading branch information
tjx666 authored Jul 24, 2024
2 parents bf16bed + 2e86316 commit 1fd2c89
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 24 deletions.
14 changes: 14 additions & 0 deletions src/commands/keepInstalledVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import vscode from 'vscode';

interface Args {
versionRange: vscode.Range;
installedVersion: string;
}

export async function keepInstalledVersion(arg: Args) {
const editor = vscode.window.activeTextEditor;

return editor?.edit((editBuilder) => {
editBuilder.replace(arg.versionRange, arg.installedVersion);
});
}
4 changes: 4 additions & 0 deletions src/commands/runNpmScriptInTerminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export async function runNpmScriptInTerminal(args: Args) {
Uri.file(resolve(args.cwd, 'package.json')),
);
if (!workspaceFolder) return;
const document = vscode.window.activeTextEditor?.document;
if (document?.isDirty) {
await document.save();
}

const pm = await detectPm(workspaceFolder.uri);
const terminalName = 'Run Script';
Expand Down
134 changes: 110 additions & 24 deletions src/diagnostic/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import path from 'path';
import path from 'node:path';

import type { ParsedJson } from 'jsonpos';
import semver from 'semver';
Expand All @@ -7,20 +7,25 @@ import vscode from 'vscode';

import { configuration } from '../configuration';
import { logger } from '../logger';
import { commands } from '../utils/constants';
import { commands, EXT_NAME, PACKAGE_JSON } from '../utils/constants';
import { findPkgInstallDir } from '../utils/pkg';
import { getPackageInfo } from '../utils/pkg-info';
import { detectPm } from '../utils/pm';

enum DepsCheckDiagnosticCode {
PACKAGE_NOT_FOUND = `${EXT_NAME}.packageNotFound`,
UNMET_DEPENDENCY = `${EXT_NAME}.unmetDependency`,
}

export const diagnosticCollection = vscode.languages.createDiagnosticCollection(
'package-manager-enhancer:depsVersionCheck',
`${EXT_NAME}:depsVersionCheck`,
);

export async function updateDiagnostic(document: vscode.TextDocument) {
if (!configuration.depsVersionCheck.enable) return;

if (
!path.basename(document.uri.fsPath).includes('package.json') ||
!path.basename(document.uri.fsPath).includes(PACKAGE_JSON) ||
document.languageId !== 'json'
)
return;
Expand Down Expand Up @@ -64,35 +69,45 @@ export async function updateDiagnostic(document: vscode.TextDocument) {
location.end.line - 1,
location.end.column - 1,
);

const packageInstallDir = await findPkgInstallDir(name, document.uri.fsPath);
const packageInfo = await getPackageInfo(name, {
packageInstallDir: await findPkgInstallDir(name, document.uri.fsPath),
packageInstallDir,
fetchBundleSize: false,
remoteFetch: false,
skipBuiltinModuleCheck: true,
});

if (packageInfo?.isBuiltinModule) return;

// not installed
if (!packageInfo || !packageInfo.installedVersion) {
const diagnostic = new vscode.Diagnostic(
range,
`Package "${name}" not installed`,
vscode.DiagnosticSeverity.Warning,
);
diagnostic.code = 'package-manager-enhancer.packageNotFound';
diagnostic.code = DepsCheckDiagnosticCode.PACKAGE_NOT_FOUND;
diagnostic.data = {
depName: name,
depDeclaredVersion: version,
};
diagnostics.push(diagnostic);
return;
}

// doesn't match declared version
const { version: installedVersion } = packageInfo;
if (semver.validRange(version) && !semver.satisfies(installedVersion, version)) {
const diagnostic = new vscode.Diagnostic(
range,
`Installed ${name} version "${installedVersion}" doesn't match declared version: "${version}"`,
vscode.DiagnosticSeverity.Warning,
);
diagnostic.code = 'package-manager-enhancer.unmetDependency';
diagnostic.code = DepsCheckDiagnosticCode.UNMET_DEPENDENCY;
diagnostic.data = {
depInstalledVersion: installedVersion,
};

diagnostics.push(diagnostic);
}
}),
Expand All @@ -113,35 +128,106 @@ export async function updateDiagnostic(document: vscode.TextDocument) {
}

export class DepsCheckCodeActionProvider implements CodeActionProvider {
private createNpmInstallAction(diagnostics: vscode.Diagnostic[], pm: string, cwd: string) {
const runInstallTitle = `Run "${pm} install"`;
const runInstallAction = new vscode.CodeAction(
runInstallTitle,
vscode.CodeActionKind.QuickFix,
);
runInstallAction.command = {
command: commands.runNpmScriptInTerminal,
title: runInstallTitle,
arguments: [
{
command: 'install',
cwd,
},
],
};
runInstallAction.diagnostics = diagnostics;
return runInstallAction;
}

private createNpmInstallSingleAction(
diagnostics: vscode.Diagnostic[],
pm: string,
cwd: string,
) {
const { depName, depDeclaredVersion } = diagnostics[0].data!;
const packageNameAndVersion = `${depName}@${depDeclaredVersion}`;
const runInstallSingleTitle = `Run "${pm} install ${packageNameAndVersion}"`;
const runInstallSingleAction = new vscode.CodeAction(
runInstallSingleTitle,
vscode.CodeActionKind.QuickFix,
);
runInstallSingleAction.command = {
command: commands.runNpmScriptInTerminal,
title: runInstallSingleTitle,
arguments: [
{
command: `install ${packageNameAndVersion}`,
cwd,
},
],
};
runInstallSingleAction.diagnostics = diagnostics;
return runInstallSingleAction;
}

private createLockVersionAction(diagnostics: vscode.Diagnostic[], range: vscode.Range) {
const { depInstalledVersion: installedVersion } = diagnostics[0].data!;
const lockVersionActon = new vscode.CodeAction(
`Lock to ${installedVersion}`,
vscode.CodeActionKind.QuickFix,
);
lockVersionActon.command = {
command: commands.keepInstalledVersion,
title: `Lock to ${installedVersion}`,
arguments: [
{
versionRange: range,
installedVersion: `\"${installedVersion}\"`,
},
],
};
lockVersionActon.diagnostics = diagnostics;
return lockVersionActon;
}

async provideCodeActions(
document: vscode.TextDocument,
_range: vscode.Range | vscode.Selection,
range: vscode.Range | vscode.Selection,
_context: vscode.CodeActionContext,
_token: vscode.CancellationToken,
): Promise<vscode.CodeAction[] | undefined> {
const codeActions: vscode.CodeAction[] = [];

const line = range.start.line;
const diagnostics = vscode.languages
.getDiagnostics(document.uri)
.filter(
(diagnostic) =>
diagnostic.code === 'package-manager-enhancer.packageNotFound' ||
diagnostic.code === 'package-manager-enhancer.unmetDependency',
line === diagnostic.range.start.line &&
(diagnostic.code === DepsCheckDiagnosticCode.PACKAGE_NOT_FOUND ||
diagnostic.code === DepsCheckDiagnosticCode.UNMET_DEPENDENCY),
);
if (diagnostics.length === 0) return;

const pm = await detectPm(vscode.workspace.getWorkspaceFolder(document.uri)!.uri);
const cwd = vscode.workspace.getWorkspaceFolder(document.uri)!.uri.fsPath;

const action = new vscode.CodeAction(`Run ${pm} install`, vscode.CodeActionKind.QuickFix);
action.command = {
command: commands.runNpmScriptInTerminal,
title: `Run ${pm} install`,
arguments: [
{
command: 'install',
cwd: vscode.workspace.getWorkspaceFolder(document.uri)!.uri.fsPath,
},
],
};
action.diagnostics = diagnostics;
return [action];
codeActions.push(
this.createNpmInstallAction(diagnostics, pm, cwd),
this.createNpmInstallSingleAction(diagnostics, pm, cwd),
);

const unmetDepDiagnostics = diagnostics.filter(
(diagnostic) => diagnostic.code === DepsCheckDiagnosticCode.UNMET_DEPENDENCY,
);
if (unmetDepDiagnostics.length > 0) {
codeActions.push(this.createLockVersionAction(unmetDepDiagnostics, range));
}

return codeActions;
}
}
4 changes: 4 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export function activate(context: vscode.ExtensionContext) {
),
);

registerCommand(commands.keepInstalledVersion, (arg) =>
import('./commands/keepInstalledVersion').then((mod) => mod.keepInstalledVersion(arg)),
);

registerTextEditorCommand(commands.addMissingDeps, (editor) =>
import('./commands/addMissingDeps').then((mod) => mod.addMissingDeps(editor)),
);
Expand Down
12 changes: 12 additions & 0 deletions src/typings/module.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
declare module '@npmcli/config/lib/definitions' {
export const definitions: Record<string, any>;
}

import * as vscode from 'vscode';

declare module 'vscode' {
export interface Diagnostic {
data?: {
depName?: string;
depDeclaredVersion?: string;
depInstalledVersion?: string;
};
}
}
1 change: 1 addition & 0 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const commandsArray = [
'upgradeVersion',
'findNpmPackage',
'findPathInNodeModules',
'keepInstalledVersion',
] as const;

type CommandsArrayUnion = (typeof commandsArray)[number];
Expand Down

0 comments on commit 1fd2c89

Please sign in to comment.