Skip to content

Commit

Permalink
feat: support package.json deps hover tooltip
Browse files Browse the repository at this point in the history
  • Loading branch information
tjx666 committed Apr 2, 2024
1 parent 37db3f4 commit 9088f07
Show file tree
Hide file tree
Showing 15 changed files with 609 additions and 87 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,17 @@
"prepare": "simple-git-hooks"
},
"dependencies": {
"axios": "^1.6.8",
"detect-package-manager": "^3.0.1",
"escape-string-regexp": "^5.0.0",
"execa": "^8.0.1",
"expiry-map": "^2.0.0",
"globby": "^14.0.1",
"hosted-git-info": "^7.0.1",
"is-builtin-module": "^3.2.1",
"jsonc-parser": "^3.2.1",
"lodash-es": "^4.17.21",
"lru-cache": "^10.2.0",
"micromatch": "^4.0.5",
"p-memoize": "^7.1.1",
"p-queue": "^8.0.1",
Expand All @@ -258,6 +262,7 @@
},
"devDependencies": {
"@types/glob": "^8.1.0",
"@types/hosted-git-info": "^3.0.5",
"@types/lodash-es": "^4.17.12",
"@types/micromatch": "^4.0.6",
"@types/mocha": "^10.0.6",
Expand Down
81 changes: 77 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/commands/addMissingDeps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as jsonc from 'jsonc-parser';
import type { TextEditor } from 'vscode';
import { Range } from 'vscode';

import { getPackageInfo } from '../utils/package';
import { getPackageInfoFromNpmView } from '../utils/pkg';
import { searchUsedDeps } from '../utils/searchUsedDeps';

export async function addMissingDeps(editor: TextEditor) {
Expand Down Expand Up @@ -38,7 +38,7 @@ export async function addMissingDeps(editor: TextEditor) {

const getVersionPromises = Object.keys(newDependencies).map(async (packageName) => {
const properties = ['version'] as const;
const version = await getPackageInfo<string, typeof properties>(
const version = await getPackageInfoFromNpmView<string, typeof properties>(
packageName,
properties,
cwd,
Expand Down
10 changes: 5 additions & 5 deletions src/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import vscode, { ConfigurationTarget } from 'vscode';

import { extensionName } from './utils/constants';
import { EXT_NAME } from './utils/constants';

interface Configuration {
enableLogInfo: boolean;
Expand All @@ -26,7 +26,7 @@ interface Configuration {

export const configuration: Configuration = {} as Configuration;
export async function updateConfiguration() {
const extensionConfig = vscode.workspace.getConfiguration(extensionName);
const extensionConfig = vscode.workspace.getConfiguration(EXT_NAME);

configuration.enableLogInfo = extensionConfig.get('enableLogInfo')!;

Expand All @@ -51,7 +51,7 @@ export async function updateConfiguration() {
>('packageJsonDependenciesCodeLens')!;
await vscode.commands.executeCommand(
'setContext',
`${extensionName}.enablePackageJsonDependenciesCodeLens`,
`${EXT_NAME}.enablePackageJsonDependenciesCodeLens`,
configuration.enablePackageJsonDependenciesCodeLens,
);

Expand All @@ -73,7 +73,7 @@ type CfgToCfgKeys<T extends object, ParentPath extends string> = {
}
: `${ParentPath}${P & string}`;
};
type ConfigurationKeys = CfgToCfgKeys<Configuration, typeof extensionName>;
type ConfigurationKeys = CfgToCfgKeys<Configuration, typeof EXT_NAME>;
function setupKeys(cfg: Record<string, any>, cfgKeys: Record<string, any>, parentKeyPath = '') {
for (const [key, value] of Object.entries(cfg)) {
const newParentPath = `${parentKeyPath}${parentKeyPath === '' ? '' : '.'}${key}`;
Expand All @@ -85,7 +85,7 @@ function setupKeys(cfg: Record<string, any>, cfgKeys: Record<string, any>, paren
cfgKeys[newParentPath] = subObject;
setupKeys(value, subObject, newParentPath);
} else {
cfgKeys[newParentPath] = `${extensionName}.${newParentPath}`;
cfgKeys[newParentPath] = `${EXT_NAME}.${newParentPath}`;
}
}
return cfgKeys;
Expand Down
43 changes: 5 additions & 38 deletions src/definitions/dependencies.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import fs from 'node:fs/promises';

import type { Node } from 'jsonc-parser';
import validatePkgName from 'validate-npm-package-name';
import {
type CancellationToken,
type Definition,
Expand All @@ -13,58 +11,27 @@ import {
} from 'vscode';

import { getFileRange, jsoncStringNodeToRange } from '../utils/editor';
import { findPackagePath } from '../utils/pkg';
import { findPackagePath, getPkgNameAndVersionFromDocPosition } from '../utils/pkg';

export class DependenciesDefinitionProvider implements DefinitionProvider {
async provideDefinition(
document: TextDocument,
position: Position,
_token: CancellationToken,
): Promise<Definition | DefinitionLink[] | undefined> {
const jsoncParser = await import('jsonc-parser');

const pkgJson = document.getText();
let root: Node | undefined;
try {
root = jsoncParser.parseTree(pkgJson);
} catch {
return;
}
if (!root) return;

const dependenciesNodePath = [
'dependencies',
'devDependencies',
'peerDependencies',
'optionalDependencies',
];

const node = jsoncParser.findNodeAtOffset(root, document.offsetAt(position));
if (!node) return;

const dependenciesNodes = dependenciesNodePath.map((path) =>
jsoncParser.findNodeAtLocation(root, path.split('.')),
);
const isHoverOverDependency =
node.type === 'string' &&
node.parent?.type === 'property' &&
node === node.parent.children?.[0] &&
dependenciesNodes.includes(node.parent?.parent);
if (!isHoverOverDependency) return;

const pkgName = node.value;
if (!validatePkgName(pkgName).validForOldPackages) return;
const pkgInfo = await getPkgNameAndVersionFromDocPosition(document, position);
if (!pkgInfo) return;

const pkgJsonPath = await fs.realpath(document.uri.fsPath);
const pkgPath = await findPackagePath(pkgName, pkgJsonPath);
const pkgPath = await findPackagePath(pkgInfo.name, pkgJsonPath);
if (!pkgPath) return;

const [targetUri, targetRange] = await Promise.all([
fs.realpath(pkgPath.pkgJsonPath).then((p) => Uri.file(p)),
getFileRange(pkgPath.pkgJsonPath),
]);
const definition: DefinitionLink = {
originSelectionRange: jsoncStringNodeToRange(document, node),
originSelectionRange: jsoncStringNodeToRange(document, pkgInfo.nameNode),
targetUri,
targetRange,
};
Expand Down
6 changes: 4 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ import { PackageJsonVersionCodeLensProvider } from './codeLens/packageJsonVersio
import { PnpmWorkspaceCodeLensProvider } from './codeLens/pnpmWorkspace';
import { updateConfiguration } from './configuration';
import { DependenciesDefinitionProvider } from './definitions/dependencies';
import { DependenciesHoverProvider } from './hoverTooltips/dependencies';
import { NpmScriptsHoverProvider } from './hoverTooltips/npmScripts';
import { logger } from './logger';
import type { Command } from './utils/constants';
import { commands, extensionName } from './utils/constants';
import { commands, EXT_NAME } from './utils/constants';
import { store } from './utils/store';

export function activate(context: vscode.ExtensionContext) {
const { storageUri, subscriptions } = context;
store.storageDir = storageUri!.fsPath;
vscode.workspace.onDidChangeConfiguration(
async (event) => {
if (event.affectsConfiguration(extensionName)) {
if (event.affectsConfiguration(EXT_NAME)) {
await updateConfiguration();
}
},
Expand Down Expand Up @@ -126,6 +127,7 @@ export function activate(context: vscode.ExtensionContext) {
new NodeVersionCodeLensProvider(context),
),
vscode.languages.registerHoverProvider(pkgJsonSelector, new NpmScriptsHoverProvider()),
vscode.languages.registerHoverProvider(pkgJsonSelector, new DependenciesHoverProvider()),
vscode.languages.registerDefinitionProvider(
pkgJsonSelector,
new DependenciesDefinitionProvider(),
Expand Down
Loading

0 comments on commit 9088f07

Please sign in to comment.