Skip to content

Commit

Permalink
chore(core): reconcile functions to find project of a path
Browse files Browse the repository at this point in the history
  • Loading branch information
FrozenPandaz committed Nov 23, 2022
1 parent 76d8362 commit 21cd53a
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 249 deletions.
18 changes: 8 additions & 10 deletions packages/angular/src/generators/component/lib/normalize-options.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import type { Tree } from '@nrwl/devkit';
import {
joinPathFragments,
readCachedProjectGraph,
readProjectConfiguration,
readWorkspaceConfiguration,
} from '@nrwl/devkit';
import type { NormalizedSchema, Schema } from '../schema';
import { getProjectNameFromDirPath } from 'nx/src/utils/project-graph-utils';

function getProjectFromPath(path: string) {
try {
return getProjectNameFromDirPath(path);
} catch {
return null;
}
}
import {
createProjectRootMappings,
findProjectForPath,
} from 'nx/src/project-graph/utils/find-project-for-path';

export function normalizeOptions(
tree: Tree,
options: Schema
): NormalizedSchema {
const projectGraph = readCachedProjectGraph();
const projectRootMappings = createProjectRootMappings(projectGraph.nodes);
const project =
options.project ??
getProjectFromPath(options.path) ??
findProjectForPath(options.path, projectRootMappings) ??
readWorkspaceConfiguration(tree).defaultProject;
const { projectType, root, sourceRoot } = readProjectConfiguration(
tree,
Expand Down
15 changes: 12 additions & 3 deletions packages/eslint-plugin-nx/src/rules/enforce-module-boundaries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export default createESLintRule<Options, MessageIds>({
);
const fileName = normalizePath(context.getFilename());

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

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

const sourceFilePath = getSourceFilePath(fileName, projectPath);

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

if (isAbsoluteImportIntoAnotherProj) {
targetProject = findTargetProject(projectGraph, imp);
targetProject = findTargetProject(
projectGraph,
projectRootMappings,
imp
);
} else {
targetProject = getTargetProjectBasedOnRelativeImport(
imp,
projectPath,
projectGraph,
projectRootMappings,
sourceFilePath
);
}
Expand Down
8 changes: 6 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,18 @@ export default createESLintRule<Options, MessageIds>({
return {};
}

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

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

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

export function ensureGlobalProjectGraph(ruleName: string) {
/**
Expand All @@ -20,8 +20,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).projectRootMappings = createProjectRootMappings(
(global as any).projectGraph
);
} catch {
const WARNING_PREFIX = `${chalk.reset.keyword('orange')('warning')}`;
Expand All @@ -34,7 +35,13 @@ export function ensureGlobalProjectGraph(ruleName: string) {
}
}

export function readProjectGraph(ruleName: string) {
export function readProjectGraph(ruleName: string): {
projectGraph: ProjectGraph;
projectRootMappings: ProjectRootMappings;
} {
ensureGlobalProjectGraph(ruleName);
return (global as any).projectGraph as MappedProjectGraph;
return {
projectGraph: (global as any).projectGraph,
projectRootMappings: (global as any).projectRootMappings,
};
}
70 changes: 23 additions & 47 deletions packages/eslint-plugin-nx/src/utils/runtime-lint-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import { getPath, pathExists } from './graph-utils';
import { existsSync } from 'fs';
import { readFileIfExisting } from 'nx/src/project-graph/file-utils';
import { TargetProjectLocator } from 'nx/src/utils/target-project-locator';

export type MappedProjectGraph<T = any> = ProjectGraph<T> & {
allFiles: Record<string, string>;
};
import {
findProjectForPath,
ProjectRootMappings,
} from 'nx/src/project-graph/utils/find-project-for-path';

export type Deps = { [projectName: string]: ProjectGraphDependency[] };
export type DepConstraint = {
Expand Down Expand Up @@ -103,7 +103,8 @@ export function isRelative(s: string) {
export function getTargetProjectBasedOnRelativeImport(
imp: string,
projectPath: string,
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
projectRootMappings: ProjectRootMappings,
sourceFilePath: string
): ProjectGraphProjectNode<any> | undefined {
if (!isRelative(imp)) {
Expand All @@ -115,42 +116,39 @@ export function getTargetProjectBasedOnRelativeImport(
projectPath.length + 1
);

return findTargetProject(projectGraph, targetFile);
}

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

export function findSourceProject(
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
projectRootMappings: ProjectRootMappings,
sourceFilePath: string
) {
const targetFile = removeExt(sourceFilePath);
return findProjectUsingFile(projectGraph, targetFile);
return projectGraph.nodes[
findProjectForPath(targetFile, projectRootMappings)
];
}

export function findTargetProject(
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
projectRootMappings: ProjectRootMappings,
targetFile: string
) {
let targetProject = findProjectUsingFile(projectGraph, targetFile);
let targetProject = findProjectForPath(targetFile, projectRootMappings);
if (!targetProject) {
targetProject = findProjectUsingFile(
projectGraph,
normalizePath(path.join(targetFile, 'index'))
targetProject = findProjectForPath(
normalizePath(path.join(targetFile, 'index')),
projectRootMappings
);
}
if (!targetProject) {
targetProject = findProjectUsingFile(
projectGraph,
normalizePath(path.join(targetFile, 'src', 'index'))
targetProject = findProjectForPath(
normalizePath(path.join(targetFile, 'src', 'index')),
projectRootMappings
);
}
return targetProject;
return projectGraph.nodes[targetProject];
}

export function isAbsoluteImportIntoAnotherProject(
Expand All @@ -166,7 +164,7 @@ export function isAbsoluteImportIntoAnotherProject(
}

export function findProjectUsingImport(
projectGraph: MappedProjectGraph,
projectGraph: ProjectGraph,
targetProjectLocator: TargetProjectLocator,
filePath: string,
imp: string
Expand Down Expand Up @@ -353,28 +351,6 @@ export function hasBuildExecutor(
);
}

export function mapProjectGraphFiles<T>(
projectGraph: ProjectGraph<T>
): MappedProjectGraph | null {
if (!projectGraph) {
return null;
}
const allFiles: 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;
});
});

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

const ESLINT_REGEX = /node_modules.*[\/\\]eslint$/;
const JEST_REGEX = /node_modules\/.bin\/jest$/; // when we run unit tests in jest
const NRWL_CLI_REGEX = /nx[\/\\]bin[\/\\]run-executor\.js$/;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { NxJsonConfiguration } from '../../../config/nx-json';
import { ProjectGraphProjectNode } from '../../../config/project-graph';
import {
createProjectRootMappings,
findMatchingProjectForPath,
} from '../../../utils/target-project-locator';
findProjectForPath,
} from '../../utils/find-project-for-path';

export const getTouchedProjects: TouchedProjectLocator = (
touchedFiles,
Expand All @@ -14,7 +14,7 @@ export const getTouchedProjects: TouchedProjectLocator = (
const projectRootMap = createProjectRootMappings(projectGraphNodes);

return touchedFiles.reduce((affected, f) => {
const matchingProject = findMatchingProjectForPath(f.file, projectRootMap);
const matchingProject = findProjectForPath(f.file, projectRootMap);
if (matchingProject) {
affected.push(matchingProject);
}
Expand Down
76 changes: 18 additions & 58 deletions packages/nx/src/project-graph/file-map-utils.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,23 @@
import { dirname } from 'path';
import { FileData, ProjectFileMap } from '../config/project-graph';

function createProjectRootMappings(
workspaceJson: any,
projectFileMap: ProjectFileMap
) {
const projectRootMappings = new Map();
for (const projectName of Object.keys(workspaceJson.projects)) {
if (!projectFileMap[projectName]) {
projectFileMap[projectName] = [];
}
const root =
workspaceJson.projects[projectName].root === ''
? '.'
: workspaceJson.projects[projectName].root;
projectRootMappings.set(
root.endsWith('/') ? root.substring(0, root.length - 1) : root,
projectFileMap[projectName]
);
}
return projectRootMappings;
}

function findMatchingProjectFiles(
projectRootMappings: Map<string, FileData[]>,
file: string
) {
let currentPath = file;
do {
currentPath = dirname(currentPath);
const p = projectRootMappings.get(currentPath);
if (p) {
return p;
}
} while (currentPath != dirname(currentPath));

return null;
}
import {
createProjectRootMappingsFromProjectConfigurations,
findProjectForPath,
} from './utils/find-project-for-path';

export function createProjectFileMap(
workspaceJson: any,
allWorkspaceFiles: FileData[]
): { projectFileMap: ProjectFileMap; allWorkspaceFiles: FileData[] } {
const projectFileMap: ProjectFileMap = {};
const projectRootMappings = createProjectRootMappings(
workspaceJson,
projectFileMap
);
const projectRootMappings =
createProjectRootMappingsFromProjectConfigurations(workspaceJson.projects);

for (const projectName of Object.keys(workspaceJson.projects)) {
projectFileMap[projectName] ??= [];
}
for (const f of allWorkspaceFiles) {
const matchingProjectFiles = findMatchingProjectFiles(
projectRootMappings,
f.file
);
const matchingProjectFiles =
projectFileMap[findProjectForPath(f.file, projectRootMappings)];
if (matchingProjectFiles) {
matchingProjectFiles.push(f);
}
Expand All @@ -66,16 +32,12 @@ export function updateProjectFileMap(
updatedFiles: Map<string, string>,
deletedFiles: string[]
): { projectFileMap: ProjectFileMap; allWorkspaceFiles: FileData[] } {
const projectRootMappings = createProjectRootMappings(
workspaceJson,
projectFileMap
);
const projectRootMappings =
createProjectRootMappingsFromProjectConfigurations(workspaceJson.projects);

for (const f of updatedFiles.keys()) {
const matchingProjectFiles = findMatchingProjectFiles(
projectRootMappings,
f
);
const matchingProjectFiles =
projectFileMap[findProjectForPath(f, projectRootMappings)] ?? [];
if (matchingProjectFiles) {
const fileData: FileData = matchingProjectFiles.find((t) => t.file === f);
if (fileData) {
Expand All @@ -100,10 +62,8 @@ export function updateProjectFileMap(
}

for (const f of deletedFiles) {
const matchingProjectFiles = findMatchingProjectFiles(
projectRootMappings,
f
);
const matchingProjectFiles =
projectFileMap[findProjectForPath(f, projectRootMappings)] ?? [];
if (matchingProjectFiles) {
const index = matchingProjectFiles.findIndex((t) => t.file === f);
if (index > -1) {
Expand Down
Loading

0 comments on commit 21cd53a

Please sign in to comment.