Skip to content

Commit

Permalink
feat: workspace codelens (#1075)
Browse files Browse the repository at this point in the history
  • Loading branch information
sandikbarr authored May 28, 2021
1 parent d2c4bd4 commit 3e18e99
Show file tree
Hide file tree
Showing 13 changed files with 389 additions and 67 deletions.
14 changes: 12 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@
{
"version": "0.2.0",
"configurations": [
{
"args": [
"--disable-extensions",
"--extensionDevelopmentPath=${workspaceFolder}/dist/apps/vscode"
],
"name": "Launch Extension",
"outFiles": ["${workspaceFolder}/out/**/*.js"],
"request": "launch",
"type": "pwa-extensionHost"
},
{
"name": "Run Extension In Dev Mode",
"type": "extensionHost",
"type": "pwa-extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--disable-extensions",
"--extensionDevelopmentPath=${workspaceFolder}/dist/apps/vscode"
],
"trace": "false",
"trace": false,
"internalConsoleOptions": "openOnFirstSessionStart",
"outFiles": [
"${workspaceFolder}/dist/apps/vscode",
Expand Down
14 changes: 12 additions & 2 deletions apps/vscode/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { existsSync } from 'fs';
import { dirname, join, parse } from 'path';
import {
commands,
ConfigurationChangeEvent,
Disposable,
ExtensionContext,
FileSystemWatcher,
languages,
tasks,
TreeView,
Uri,
Expand Down Expand Up @@ -33,7 +36,7 @@ import {
RunTargetTreeItem,
RunTargetTreeProvider,
} from '@nx-console/vscode/nx-run-target-view';
import { verifyNodeModules, verifyWorkspace } from '@nx-console/vscode/verify';
import { verifyNodeModules } from '@nx-console/vscode/verify';
import {
NxCommandsTreeItem,
NxCommandsTreeProvider,
Expand All @@ -42,6 +45,10 @@ import {
NxProjectTreeItem,
NxProjectTreeProvider,
} from '@nx-console/vscode/nx-project-view';
import {
verifyWorkspace,
WorkspaceCodeLensProvider,
} from '@nx-console/vscode/nx-workspace';
import { environment } from './environments/environment';

let runTargetTreeView: TreeView<RunTargetTreeItem>;
Expand Down Expand Up @@ -99,7 +106,7 @@ export function activate(c: ExtensionContext) {
);

const manuallySelectWorkspaceDefinitionCommand = commands.registerCommand(
LOCATE_YOUR_WORKSPACE.command!.command,
LOCATE_YOUR_WORKSPACE.command?.command || '',
async () => {
return manuallySelectWorkspaceDefinition();
}
Expand All @@ -117,6 +124,9 @@ export function activate(c: ExtensionContext) {
manuallySelectWorkspaceDefinitionCommand
);

// registers itself as a CodeLensProvider and watches config to dispose/re-register
new WorkspaceCodeLensProvider(context);

getTelemetry().extensionActivated((Date.now() - startTime) / 1000);
} catch (e) {
window.showErrorMessage(
Expand Down
44 changes: 43 additions & 1 deletion apps/vscode/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,17 @@
"menus": {
"explorer/context": [
{
"when": "isAngularWorkspace && config.nxConsole.enableGenerateFromContextMenu || isNxWorkspace && config.nxConsole.enableGenerateFromContextMenu",
"when": "isAngularWorkspace && config.nxConsole.enableGenerateFromContextMenu",
"command": "ng.generate.ui.fileexplorer",
"group": "explorerContext"
},
{
"when": "isAngularWorkspace && config.nxConsole.enableGenerateFromContextMenu",
"command": "ng.run.fileexplorer",
"group": "explorerContext"
},
{
"when": "isNxWorkspace && config.nxConsole.enableGenerateFromContextMenu",
"command": "nx.generate.ui.fileexplorer",
"group": "explorerContext"
},
Expand Down Expand Up @@ -82,6 +92,14 @@
}
],
"commandPalette": [
{
"command": "ng.generate.ui.fileexplorer",
"when": "false"
},
{
"command": "ng.run.fileexplorer",
"when": "false"
},
{
"command": "nx.generate.ui.fileexplorer",
"when": "false"
Expand Down Expand Up @@ -114,6 +132,10 @@
"command": "ng.test",
"when": "isAngularWorkspace"
},
{
"command": "ng.run",
"when": "isAngularWorkspace"
},
{
"command": "ng.lint.ui",
"when": "isAngularWorkspace"
Expand Down Expand Up @@ -300,6 +322,11 @@
"title": "test",
"command": "ng.test"
},
{
"category": "ng",
"title": "run",
"command": "ng.run"
},
{
"category": "ng",
"title": "lint (ui)",
Expand Down Expand Up @@ -335,6 +362,16 @@
"title": "generate (ui)",
"command": "ng.generate.ui"
},
{
"category": "ng",
"title": "ng generate (ui)",
"command": "ng.generate.ui.fileexplorer"
},
{
"category": "ng",
"title": "ng run",
"command": "ng.run.fileexplorer"
},
{
"category": "Nx",
"title": "lint",
Expand Down Expand Up @@ -493,6 +530,11 @@
"type": "boolean",
"default": true,
"description": "Shows or hides Nx Generate ui option from the file explorer context menu."
},
"nxConsole.enableWorkspaceConfigCodeLens": {
"type": "boolean",
"default": true,
"description": "Shows or hides CodeLens for running targets from the Nx workspace config file."
}
}
},
Expand Down
1 change: 1 addition & 0 deletions libs/vscode/configuration/src/lib/configuration-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const GLOBAL_CONFIG_KEYS = [
'enableTelemetry',
'useNVM',
'enableGenerateFromContextMenu',
'enableWorkspaceConfigCodeLens',
] as const;

/**
Expand Down
2 changes: 2 additions & 0 deletions libs/vscode/nx-workspace/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './lib/find-workspace-json-target';
export * from './lib/reveal-workspace-json';
export * from './lib/workspace-codelens-provider';
export * from './lib/verify-workspace';
93 changes: 93 additions & 0 deletions libs/vscode/nx-workspace/src/lib/find-workspace-json-target.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TextDocument } from 'vscode';
import { JSONVisitor, visit } from 'jsonc-parser';
import * as typescript from 'typescript';

export function findWorkspaceJsonTarget(
document: TextDocument,
Expand Down Expand Up @@ -61,3 +62,95 @@ export function findWorkspaceJsonTarget(

return scriptOffset;
}

export interface ProjectLocations {
[projectName: string]: ProjectTargetLocation;
}
export interface ProjectTargetLocation {
[target: string]: {
position: number;
configurations?: ProjectTargetLocation;
};
}

export function getProjectLocations(document: TextDocument) {
const projectLocations: ProjectLocations = {};
const json = typescript.parseJsonText('workspace.json', document.getText());
const statement = json.statements[0];
const projects = getProperties(statement.expression)?.find(
(property) => getPropertyName(property) === 'projects'
) as typescript.PropertyAssignment | undefined;

if (!projects) {
return projectLocations;
}

getProperties(projects.initializer)?.forEach((project) => {
const projectName = getPropertyName(project);
if (!projectName) {
return;
}
projectLocations[projectName] =
getPositions(project, ['architect', 'targets'], json) ?? {};
});

return projectLocations;
}

function getProperties(
objectLiteral: typescript.Node
): typescript.NodeArray<typescript.ObjectLiteralElementLike> | undefined {
if (typescript.isObjectLiteralExpression(objectLiteral)) {
return objectLiteral.properties;
} else if (typescript.isPropertyAssignment(objectLiteral)) {
return getProperties(objectLiteral.initializer);
}
}

function getPropertyName(property: typescript.ObjectLiteralElementLike) {
if (
typescript.isPropertyAssignment(property) &&
typescript.isStringLiteral(property.name)
) {
return property.name.text;
}
}

function getPositions(
property: typescript.Node,
properties: string[],
document: typescript.JsonSourceFile
): ProjectTargetLocation | undefined {
const objectLike = getProperties(property)?.find((prop) => {
const propName = getPropertyName(prop);
return properties.some((value) => propName === value);
});

if (!objectLike) {
return undefined;
}

return getProperties(objectLike)?.reduce<ProjectTargetLocation>(
(acc, prop) => {
const propName = getPropertyName(prop);

if (!propName) {
return acc;
}

acc[propName] = {
position: prop.getStart(document),
};

// get configuration positions
const configs = getPositions(prop, ['configurations'], document);

if (configs) {
acc[propName].configurations = configs;
}

return acc;
},
{}
);
}
Loading

0 comments on commit 3e18e99

Please sign in to comment.