Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): optimize project graph file mapping #13249

Merged
merged 2 commits into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/angular/plugins/component-testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
stripIndents,
workspaceRoot,
} from '@nrwl/devkit';
import { mapProjectGraphFiles } from 'nx/src/utils/target-project-locator';
import { createProjectFileMappings } from 'nx/src/utils/target-project-locator';
import { lstatSync, mkdirSync, writeFileSync } from 'fs';
import { dirname, join, relative } from 'path';
import type { BrowserBuilderSchema } from '../src/builders/webpack-browser/webpack-browser.impl';
Expand Down Expand Up @@ -279,14 +279,16 @@ function withSchemaDefaults(options: any): BrowserBuilderSchema {
* this file should get cleaned up via the cypress executor
*/
function getTempStylesForTailwind(ctExecutorContext: ExecutorContext) {
const mappedGraph = mapProjectGraphFiles(ctExecutorContext.projectGraph);
const mappedGraphFiles = createProjectFileMappings(
ctExecutorContext.projectGraph
);
const ctProjectConfig = ctExecutorContext.projectGraph.nodes[
ctExecutorContext.projectName
].data as ProjectConfiguration;
// angular only supports `tailwind.config.{js,cjs}`
const ctProjectTailwindConfig = join(ctProjectConfig.root, 'tailwind.config');
const isTailWindInCtProject = !!mappedGraph.allFiles[ctProjectTailwindConfig];
const isTailWindInRoot = !!mappedGraph.allFiles['tailwind.config'];
const isTailWindInCtProject = !!mappedGraphFiles[ctProjectTailwindConfig];
const isTailWindInRoot = !!mappedGraphFiles['tailwind.config'];

if (isTailWindInRoot || isTailWindInCtProject) {
const pathToStyle = getTempTailwindPath(ctExecutorContext);
Expand Down
6 changes: 3 additions & 3 deletions packages/cypress/plugins/cypress-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
workspaceRoot,
} from '@nrwl/devkit';
import { readProjectsConfigurationFromProjectGraph } from 'nx/src/project-graph/project-graph';
import { mapProjectGraphFiles } from 'nx/src/utils/target-project-locator';
import { createProjectFileMappings } from 'nx/src/utils/target-project-locator';
import { dirname, extname, join, relative } from 'path';
import { lstatSync } from 'fs';

Expand Down Expand Up @@ -90,9 +90,9 @@ export function getProjectConfigByPath(
: configFileFromWorkspaceRoot
);

const mappedGraph = mapProjectGraphFiles(graph);
const mappedGraphFiles = createProjectFileMappings(graph);
const componentTestingProjectName =
mappedGraph.allFiles[normalizedPathFromWorkspaceRoot];
mappedGraphFiles[normalizedPathFromWorkspaceRoot];
if (
!componentTestingProjectName ||
!graph.nodes[componentTestingProjectName]?.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { TSESLint } from '@typescript-eslint/utils';
import { vol } from 'memfs';
import {
TargetProjectLocator,
mapProjectGraphFiles,
createProjectFileMappings,
} from 'nx/src/utils/target-project-locator';
import enforceModuleBoundaries, {
RULE_NAME as enforceModuleBoundariesRuleName,
Expand Down Expand Up @@ -1885,7 +1885,9 @@ function runRule(
projectGraph: ProjectGraph
): TSESLint.Linter.LintMessage[] {
(global as any).projectPath = `${process.cwd()}/proj`;
(global as any).projectGraph = mapProjectGraphFiles(projectGraph);
(global as any).projectGraph = projectGraph;
(global as any).projectGraphFileMappings =
createProjectFileMappings(projectGraph);
(global as any).targetProjectLocator = new TargetProjectLocator(
projectGraph.nodes,
projectGraph.externalNodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ export default createESLintRule<Options, MessageIds>({
);
const fileName = normalizePath(context.getFilename());

const projectGraph = readProjectGraph(RULE_NAME);
const { projectGraph, projectGraphFileMappings } =
readProjectGraph(RULE_NAME);

if (!projectGraph) {
return {};
Expand Down Expand Up @@ -198,7 +199,11 @@ export default createESLintRule<Options, MessageIds>({

const sourceFilePath = getSourceFilePath(fileName, projectPath);

const sourceProject = findSourceProject(projectGraph, sourceFilePath);
const sourceProject = findSourceProject(
projectGraph,
projectGraphFileMappings,
sourceFilePath
);
// If source is not part of an nx workspace, return.
if (!sourceProject) {
return;
Expand All @@ -210,12 +215,17 @@ export default createESLintRule<Options, MessageIds>({
let targetProject: ProjectGraphProjectNode | ProjectGraphExternalNode;

if (isAbsoluteImportIntoAnotherProj) {
targetProject = findTargetProject(projectGraph, imp);
targetProject = findTargetProject(
projectGraph,
projectGraphFileMappings,
imp
);
} else {
targetProject = getTargetProjectBasedOnRelativeImport(
imp,
projectPath,
projectGraph,
projectGraphFileMappings,
sourceFilePath
);
}
Expand Down
9 changes: 7 additions & 2 deletions packages/eslint-plugin-nx/src/rules/nx-plugin-checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,19 @@ export default createESLintRule<Options, MessageIds>({
return {};
}

const projectGraph = readProjectGraph(RULE_NAME);
const { projectGraph, projectGraphFileMappings } =
readProjectGraph(RULE_NAME);

const sourceFilePath = getSourceFilePath(
context.getFilename(),
workspaceRoot
);

const sourceProject = findSourceProject(projectGraph, sourceFilePath);
const sourceProject = findSourceProject(
projectGraph,
projectGraphFileMappings,
sourceFilePath
);
// If source is not part of an nx workspace, return.
if (!sourceProject) {
return {};
Expand Down
28 changes: 18 additions & 10 deletions packages/eslint-plugin-nx/src/utils/project-graph-utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { readCachedProjectGraph, readNxJson } from '@nrwl/devkit';
import {
mapProjectGraphFiles,
MappedProjectGraph,
} from 'nx/src/utils/target-project-locator';
import { ProjectGraph, readCachedProjectGraph, readNxJson } from '@nrwl/devkit';
import { createProjectFileMappings } from 'nx/src/utils/target-project-locator';
import { isTerminalRun } from './runtime-lint-utils';
import * as chalk from 'chalk';

Expand All @@ -11,7 +8,11 @@ export function ensureGlobalProjectGraph(ruleName: string) {
* Only reuse graph when running from terminal
* Enforce every IDE change to get a fresh nxdeps.json
*/
if (!(global as any).projectGraph || !isTerminalRun()) {
if (
!(global as any).projectGraph ||
!(global as any).projectGraphFileMappings ||
!isTerminalRun()
) {
const nxJson = readNxJson();
(global as any).workspaceLayout = nxJson.workspaceLayout;

Expand All @@ -20,8 +21,9 @@ export function ensureGlobalProjectGraph(ruleName: string) {
* the ProjectGraph may or may not exist by the time the lint rule is invoked for the first time.
*/
try {
(global as any).projectGraph = mapProjectGraphFiles(
readCachedProjectGraph()
(global as any).projectGraph = readCachedProjectGraph();
(global as any).projectGraphFileMappings = createProjectFileMappings(
(global as any).projectGraph
);
} catch {
const WARNING_PREFIX = `${chalk.reset.keyword('orange')('warning')}`;
Expand All @@ -34,7 +36,13 @@ export function ensureGlobalProjectGraph(ruleName: string) {
}
}

export function readProjectGraph(ruleName: string) {
export function readProjectGraph(ruleName: string): {
projectGraph: ProjectGraph;
projectGraphFileMappings: Record<string, string>;
} {
ensureGlobalProjectGraph(ruleName);
return (global as any).projectGraph as MappedProjectGraph;
return {
projectGraph: (global as any).projectGraph,
projectGraphFileMappings: (global as any).projectGraphFileMappings,
};
}
35 changes: 24 additions & 11 deletions packages/eslint-plugin-nx/src/utils/runtime-lint-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { existsSync } from 'fs';
import { readFileIfExisting } from 'nx/src/project-graph/file-utils';
import {
TargetProjectLocator,
MappedProjectGraph,
removeExt,
} from 'nx/src/utils/target-project-locator';

Expand Down Expand Up @@ -99,7 +98,8 @@ export function isRelative(s: string) {
export function getTargetProjectBasedOnRelativeImport(
imp: string,
projectPath: string,
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
projectGraphFileMappings: Record<string, string>,
sourceFilePath: string
): ProjectGraphProjectNode<any> | undefined {
if (!isRelative(imp)) {
Expand All @@ -111,38 +111,51 @@ export function getTargetProjectBasedOnRelativeImport(
projectPath.length + 1
);

return findTargetProject(projectGraph, targetFile);
return findTargetProject(projectGraph, projectGraphFileMappings, targetFile);
}

export function findProjectUsingFile<T>(
projectGraph: MappedProjectGraph<T>,
function findProjectUsingFile(
projectGraph: ProjectGraph,
projectGraphFileMappings: Record<string, string>,
file: string
): ProjectGraphProjectNode {
return projectGraph.nodes[projectGraph.allFiles[file]];
return projectGraph.nodes[projectGraphFileMappings[file]];
}

export function findSourceProject(
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
projectGraphFileMappings: Record<string, string>,
sourceFilePath: string
) {
const targetFile = removeExt(sourceFilePath);
return findProjectUsingFile(projectGraph, targetFile);
return findProjectUsingFile(
projectGraph,
projectGraphFileMappings,
targetFile
);
}

export function findTargetProject(
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
projectGraphFileMappings: Record<string, string>,
targetFile: string
) {
let targetProject = findProjectUsingFile(projectGraph, targetFile);
let targetProject = findProjectUsingFile(
projectGraph,
projectGraphFileMappings,
targetFile
);
if (!targetProject) {
targetProject = findProjectUsingFile(
projectGraph,
projectGraphFileMappings,
normalizePath(path.join(targetFile, 'index'))
);
}
if (!targetProject) {
targetProject = findProjectUsingFile(
projectGraph,
projectGraphFileMappings,
normalizePath(path.join(targetFile, 'src', 'index'))
);
}
Expand All @@ -162,7 +175,7 @@ export function isAbsoluteImportIntoAnotherProject(
}

export function findProjectUsingImport(
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
targetProjectLocator: TargetProjectLocator,
filePath: string,
imp: string
Expand Down
24 changes: 7 additions & 17 deletions packages/nx/src/utils/target-project-locator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ function filterRootExternalDependencies(
*/
export function createProjectRootMappings(
nodes: Record<string, ProjectGraphProjectNode>
) {
): Map<string, string> {
const projectRootMappings = new Map<string, string>();
for (const projectName of Object.keys(nodes)) {
const root = nodes[projectName].data.root;
Expand All @@ -218,10 +218,6 @@ export function createProjectRootMappings(
return projectRootMappings;
}

export type MappedProjectGraph<T = any> = ProjectGraph<T> & {
allFiles: Record<string, string>;
};

/**
* Strips the file extension from the file path
* @param file
Expand All @@ -237,26 +233,20 @@ export function removeExt(file: string): string {
* @param projectGraph
* @returns
*/
export function mapProjectGraphFiles<T>(
projectGraph: ProjectGraph<T>
): MappedProjectGraph | null {
if (!projectGraph) {
return null;
}
const allFiles: Record<string, string> = {};
export function createProjectFileMappings(
projectGraph: ProjectGraph
): Record<string, string> {
const result: Record<string, string> = {};
Object.entries(
projectGraph.nodes as Record<string, ProjectGraphProjectNode>
).forEach(([name, node]) => {
node.data.files.forEach(({ file }) => {
const fileName = removeExt(file);
allFiles[fileName] = name;
result[fileName] = name;
});
});

return {
...projectGraph,
allFiles,
};
return result;
}

/**
Expand Down