Skip to content

Commit

Permalink
feat(core): find references for files not in proj
Browse files Browse the repository at this point in the history
- looks for changed file basename references in cwd
- compares referencing file and change file path
- if equals adds the found line number to changed files
  • Loading branch information
EladBezalel committed Oct 23, 2023
1 parent b51d992 commit bb72919
Show file tree
Hide file tree
Showing 15 changed files with 423 additions and 108 deletions.
Empty file.
12 changes: 12 additions & 0 deletions libs/core/src/__fixtures__/monorepo/angular-component/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore-next-line
import { Component } from '@angular/core';

@Component({
selector: 'example-component',
templateUrl: './component.html',
styleUrls: ['./component.css'],
})
export class AppComponent {
title = 'example';
}
10 changes: 9 additions & 1 deletion libs/core/src/git.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,15 @@ describe('git', () => {
it('should return diff', () => {
const diff = getDiff({
base: branch,
cwd,
});

expect(diff).toEqual(expect.any(String));
});

it('should return diff from absolute cwd path', () => {
const diff = getDiff({
base: branch,
cwd: absoluteCwd,
});

expect(diff).toEqual(expect.any(String));
Expand Down
9 changes: 5 additions & 4 deletions libs/core/src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ export function getMergeBase({

export function getDiff({ base, cwd }: BaseGitActionArgs): string {
try {
const diffCommand = cwd
? `git diff ${base} --unified=0 --relative -- ${resolve(cwd)}`
: `git diff ${base} --unified=0 `;
const diffCommand =
cwd != null
? `git diff ${base} --unified=0 --relative -- ${resolve(cwd)}`
: `git diff ${base} --unified=0 `;

return execSync(diffCommand, {
maxBuffer: TEN_MEGABYTES,
Expand All @@ -60,7 +61,7 @@ export function getDiff({ base, cwd }: BaseGitActionArgs): string {
}
}

interface GetChangedFiles {
export interface GetChangedFiles {
filePath: string;
changedLines: number[];
}
Expand Down
1 change: 1 addition & 0 deletions libs/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './true-affected';
export * from './types';
99 changes: 41 additions & 58 deletions libs/core/src/true-affected.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
trueAffected,
findRootNode,
getPackageNameByPath,
} from './true-affected';
import { Project, SyntaxKind } from 'ts-morph';
import { trueAffected } from './true-affected';
import * as git from './git';

describe('trueAffected', () => {
Expand Down Expand Up @@ -205,6 +200,46 @@ describe('trueAffected', () => {
expect(affected).toEqual([]);
});

it('should find files that are related to changed files which are not in projects files', async () => {
jest.spyOn(git, 'getChangedFiles').mockReturnValue([
{
filePath: 'angular-component/component.html',
changedLines: [6],
},
]);

const affected = await trueAffected({
cwd,
base: 'main',
rootTsConfig: 'tsconfig.json',
projects: [
{
name: 'angular-component',
sourceRoot: 'angular-component/',
tsConfig: 'angular-component/tsconfig.json',
},
{
name: 'proj1',
sourceRoot: 'proj1/',
tsConfig: 'proj1/tsconfig.json',
},
{
name: 'proj2',
sourceRoot: 'proj2/',
tsConfig: 'proj2/tsconfig.json',
},
{
name: 'proj3',
sourceRoot: 'proj3/',
tsConfig: 'proj3/tsconfig.json',
implicitDependencies: ['proj1'],
},
],
});

expect(affected).toEqual(['angular-component']);
});

it("should ignore files when can't find the changed line", async () => {
jest.spyOn(git, 'getChangedFiles').mockReturnValue([
{
Expand Down Expand Up @@ -320,55 +355,3 @@ describe('trueAffected', () => {
expect(affected).toEqual(expected);
});
});

describe('findRootNode', () => {
it('should find the root node', () => {
const project = new Project({ useInMemoryFileSystem: true });

const file = project.createSourceFile('file.ts', 'export const foo = 1;');

const node = file.getFirstDescendantByKind(SyntaxKind.Identifier);

const root = findRootNode(node);

expect(root?.getKind()).toEqual(SyntaxKind.VariableStatement);
});

it('should return undefined if could not find root node', () => {
const project = new Project({ useInMemoryFileSystem: true });

const file = project.createSourceFile('file.ts', 'export const foo = 1;');

const node = file.getFirstDescendantByKind(SyntaxKind.FunctionDeclaration);

const root = findRootNode(node);

expect(root?.getKindName()).toBeUndefined();
});
});

describe('getPackageNameByPath', () => {
it('should return the package name by path', () => {
const packageName = getPackageNameByPath('pkg1/index.ts', [
{
name: 'pkg1',
sourceRoot: 'pkg1/',
tsConfig: '',
},
]);

expect(packageName).toEqual('pkg1');
});

it('should return undefined if could not find package name', () => {
const packageName = getPackageNameByPath('pkg1/index.ts', [
{
name: 'pkg2',
sourceRoot: 'pkg2/',
tsConfig: '',
},
]);

expect(packageName).toBeUndefined();
});
});
61 changes: 28 additions & 33 deletions libs/core/src/true-affected.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import { existsSync } from 'fs';
import { join, resolve } from 'path';
import { Project, Node, ts, SyntaxKind } from 'ts-morph';
import { getChangedFiles } from './git';

export interface TrueAffectedProject {
name: string;
sourceRoot: string;
tsConfig?: string;
implicitDependencies?: string[];
}

export interface TrueAffected {
cwd: string;
rootTsConfig?: string;
base?: string;
projects: TrueAffectedProject[];
includeFiles?: string[];
}
import { GetChangedFiles, getChangedFiles } from './git';
import {
findNonSourceAffectedFiles,
findRootNode,
getPackageNameByPath,
} from './utils';
import { TrueAffected, TrueAffectedProject } from './types';

const ignoredRootNodeTypes = [
SyntaxKind.ImportDeclaration,
Expand All @@ -26,22 +17,6 @@ const ignoredRootNodeTypes = [
SyntaxKind.IfStatement,
];

export const findRootNode = (
node?: Node<ts.Node>
): Node<ts.Node> | undefined => {
if (node == null) return;
/* istanbul ignore next */
if (node.getParent()?.getKind() === SyntaxKind.SourceFile) return node;
return findRootNode(node.getParent());
};

export const getPackageNameByPath = (
path: string,
projects: TrueAffectedProject[]
): string | undefined => {
return projects.find(({ sourceRoot }) => path.includes(sourceRoot))?.name;
};

export const trueAffected = async ({
cwd,
rootTsConfig,
Expand Down Expand Up @@ -89,10 +64,30 @@ export const trueAffected = async ({
}
);

const changedFiles = getChangedFiles({ base, cwd }).filter(
const sourceChangedFiles: GetChangedFiles[] = getChangedFiles({
base,
cwd,
}).filter(
({ filePath }) => project.getSourceFile(resolve(cwd, filePath)) != null
);

const ignoredPaths = ['node_modules', 'dist', '.git'];

const nonSourceChangedFiles: GetChangedFiles[] = getChangedFiles({
base,
cwd,
})
.filter(
({ filePath }) =>
!filePath.match(/.*\.(ts|js)x?$/g) &&
project.getSourceFile(resolve(cwd, filePath)) == null
)
.flatMap(({ filePath: changedFilePath }) =>
findNonSourceAffectedFiles(cwd, changedFilePath, ignoredPaths)
);

const changedFiles = [...sourceChangedFiles, ...nonSourceChangedFiles];

const affectedPackages = new Set<string>();
const visitedIdentifiers = new Map<string, string[]>();

Expand Down
14 changes: 14 additions & 0 deletions libs/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface TrueAffectedProject {
name: string;
sourceRoot: string;
tsConfig?: string;
implicitDependencies?: string[];
}

export interface TrueAffected {
cwd: string;
rootTsConfig?: string;
base?: string;
projects: TrueAffectedProject[];
includeFiles?: string[];
}
Loading

0 comments on commit bb72919

Please sign in to comment.