Skip to content

Commit

Permalink
feat: Go to project.json file from workspace file with codelens
Browse files Browse the repository at this point in the history
  • Loading branch information
Cammisuli committed Nov 19, 2021
1 parent 3ed7119 commit 320c314
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 53 deletions.
1 change: 1 addition & 0 deletions libs/server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export {
toWorkspaceFormat,
} from './lib/utils/utils';
export { watchFile } from './lib/utils/watch-file';
export { buildProjectPath } from './lib/utils/build-project-path';
15 changes: 15 additions & 0 deletions libs/server/src/lib/utils/build-project-path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { dirname, join } from 'path';

/**
* Builds the project path from the given project name.
* @param workspaceJsonPath The full path to the workspace.json file
* @param projectPath The path to the project relative to the workspace.json file
* @returns The full path to the project.json file
*/
export function buildProjectPath(
workspaceJsonPath: string,
projectPath: string
): string {
const workspaceRootDir = dirname(workspaceJsonPath);
return join(workspaceRootDir, projectPath, 'project.json');
}
4 changes: 2 additions & 2 deletions libs/server/src/lib/utils/read-collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ export async function readCollectionsFromNodeModules(

const collections = await Promise.all(
packages.map(async (p) => {
const json = await readAndCacheJsonFile(
const { json } = await readAndCacheJsonFile(
join(p, 'package.json'),
nodeModulesDir
);
return {
packageName: p,
packageJson: json.json,
packageJson: json,
};
})
);
Expand Down
29 changes: 24 additions & 5 deletions libs/vscode/nx-workspace/src/lib/find-workspace-json-target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
export interface ProjectLocations {
[projectName: string]: {
position: number;
targets: ProjectTargetLocation;
targets?: ProjectTargetLocation;
projectPath?: string;
};
}
export interface ProjectTargetLocation {
Expand All @@ -34,10 +35,20 @@ export function getProjectLocations(document: TextDocument, projectName = '') {
if (!projectName) {
return;
}
projectLocations[projectName] = {
position: project.getStart(json),
targets: getPositions(project, ['architect', 'targets'], json) ?? {},
};

if (project)
if (isProjectPathConfig(project)) {
projectLocations[projectName] = {
position: project.getStart(json),
projectPath: project.initializer.getText(json).replace(/"/g, ''),
};
} else {
projectLocations[projectName] = {
position: project.getStart(json),
targets:
getPositions(project, ['architect', 'targets'], json) ?? {},
};
}
});
} else {
projectLocations[projectName] = {
Expand All @@ -61,6 +72,14 @@ function getProperties(
}
}

function isProjectPathConfig(
property: typescript.ObjectLiteralElementLike
): property is typescript.PropertyAssignment {
return (
isPropertyAssignment(property) && isStringLiteral(property.initializer)
);
}

function getPropertyName(property: typescript.ObjectLiteralElementLike) {
if (isPropertyAssignment(property) && isStringLiteral(property.name)) {
return property.name.text;
Expand Down
26 changes: 13 additions & 13 deletions libs/vscode/nx-workspace/src/lib/reveal-workspace-json.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { dirname, join } from 'path';
import { buildProjectPath } from '@nx-console/server';
import { Selection, TextDocument, Uri, window, workspace } from 'vscode';
import { getProjectLocations } from './find-workspace-json-target';
import { getRawWorkspace } from './get-raw-workspace';
Expand All @@ -15,11 +15,9 @@ export async function revealNxProject(
* if the project is a split config, just use the project.json as the "workspace.json"
*/
if (typeof rawWorkspace.projects[projectName] === 'string') {
const workspaceRootDir = dirname(workspaceJsonPath);
workspaceJsonPath = join(
workspaceRootDir,
rawWorkspace.projects[projectName] as unknown as string,
'project.json'
workspaceJsonPath = buildProjectPath(
workspaceJsonPath,
rawWorkspace.projects[projectName] as unknown as string
);
}

Expand All @@ -31,14 +29,16 @@ export async function revealNxProject(

let offset = projectLocations[projectName].position;
if (target) {
const projectTarget = projectLocations[projectName].targets[target.name];
const targetConfiguration =
projectTarget.configurations?.[target.configuration || ''];
const projectTarget = projectLocations[projectName].targets?.[target.name];
if (projectTarget) {
const targetConfiguration =
projectTarget.configurations?.[target.configuration || ''];

if (targetConfiguration) {
offset = targetConfiguration.position;
} else {
offset = projectTarget.position;
if (targetConfiguration) {
offset = targetConfiguration.position;
} else {
offset = projectTarget.position;
}
}
}

Expand Down
137 changes: 104 additions & 33 deletions libs/vscode/nx-workspace/src/lib/workspace-codelens-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,20 @@ import {
ExtensionContext,
languages,
Range,
Uri,
workspace,
} from 'vscode';
import { TextDocument } from 'vscode';
import { verifyWorkspace } from './verify-workspace';
import { getProjectLocations } from './find-workspace-json-target';
import {
getProjectLocations,
ProjectLocations,
} from './find-workspace-json-target';
import { GlobalConfigurationStore } from '@nx-console/vscode/configuration';
import { getRawWorkspace } from './get-raw-workspace';
import { buildProjectPath } from '@nx-console/server';

export class ProjectCodeLens extends CodeLens {
export class TargetCodeLens extends CodeLens {
constructor(
range: Range,
public workspaceType: 'nx' | 'ng',
Expand All @@ -26,6 +31,17 @@ export class ProjectCodeLens extends CodeLens {
super(range);
}
}

export class ProjectCodeLens extends CodeLens {
constructor(
range: Range,
public project: string,
public projectPath: string
) {
super(range);
}
}

export class WorkspaceCodeLensProvider implements CodeLensProvider {
/**
* CodeLensProvider is disposed and re-registered on setting changes
Expand Down Expand Up @@ -57,8 +73,8 @@ export class WorkspaceCodeLensProvider implements CodeLensProvider {
/**
* Find the project name of the corresponding project.json file
*/
const { rawWorkspace, workspaceJsonPath } = await getRawWorkspace();
if (document.uri.path.endsWith('project.json')) {
const { rawWorkspace } = await getRawWorkspace();
for (const [key, project] of Object.entries(rawWorkspace.projects)) {
if (
typeof project === 'string' &&
Expand All @@ -80,39 +96,83 @@ export class WorkspaceCodeLensProvider implements CodeLensProvider {

for (const projectName in projectLocations) {
const project = projectLocations[projectName];
const projectTargets = project.targets;
for (const target in projectTargets) {
const position = document.positionAt(projectTargets[target].position);

lens.push(
new ProjectCodeLens(
new Range(position, position),
workspaceType,
projectName,
target
)
);
const configurations = projectTargets[target].configurations;
if (configurations) {
for (const configuration in configurations) {
const configurationPosition = document.positionAt(
configurations[configuration].position
);

lens.push(
new ProjectCodeLens(
new Range(configurationPosition, configurationPosition),
workspaceType,
projectName,
target,
configuration
)
);
}
this.buildProjectLenses(
project,
document,
lens,
projectName,
workspaceJsonPath
);

this.buildTargetLenses(
project,
document,
lens,
workspaceType,
projectName
);
}
return lens;
}
buildProjectLenses(
project: ProjectLocations[string],
document: TextDocument,
lens: CodeLens[],
projectName: string,
workspaceJsonPath: string
) {
if (!project.projectPath) {
return;
}
const position = document.positionAt(project.position);
lens.push(
new ProjectCodeLens(
new Range(position, position),
projectName,
buildProjectPath(workspaceJsonPath, project.projectPath)
)
);
}

private buildTargetLenses(
project: ProjectLocations[string],
document: TextDocument,
lens: CodeLens[],
workspaceType: 'nx' | 'ng',
projectName: string
) {
const projectTargets = project.targets;
for (const target in projectTargets) {
const position = document.positionAt(projectTargets[target].position);

lens.push(
new TargetCodeLens(
new Range(position, position),
workspaceType,
projectName,
target
)
);
const configurations = projectTargets[target].configurations;
if (configurations) {
for (const configuration in configurations) {
const configurationPosition = document.positionAt(
configurations[configuration].position
);

lens.push(
new TargetCodeLens(
new Range(configurationPosition, configurationPosition),
workspaceType,
projectName,
target,
configuration
)
);
}
}
}
return lens;
}

/**
Expand All @@ -122,7 +182,7 @@ export class WorkspaceCodeLensProvider implements CodeLensProvider {
*/
// https://github.com/microsoft/vscode-extension-samples/blob/main/codelens-sample/src/CodelensProvider.ts
resolveCodeLens(lens: CodeLens): CodeLens | Promise<CodeLens> | null {
if (lens instanceof ProjectCodeLens) {
if (lens instanceof TargetCodeLens) {
const command: Command = {
command: `${lens.workspaceType}.run`,
title: lens.configuration
Expand All @@ -133,6 +193,17 @@ export class WorkspaceCodeLensProvider implements CodeLensProvider {
lens.command = command;
return lens;
}

if (lens instanceof ProjectCodeLens) {
const command: Command = {
command: `vscode.open`,
title: `Go to "${lens.project}" configuration`,
arguments: [Uri.file(lens.projectPath)],
};
lens.command = command;
return lens;
}

return null;
}

Expand Down

0 comments on commit 320c314

Please sign in to comment.