@archest/vitest 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +16 -0
- package/dist/index.js +1 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +44 -764
- package/dist/index.mjs.map +1 -1
- package/dist/matchers/index.d.ts +16 -0
- package/dist/matchers/models.d.ts +201 -0
- package/node_modules/@archest/core/dist/classes/locateClasses.d.ts +5 -0
- package/node_modules/@archest/core/dist/classes/types.d.ts +25 -0
- package/node_modules/@archest/core/dist/dto.d.ts +78 -0
- package/node_modules/@archest/core/dist/files/checkDependOnExternalModule.d.ts +3 -0
- package/node_modules/@archest/core/dist/files/getFileDependencies.d.ts +2 -0
- package/node_modules/@archest/core/dist/files/locateFiles.d.ts +4 -0
- package/node_modules/@archest/core/dist/files/types.d.ts +17 -0
- package/node_modules/@archest/core/dist/functions/locateFunctions.d.ts +5 -0
- package/node_modules/@archest/core/dist/functions/types.d.ts +19 -0
- package/node_modules/@archest/core/dist/index.d.ts +43 -0
- package/node_modules/@archest/core/dist/index.js +14 -0
- package/node_modules/@archest/core/dist/index.js.map +1 -0
- package/node_modules/@archest/core/dist/index.mjs +615 -0
- package/node_modules/@archest/core/dist/index.mjs.map +1 -0
- package/node_modules/@archest/core/dist/layers/createLayeredArchitecture.d.ts +3 -0
- package/node_modules/@archest/core/dist/layers/getLayerDependencies.d.ts +2 -0
- package/node_modules/@archest/core/dist/layers/types.d.ts +8 -0
- package/node_modules/@archest/core/dist/project/parseProject.d.ts +55 -0
- package/node_modules/@archest/core/dist/properties/locateProperties.d.ts +5 -0
- package/node_modules/@archest/core/dist/properties/types.d.ts +17 -0
- package/node_modules/@archest/core/dist/shared/sharedCheckHaveMaxCyclomaticComplexity.d.ts +1 -0
- package/node_modules/@archest/core/dist/shared/sharedCheckHaveMinMaintainabilityIndex.d.ts +1 -0
- package/node_modules/@archest/core/dist/shared/sharedCheckHaveModifier.d.ts +7 -0
- package/node_modules/@archest/core/dist/shared/sharedCheckHaveNameMatchingFileName.d.ts +3 -0
- package/node_modules/@archest/core/dist/shared/sharedCheckMatchNamePattern.d.ts +1 -0
- package/node_modules/@archest/core/dist/slices/locateSlices.d.ts +3 -0
- package/node_modules/@archest/core/dist/slices/types.d.ts +8 -0
- package/node_modules/@archest/core/package.json +49 -0
- package/node_modules/@archest/core-rust/core-rust.darwin-arm64.node +0 -0
- package/node_modules/@archest/core-rust/core-rust.linux-x64-gnu.node +0 -0
- package/node_modules/@archest/core-rust/core-rust.win32-x64-msvc.node +0 -0
- package/node_modules/@archest/core-rust/index.d.ts +16 -0
- package/node_modules/@archest/core-rust/index.js +316 -0
- package/node_modules/@archest/core-rust/package.json +34 -0
- package/package.json +12 -1
- package/dist/src/core/classes/locateClasses.d.ts +0 -3
- package/dist/src/core/classes/types.d.ts +0 -14
- package/dist/src/core/files/getFileDependencies.d.ts +0 -2
- package/dist/src/core/files/locateFiles.d.ts +0 -3
- package/dist/src/core/files/types.d.ts +0 -10
- package/dist/src/core/functions/locateFunctions.d.ts +0 -3
- package/dist/src/core/functions/types.d.ts +0 -11
- package/dist/src/core/layers/createLayeredArchitecture.d.ts +0 -3
- package/dist/src/core/layers/getLayerDependencies.d.ts +0 -2
- package/dist/src/core/layers/types.d.ts +0 -8
- package/dist/src/core/project/parseProject.d.ts +0 -22
- package/dist/src/core/properties/locateProperties.d.ts +0 -3
- package/dist/src/core/properties/types.d.ts +0 -10
- package/dist/src/core/shared/sharedCheckHaveMaxCyclomaticComplexity.d.ts +0 -1
- package/dist/src/core/shared/sharedCheckHaveMinMaintainabilityIndex.d.ts +0 -1
- package/dist/src/core/shared/sharedCheckHaveModifier.d.ts +0 -2
- package/dist/src/core/shared/sharedCheckHaveNameMatchingFileName.d.ts +0 -2
- package/dist/src/core/shared/sharedCheckMatchNamePattern.d.ts +0 -1
- package/dist/src/core/slices/locateSlices.d.ts +0 -3
- package/dist/src/core/slices/types.d.ts +0 -8
- package/dist/src/index.d.ts +0 -35
- package/dist/src/matchers/index.d.ts +0 -20
- package/src/core/classes/classCheckExtendClass.test.ts +0 -30
- package/src/core/classes/classCheckExtendClass.ts +0 -41
- package/src/core/classes/classCheckHaveMaxCyclomaticComplexity.test.ts +0 -8
- package/src/core/classes/classCheckHaveMaxCyclomaticComplexity.ts +0 -35
- package/src/core/classes/classCheckHaveModifier.test.ts +0 -30
- package/src/core/classes/classCheckHaveModifier.ts +0 -17
- package/src/core/classes/classCheckHaveNameMatchingFileName.test.ts +0 -30
- package/src/core/classes/classCheckHaveNameMatchingFileName.ts +0 -15
- package/src/core/classes/classCheckImplementInterface.test.ts +0 -30
- package/src/core/classes/classCheckImplementInterface.ts +0 -43
- package/src/core/classes/classCheckMatchNamePattern.test.ts +0 -8
- package/src/core/classes/classCheckMatchNamePattern.ts +0 -17
- package/src/core/classes/classCheckResideInFolder.test.ts +0 -8
- package/src/core/classes/classCheckResideInFolder.ts +0 -31
- package/src/core/classes/locateClasses.test.ts +0 -13
- package/src/core/classes/locateClasses.ts +0 -127
- package/src/core/classes/types.ts +0 -16
- package/src/core/files/checkDependOnFilesInFolder.test.ts +0 -7
- package/src/core/files/checkDependOnFilesInFolder.ts +0 -36
- package/src/core/files/fileCheckBeFreeOfCycles.test.ts +0 -7
- package/src/core/files/fileCheckBeFreeOfCycles.ts +0 -72
- package/src/core/files/fileCheckHaveMaxCyclomaticComplexity.test.ts +0 -8
- package/src/core/files/fileCheckHaveMaxCyclomaticComplexity.ts +0 -35
- package/src/core/files/fileCheckHaveMaxExportedFunctions.test.ts +0 -32
- package/src/core/files/fileCheckHaveMaxExportedFunctions.ts +0 -45
- package/src/core/files/fileCheckHaveMinMaintainabilityIndex.test.ts +0 -8
- package/src/core/files/fileCheckHaveMinMaintainabilityIndex.ts +0 -19
- package/src/core/files/fileCheckMatchNamePattern.test.ts +0 -30
- package/src/core/files/fileCheckMatchNamePattern.ts +0 -17
- package/src/core/files/getFileDependencies.ts +0 -43
- package/src/core/files/locateFiles.test.ts +0 -30
- package/src/core/files/locateFiles.ts +0 -31
- package/src/core/files/types.ts +0 -12
- package/src/core/functions/functionCheckHaveExplicitReturnType.test.ts +0 -30
- package/src/core/functions/functionCheckHaveExplicitReturnType.ts +0 -29
- package/src/core/functions/functionCheckHaveMaxCyclomaticComplexity.test.ts +0 -8
- package/src/core/functions/functionCheckHaveMaxCyclomaticComplexity.ts +0 -20
- package/src/core/functions/functionCheckHaveMinMaintainabilityIndex.test.ts +0 -8
- package/src/core/functions/functionCheckHaveMinMaintainabilityIndex.ts +0 -20
- package/src/core/functions/functionCheckHaveModifier.test.ts +0 -30
- package/src/core/functions/functionCheckHaveModifier.ts +0 -18
- package/src/core/functions/functionCheckHaveNameMatchingFileName.test.ts +0 -30
- package/src/core/functions/functionCheckHaveNameMatchingFileName.ts +0 -16
- package/src/core/functions/functionCheckMatchNamePattern.test.ts +0 -30
- package/src/core/functions/functionCheckMatchNamePattern.ts +0 -18
- package/src/core/functions/locateFunctions.test.ts +0 -16
- package/src/core/functions/locateFunctions.ts +0 -47
- package/src/core/functions/types.ts +0 -13
- package/src/core/layers/checkLayeredArchitecture.test.ts +0 -23
- package/src/core/layers/checkLayeredArchitecture.ts +0 -15
- package/src/core/layers/createLayeredArchitecture.test.ts +0 -13
- package/src/core/layers/createLayeredArchitecture.ts +0 -15
- package/src/core/layers/getLayerDependencies.ts +0 -45
- package/src/core/layers/layer.test.ts +0 -12
- package/src/core/layers/layer.ts +0 -10
- package/src/core/layers/layerShouldNotBeAccessedByAnyLayer.test.ts +0 -14
- package/src/core/layers/layerShouldNotBeAccessedByAnyLayer.ts +0 -40
- package/src/core/layers/layerShouldOnlyBeAccessedBy.test.ts +0 -15
- package/src/core/layers/layerShouldOnlyBeAccessedBy.ts +0 -48
- package/src/core/layers/types.ts +0 -9
- package/src/core/metrics/calculateCyclomaticComplexity.test.ts +0 -23
- package/src/core/metrics/calculateCyclomaticComplexity.ts +0 -36
- package/src/core/metrics/calculateMaintainabilityIndex.test.ts +0 -38
- package/src/core/metrics/calculateMaintainabilityIndex.ts +0 -47
- package/src/core/project/parseProject.test.ts +0 -19
- package/src/core/project/parseProject.ts +0 -216
- package/src/core/properties/locateProperties.test.ts +0 -19
- package/src/core/properties/locateProperties.ts +0 -41
- package/src/core/properties/propertyCheckBeReadonly.test.ts +0 -32
- package/src/core/properties/propertyCheckBeReadonly.ts +0 -27
- package/src/core/properties/types.ts +0 -12
- package/src/core/shared/sharedCheckHaveMaxCyclomaticComplexity.test.ts +0 -30
- package/src/core/shared/sharedCheckHaveMaxCyclomaticComplexity.ts +0 -23
- package/src/core/shared/sharedCheckHaveMinMaintainabilityIndex.test.ts +0 -30
- package/src/core/shared/sharedCheckHaveMinMaintainabilityIndex.ts +0 -23
- package/src/core/shared/sharedCheckHaveModifier.test.ts +0 -31
- package/src/core/shared/sharedCheckHaveModifier.ts +0 -51
- package/src/core/shared/sharedCheckHaveNameMatchingFileName.test.ts +0 -17
- package/src/core/shared/sharedCheckHaveNameMatchingFileName.ts +0 -36
- package/src/core/shared/sharedCheckMatchNamePattern.test.ts +0 -29
- package/src/core/shared/sharedCheckMatchNamePattern.ts +0 -22
- package/src/core/slices/locateSlices.test.ts +0 -22
- package/src/core/slices/locateSlices.ts +0 -35
- package/src/core/slices/sliceCheckBeFreeOfCycles.test.ts +0 -26
- package/src/core/slices/sliceCheckBeFreeOfCycles.ts +0 -91
- package/src/core/slices/sliceCheckHaveMaxDistanceFromMainSequence.test.ts +0 -27
- package/src/core/slices/sliceCheckHaveMaxDistanceFromMainSequence.ts +0 -110
- package/src/core/slices/types.ts +0 -9
- package/src/core/testUtils.ts +0 -61
- package/src/core/types.ts +0 -19
- package/src/core/utils/ruleBuilder.test.ts +0 -24
- package/src/core/utils/ruleBuilder.ts +0 -28
- package/src/index.ts +0 -35
- package/src/matchers/index.ts +0 -331
- package/test/architecture.test.ts +0 -152
- package/tsconfig.json +0 -18
- package/vite.config.ts +0 -18
- /package/{dist/src/core → node_modules/@archest/core/dist}/classes/classCheckExtendClass.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/classes/classCheckHaveMaxCyclomaticComplexity.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/classes/classCheckHaveModifier.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/classes/classCheckHaveNameMatchingFileName.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/classes/classCheckImplementInterface.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/classes/classCheckMatchNamePattern.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/classes/classCheckResideInFolder.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/files/checkDependOnFilesInFolder.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/files/fileCheckBeFreeOfCycles.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/files/fileCheckHaveMaxCyclomaticComplexity.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/files/fileCheckHaveMaxExportedFunctions.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/files/fileCheckHaveMinMaintainabilityIndex.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/files/fileCheckMatchNamePattern.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/functions/functionCheckHaveExplicitReturnType.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/functions/functionCheckHaveMaxCyclomaticComplexity.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/functions/functionCheckHaveMinMaintainabilityIndex.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/functions/functionCheckHaveModifier.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/functions/functionCheckHaveNameMatchingFileName.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/functions/functionCheckMatchNamePattern.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/layers/checkLayeredArchitecture.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/layers/layer.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/layers/layerShouldNotBeAccessedByAnyLayer.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/layers/layerShouldOnlyBeAccessedBy.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/metrics/calculateCyclomaticComplexity.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/metrics/calculateMaintainabilityIndex.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/properties/propertyCheckBeReadonly.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/slices/sliceCheckBeFreeOfCycles.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/slices/sliceCheckHaveMaxDistanceFromMainSequence.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/types.d.ts +0 -0
- /package/{dist/src/core → node_modules/@archest/core/dist}/utils/ruleBuilder.d.ts +0 -0
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type * as ts from 'typescript';
|
|
2
|
-
import type { LayeredArchitectureData } from './types';
|
|
3
|
-
|
|
4
|
-
export function createLayeredArchitecture(
|
|
5
|
-
files: ts.SourceFile[],
|
|
6
|
-
program: ts.Program,
|
|
7
|
-
): LayeredArchitectureData {
|
|
8
|
-
return {
|
|
9
|
-
type: 'LayeredArchitecture',
|
|
10
|
-
files,
|
|
11
|
-
layers: new Map<string, string>(),
|
|
12
|
-
assertions: [],
|
|
13
|
-
program,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript';
|
|
2
|
-
|
|
3
|
-
export function getLayerDependencies(
|
|
4
|
-
sourceFile: ts.SourceFile,
|
|
5
|
-
program: ts.Program,
|
|
6
|
-
): string[] {
|
|
7
|
-
const dependencies: string[] = [];
|
|
8
|
-
const compilerOptions = program.getCompilerOptions();
|
|
9
|
-
|
|
10
|
-
const visit = (node: ts.Node) => {
|
|
11
|
-
if (ts.isImportDeclaration(node)) {
|
|
12
|
-
const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;
|
|
13
|
-
const resolved = ts.resolveModuleName(
|
|
14
|
-
moduleSpecifier,
|
|
15
|
-
sourceFile.fileName,
|
|
16
|
-
compilerOptions,
|
|
17
|
-
ts.sys,
|
|
18
|
-
);
|
|
19
|
-
if (
|
|
20
|
-
resolved.resolvedModule?.resolvedFileName &&
|
|
21
|
-
!resolved.resolvedModule.isExternalLibraryImport
|
|
22
|
-
) {
|
|
23
|
-
dependencies.push(resolved.resolvedModule.resolvedFileName);
|
|
24
|
-
}
|
|
25
|
-
} else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {
|
|
26
|
-
const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;
|
|
27
|
-
const resolved = ts.resolveModuleName(
|
|
28
|
-
moduleSpecifier,
|
|
29
|
-
sourceFile.fileName,
|
|
30
|
-
compilerOptions,
|
|
31
|
-
ts.sys,
|
|
32
|
-
);
|
|
33
|
-
if (
|
|
34
|
-
resolved.resolvedModule?.resolvedFileName &&
|
|
35
|
-
!resolved.resolvedModule.isExternalLibraryImport
|
|
36
|
-
) {
|
|
37
|
-
dependencies.push(resolved.resolvedModule.resolvedFileName);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
ts.forEachChild(node, visit);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
visit(sourceFile);
|
|
44
|
-
return dependencies;
|
|
45
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createLayeredArchitecture } from './createLayeredArchitecture';
|
|
3
|
-
import { layer } from './layer';
|
|
4
|
-
|
|
5
|
-
describe('layer', () => {
|
|
6
|
-
it('should add a layer pattern to the architecture data', () => {
|
|
7
|
-
// biome-ignore lint/suspicious/noExplicitAny: Mocking TS types for tests
|
|
8
|
-
let data = createLayeredArchitecture([], {} as any);
|
|
9
|
-
data = layer(data, 'Domain', 'src/domain');
|
|
10
|
-
expect(data.layers.get('Domain')).toBe('src/domain');
|
|
11
|
-
});
|
|
12
|
-
});
|
package/src/core/layers/layer.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createLayeredArchitecture } from './createLayeredArchitecture';
|
|
3
|
-
import { layer } from './layer';
|
|
4
|
-
import { layerShouldNotBeAccessedByAnyLayer } from './layerShouldNotBeAccessedByAnyLayer';
|
|
5
|
-
|
|
6
|
-
describe('layerShouldNotBeAccessedByAnyLayer', () => {
|
|
7
|
-
it('should push an assertion to the data', () => {
|
|
8
|
-
// biome-ignore lint/suspicious/noExplicitAny: Mocking TS types for tests
|
|
9
|
-
let data = createLayeredArchitecture([], {} as any);
|
|
10
|
-
data = layer(data, 'Domain', 'src/domain');
|
|
11
|
-
data = layerShouldNotBeAccessedByAnyLayer(data, 'Domain');
|
|
12
|
-
expect(data.assertions.length).toBe(1);
|
|
13
|
-
});
|
|
14
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { getLayerDependencies } from './getLayerDependencies';
|
|
2
|
-
import type { LayeredArchitectureData } from './types';
|
|
3
|
-
|
|
4
|
-
export function layerShouldNotBeAccessedByAnyLayer(
|
|
5
|
-
data: LayeredArchitectureData,
|
|
6
|
-
targetLayer: string,
|
|
7
|
-
): LayeredArchitectureData {
|
|
8
|
-
if (!data.layers.has(targetLayer)) {
|
|
9
|
-
throw new Error(`Layer ${targetLayer} is not defined`);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
data.assertions.push((files) => {
|
|
13
|
-
const violations: string[] = [];
|
|
14
|
-
// biome-ignore lint/style/noNonNullAssertion: Safe map lookup
|
|
15
|
-
const targetPattern = data.layers.get(targetLayer)!;
|
|
16
|
-
|
|
17
|
-
for (const file of files) {
|
|
18
|
-
const filePath = file.fileName;
|
|
19
|
-
if (
|
|
20
|
-
!filePath.includes(`/${targetPattern}/`) &&
|
|
21
|
-
!filePath.includes(`\\${targetPattern}\\`)
|
|
22
|
-
) {
|
|
23
|
-
const dependencies = getLayerDependencies(file, data.program);
|
|
24
|
-
const importsTarget = dependencies.some(
|
|
25
|
-
(dep) =>
|
|
26
|
-
dep.includes(`/${targetPattern}/`) ||
|
|
27
|
-
dep.includes(`\\${targetPattern}\\`),
|
|
28
|
-
);
|
|
29
|
-
if (importsTarget) {
|
|
30
|
-
violations.push(
|
|
31
|
-
`File ${filePath} accesses layer ${targetLayer} but it shouldn't.`,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return violations;
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return data;
|
|
40
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createLayeredArchitecture } from './createLayeredArchitecture';
|
|
3
|
-
import { layer } from './layer';
|
|
4
|
-
import { layerShouldOnlyBeAccessedBy } from './layerShouldOnlyBeAccessedBy';
|
|
5
|
-
|
|
6
|
-
describe('layerShouldOnlyBeAccessedBy', () => {
|
|
7
|
-
it('should push an assertion to the data', () => {
|
|
8
|
-
// biome-ignore lint/suspicious/noExplicitAny: Mocking TS types for tests
|
|
9
|
-
let data = createLayeredArchitecture([], {} as any);
|
|
10
|
-
data = layer(data, 'Domain', 'src/domain');
|
|
11
|
-
data = layer(data, 'Infra', 'src/infra');
|
|
12
|
-
data = layerShouldOnlyBeAccessedBy(data, 'Domain', ['Infra']);
|
|
13
|
-
expect(data.assertions.length).toBe(1);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { getLayerDependencies } from './getLayerDependencies';
|
|
2
|
-
import type { LayeredArchitectureData } from './types';
|
|
3
|
-
|
|
4
|
-
export function layerShouldOnlyBeAccessedBy(
|
|
5
|
-
data: LayeredArchitectureData,
|
|
6
|
-
targetLayer: string,
|
|
7
|
-
allowedLayers: string[],
|
|
8
|
-
): LayeredArchitectureData {
|
|
9
|
-
if (!data.layers.has(targetLayer)) {
|
|
10
|
-
throw new Error(`Layer ${targetLayer} is not defined`);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
data.assertions.push((files) => {
|
|
14
|
-
const violations: string[] = [];
|
|
15
|
-
// biome-ignore lint/style/noNonNullAssertion: Safe map lookup
|
|
16
|
-
const targetPattern = data.layers.get(targetLayer)!;
|
|
17
|
-
// biome-ignore lint/style/noNonNullAssertion: Safe map lookup
|
|
18
|
-
const allowedPatterns = allowedLayers.map((l) => data.layers.get(l)!);
|
|
19
|
-
|
|
20
|
-
for (const file of files) {
|
|
21
|
-
const filePath = file.fileName;
|
|
22
|
-
const isInAllowedLayer = allowedPatterns.some(
|
|
23
|
-
(p) => filePath.includes(`/${p}/`) || filePath.includes(`\\${p}\\`),
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
!filePath.includes(`/${targetPattern}/`) &&
|
|
28
|
-
!filePath.includes(`\\${targetPattern}\\`) &&
|
|
29
|
-
!isInAllowedLayer
|
|
30
|
-
) {
|
|
31
|
-
const dependencies = getLayerDependencies(file, data.program);
|
|
32
|
-
const importsTarget = dependencies.some(
|
|
33
|
-
(dep) =>
|
|
34
|
-
dep.includes(`/${targetPattern}/`) ||
|
|
35
|
-
dep.includes(`\\${targetPattern}\\`),
|
|
36
|
-
);
|
|
37
|
-
if (importsTarget) {
|
|
38
|
-
violations.push(
|
|
39
|
-
`File ${filePath} accesses layer ${targetLayer} but only ${allowedLayers.join(', ')} are allowed.`,
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return violations;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return data;
|
|
48
|
-
}
|
package/src/core/layers/types.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createSourceFile, getFunctions } from '../testUtils';
|
|
3
|
-
import { calculateCyclomaticComplexity } from './calculateCyclomaticComplexity';
|
|
4
|
-
|
|
5
|
-
describe('calculateCyclomaticComplexity', () => {
|
|
6
|
-
it('should return 1 for a simple function', () => {
|
|
7
|
-
const sourceFile = createSourceFile('function simple() { return 1; }');
|
|
8
|
-
const fns = getFunctions(sourceFile);
|
|
9
|
-
expect(calculateCyclomaticComplexity(fns[0])).toBe(1);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('should calculate higher complexity for branches', () => {
|
|
13
|
-
const sourceFile = createSourceFile(`
|
|
14
|
-
function complex(a) {
|
|
15
|
-
if (a) return 1;
|
|
16
|
-
if (!a) return 2;
|
|
17
|
-
return a ? 3 : 4;
|
|
18
|
-
}
|
|
19
|
-
`);
|
|
20
|
-
const fns = getFunctions(sourceFile);
|
|
21
|
-
expect(calculateCyclomaticComplexity(fns[0])).toBe(4);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript';
|
|
2
|
-
|
|
3
|
-
export function calculateCyclomaticComplexity(node: ts.Node): number {
|
|
4
|
-
let complexity = 1;
|
|
5
|
-
|
|
6
|
-
const visit = (n: ts.Node) => {
|
|
7
|
-
switch (n.kind) {
|
|
8
|
-
case ts.SyntaxKind.IfStatement:
|
|
9
|
-
case ts.SyntaxKind.ForStatement:
|
|
10
|
-
case ts.SyntaxKind.ForInStatement:
|
|
11
|
-
case ts.SyntaxKind.ForOfStatement:
|
|
12
|
-
case ts.SyntaxKind.WhileStatement:
|
|
13
|
-
case ts.SyntaxKind.DoStatement:
|
|
14
|
-
case ts.SyntaxKind.CaseClause:
|
|
15
|
-
case ts.SyntaxKind.CatchClause:
|
|
16
|
-
case ts.SyntaxKind.ConditionalExpression:
|
|
17
|
-
complexity++;
|
|
18
|
-
break;
|
|
19
|
-
case ts.SyntaxKind.BinaryExpression: {
|
|
20
|
-
const binary = n as ts.BinaryExpression;
|
|
21
|
-
if (
|
|
22
|
-
binary.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||
|
|
23
|
-
binary.operatorToken.kind === ts.SyntaxKind.BarBarToken ||
|
|
24
|
-
binary.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken
|
|
25
|
-
) {
|
|
26
|
-
complexity++;
|
|
27
|
-
}
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
ts.forEachChild(n, visit);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
ts.forEachChild(node, visit);
|
|
35
|
-
return complexity;
|
|
36
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createSourceFile, getFunctions } from '../testUtils';
|
|
3
|
-
import { calculateMaintainabilityIndex } from './calculateMaintainabilityIndex';
|
|
4
|
-
|
|
5
|
-
describe('calculateMaintainabilityIndex', () => {
|
|
6
|
-
it('should return a high index for a simple function', () => {
|
|
7
|
-
const sourceFile = createSourceFile('function simple() { return 1; }');
|
|
8
|
-
const fns = getFunctions(sourceFile);
|
|
9
|
-
expect(calculateMaintainabilityIndex(fns[0])).toBeGreaterThan(80);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('should return a lower index for a complex function', () => {
|
|
13
|
-
const sourceFile = createSourceFile(`
|
|
14
|
-
function complex(a, b, c) {
|
|
15
|
-
if (a) {
|
|
16
|
-
if (b) {
|
|
17
|
-
for (let i = 0; i < 10; i++) {
|
|
18
|
-
console.log(c);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
switch(a) {
|
|
23
|
-
case 1: return 1;
|
|
24
|
-
case 2: return 2;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
`);
|
|
28
|
-
const fns = getFunctions(sourceFile);
|
|
29
|
-
const complexMI = calculateMaintainabilityIndex(fns[0]);
|
|
30
|
-
const simpleSourceFile = createSourceFile(
|
|
31
|
-
'function simple() { return 1; }',
|
|
32
|
-
);
|
|
33
|
-
const simpleMI = calculateMaintainabilityIndex(
|
|
34
|
-
getFunctions(simpleSourceFile)[0],
|
|
35
|
-
);
|
|
36
|
-
expect(complexMI).toBeLessThan(simpleMI);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript';
|
|
2
|
-
import { calculateCyclomaticComplexity } from './calculateCyclomaticComplexity';
|
|
3
|
-
|
|
4
|
-
export function calculateMaintainabilityIndex(node: ts.Node): number {
|
|
5
|
-
let operators = 0;
|
|
6
|
-
let operands = 0;
|
|
7
|
-
const uniqueOperators = new Set<number>();
|
|
8
|
-
const uniqueOperands = new Set<string>();
|
|
9
|
-
let linesOfCode = 1;
|
|
10
|
-
|
|
11
|
-
const sourceFile = node.getSourceFile();
|
|
12
|
-
if (sourceFile) {
|
|
13
|
-
const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
|
14
|
-
const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
|
|
15
|
-
linesOfCode = end.line - start.line + 1;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const visit = (n: ts.Node) => {
|
|
19
|
-
if (
|
|
20
|
-
ts.isBinaryExpression(n) ||
|
|
21
|
-
ts.isPrefixUnaryExpression(n) ||
|
|
22
|
-
ts.isPostfixUnaryExpression(n)
|
|
23
|
-
) {
|
|
24
|
-
operators++;
|
|
25
|
-
uniqueOperators.add(n.kind);
|
|
26
|
-
} else if (ts.isIdentifier(n) || ts.isLiteralExpression(n)) {
|
|
27
|
-
operands++;
|
|
28
|
-
uniqueOperands.add(n.getText(sourceFile));
|
|
29
|
-
}
|
|
30
|
-
ts.forEachChild(n, visit);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
visit(node);
|
|
34
|
-
|
|
35
|
-
const N = operators + operands;
|
|
36
|
-
const n = uniqueOperators.size + uniqueOperands.size;
|
|
37
|
-
const V = n === 0 ? 0 : N * Math.log2(n);
|
|
38
|
-
const CC = calculateCyclomaticComplexity(node);
|
|
39
|
-
|
|
40
|
-
const mi = Math.max(
|
|
41
|
-
0,
|
|
42
|
-
((171 - 5.2 * Math.log(V || 1) - 0.23 * CC - 16.2 * Math.log(linesOfCode)) *
|
|
43
|
-
100) /
|
|
44
|
-
171,
|
|
45
|
-
);
|
|
46
|
-
return mi;
|
|
47
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { parseProject } from './parseProject';
|
|
3
|
-
|
|
4
|
-
describe('parseProject', () => {
|
|
5
|
-
it('should parse the current project correctly', () => {
|
|
6
|
-
// Running from within vitest-arch, it should pick up the tsconfig
|
|
7
|
-
const project = parseProject();
|
|
8
|
-
expect(project).toHaveProperty('getFiles');
|
|
9
|
-
expect(project).toHaveProperty('getClasses');
|
|
10
|
-
expect(project).toHaveProperty('getFunctions');
|
|
11
|
-
expect(project).toHaveProperty('layeredArchitecture');
|
|
12
|
-
expect(project).toHaveProperty('getSlices');
|
|
13
|
-
|
|
14
|
-
// Verify it can get its own files
|
|
15
|
-
const coreFiles = project.getFiles({ inFolder: 'core' });
|
|
16
|
-
expect(coreFiles.files.length).toBeGreaterThan(0);
|
|
17
|
-
expect(coreFiles.type).toBe('FileLocator');
|
|
18
|
-
});
|
|
19
|
-
});
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { dirname } from 'node:path';
|
|
2
|
-
import * as ts from 'typescript';
|
|
3
|
-
import { locateClasses } from '../classes/locateClasses';
|
|
4
|
-
import type { ClassQueryOptions } from '../classes/types';
|
|
5
|
-
import { locateFiles } from '../files/locateFiles';
|
|
6
|
-
import type { FileQueryOptions } from '../files/types';
|
|
7
|
-
import { locateFunctions } from '../functions/locateFunctions';
|
|
8
|
-
import type { FunctionQueryOptions } from '../functions/types';
|
|
9
|
-
import { checkLayeredArchitecture } from '../layers/checkLayeredArchitecture';
|
|
10
|
-
import { createLayeredArchitecture } from '../layers/createLayeredArchitecture';
|
|
11
|
-
import { layer } from '../layers/layer';
|
|
12
|
-
import { layerShouldNotBeAccessedByAnyLayer } from '../layers/layerShouldNotBeAccessedByAnyLayer';
|
|
13
|
-
import { layerShouldOnlyBeAccessedBy } from '../layers/layerShouldOnlyBeAccessedBy';
|
|
14
|
-
import { locateProperties } from '../properties/locateProperties';
|
|
15
|
-
import type { PropertyQueryOptions } from '../properties/types';
|
|
16
|
-
import { locateSlices } from '../slices/locateSlices';
|
|
17
|
-
|
|
18
|
-
export function parseProject(options: { tsConfigFilePath?: string } = {}) {
|
|
19
|
-
let compilerOptions: ts.CompilerOptions = {};
|
|
20
|
-
const configPath =
|
|
21
|
-
options.tsConfigFilePath ||
|
|
22
|
-
ts.findConfigFile(process.cwd(), ts.sys.fileExists, 'tsconfig.json');
|
|
23
|
-
|
|
24
|
-
let program: ts.Program;
|
|
25
|
-
|
|
26
|
-
if (configPath) {
|
|
27
|
-
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
28
|
-
const parsedCommandLine = ts.parseJsonConfigFileContent(
|
|
29
|
-
configFile.config,
|
|
30
|
-
ts.sys,
|
|
31
|
-
dirname(configPath),
|
|
32
|
-
undefined,
|
|
33
|
-
configPath,
|
|
34
|
-
undefined,
|
|
35
|
-
[
|
|
36
|
-
{
|
|
37
|
-
extension: '.vue',
|
|
38
|
-
isMixedContent: true,
|
|
39
|
-
scriptKind: ts.ScriptKind.TS,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
extension: '.svelte',
|
|
43
|
-
isMixedContent: true,
|
|
44
|
-
scriptKind: ts.ScriptKind.TS,
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
);
|
|
48
|
-
compilerOptions = parsedCommandLine.options;
|
|
49
|
-
|
|
50
|
-
const host = ts.createCompilerHost(compilerOptions);
|
|
51
|
-
const originalGetSourceFile = host.getSourceFile;
|
|
52
|
-
|
|
53
|
-
// biome-ignore lint/suspicious/noExplicitAny: Dynamic require
|
|
54
|
-
let vueCompiler: any;
|
|
55
|
-
try {
|
|
56
|
-
vueCompiler = require('@vue/compiler-sfc');
|
|
57
|
-
} catch (_e) {
|
|
58
|
-
// Not a Vue project
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
host.getSourceFile = (
|
|
62
|
-
fileName,
|
|
63
|
-
languageVersion,
|
|
64
|
-
onError,
|
|
65
|
-
shouldCreateNewSourceFile,
|
|
66
|
-
) => {
|
|
67
|
-
if (fileName.endsWith('.vue')) {
|
|
68
|
-
const content = ts.sys.readFile(fileName);
|
|
69
|
-
if (content) {
|
|
70
|
-
let scriptContent = '';
|
|
71
|
-
if (vueCompiler) {
|
|
72
|
-
const parsed = vueCompiler.parse(content);
|
|
73
|
-
const script = parsed.descriptor.script;
|
|
74
|
-
const scriptSetup = parsed.descriptor.scriptSetup;
|
|
75
|
-
if (script) scriptContent += `${script.content}\n`;
|
|
76
|
-
if (scriptSetup) scriptContent += `${scriptSetup.content}\n`;
|
|
77
|
-
} else {
|
|
78
|
-
const match = content.match(/<script[^>]*>(.*?)<\/script>/s);
|
|
79
|
-
if (match) scriptContent = match[1];
|
|
80
|
-
}
|
|
81
|
-
return ts.createSourceFile(
|
|
82
|
-
fileName,
|
|
83
|
-
scriptContent,
|
|
84
|
-
languageVersion,
|
|
85
|
-
true,
|
|
86
|
-
ts.ScriptKind.TS,
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (fileName.endsWith('.svelte')) {
|
|
92
|
-
const content = ts.sys.readFile(fileName);
|
|
93
|
-
if (content) {
|
|
94
|
-
let scriptContent = '';
|
|
95
|
-
const match = content.match(/<script[^>]*>(.*?)<\/script>/s);
|
|
96
|
-
if (match) scriptContent = match[1];
|
|
97
|
-
return ts.createSourceFile(
|
|
98
|
-
fileName,
|
|
99
|
-
scriptContent,
|
|
100
|
-
languageVersion,
|
|
101
|
-
true,
|
|
102
|
-
ts.ScriptKind.TS,
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return originalGetSourceFile(
|
|
108
|
-
fileName,
|
|
109
|
-
languageVersion,
|
|
110
|
-
onError,
|
|
111
|
-
shouldCreateNewSourceFile,
|
|
112
|
-
);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
program = ts.createProgram({
|
|
116
|
-
rootNames: parsedCommandLine.fileNames,
|
|
117
|
-
options: compilerOptions,
|
|
118
|
-
host: host,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// Force the TypeScript compiler to bind the AST and populate .parent pointers
|
|
122
|
-
program.getTypeChecker();
|
|
123
|
-
} else {
|
|
124
|
-
throw new Error('Could not find tsconfig.json');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const getSourceFiles = () =>
|
|
128
|
-
program
|
|
129
|
-
.getSourceFiles()
|
|
130
|
-
.filter(
|
|
131
|
-
(sf) => !sf.isDeclarationFile && !sf.fileName.includes('node_modules'),
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
return {
|
|
135
|
-
getFiles: (queryOptions?: FileQueryOptions) => {
|
|
136
|
-
return locateFiles(getSourceFiles(), program, queryOptions);
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
getClasses: (queryOptions?: ClassQueryOptions) => {
|
|
140
|
-
const allClasses: ts.ClassDeclaration[] = [];
|
|
141
|
-
for (const sf of getSourceFiles()) {
|
|
142
|
-
const visit = (node: ts.Node) => {
|
|
143
|
-
if (ts.isClassDeclaration(node)) {
|
|
144
|
-
allClasses.push(node);
|
|
145
|
-
}
|
|
146
|
-
ts.forEachChild(node, visit);
|
|
147
|
-
};
|
|
148
|
-
visit(sf);
|
|
149
|
-
}
|
|
150
|
-
return locateClasses(allClasses, program, queryOptions);
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
layeredArchitecture: () => {
|
|
154
|
-
let data = createLayeredArchitecture(getSourceFiles(), program);
|
|
155
|
-
const api = {
|
|
156
|
-
layer: (name: string, folderPattern: string) => {
|
|
157
|
-
data = layer(data, name, folderPattern);
|
|
158
|
-
return api;
|
|
159
|
-
},
|
|
160
|
-
whereLayer: (name: string) => {
|
|
161
|
-
return {
|
|
162
|
-
shouldNotBeAccessedByAnyLayer: () => {
|
|
163
|
-
data = layerShouldNotBeAccessedByAnyLayer(data, name);
|
|
164
|
-
return api;
|
|
165
|
-
},
|
|
166
|
-
shouldOnlyBeAccessedBy: (...allowedLayers: string[]) => {
|
|
167
|
-
data = layerShouldOnlyBeAccessedBy(data, name, allowedLayers);
|
|
168
|
-
return api;
|
|
169
|
-
},
|
|
170
|
-
};
|
|
171
|
-
},
|
|
172
|
-
check: () => checkLayeredArchitecture(data),
|
|
173
|
-
get data() {
|
|
174
|
-
return data;
|
|
175
|
-
},
|
|
176
|
-
};
|
|
177
|
-
return api;
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
getFunctions: (queryOptions?: FunctionQueryOptions) => {
|
|
181
|
-
const allFunctions: ts.FunctionLikeDeclaration[] = [];
|
|
182
|
-
for (const sf of getSourceFiles()) {
|
|
183
|
-
const visit = (node: ts.Node) => {
|
|
184
|
-
if (
|
|
185
|
-
ts.isFunctionDeclaration(node) ||
|
|
186
|
-
ts.isMethodDeclaration(node) ||
|
|
187
|
-
ts.isArrowFunction(node)
|
|
188
|
-
) {
|
|
189
|
-
allFunctions.push(node);
|
|
190
|
-
}
|
|
191
|
-
ts.forEachChild(node, visit);
|
|
192
|
-
};
|
|
193
|
-
visit(sf);
|
|
194
|
-
}
|
|
195
|
-
return locateFunctions(allFunctions, program, queryOptions);
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
getProperties: (queryOptions?: PropertyQueryOptions) => {
|
|
199
|
-
const allProperties: ts.PropertyDeclaration[] = [];
|
|
200
|
-
for (const sf of getSourceFiles()) {
|
|
201
|
-
const visit = (node: ts.Node) => {
|
|
202
|
-
if (ts.isPropertyDeclaration(node)) {
|
|
203
|
-
allProperties.push(node);
|
|
204
|
-
}
|
|
205
|
-
ts.forEachChild(node, visit);
|
|
206
|
-
};
|
|
207
|
-
visit(sf);
|
|
208
|
-
}
|
|
209
|
-
return locateProperties(allProperties, program, queryOptions);
|
|
210
|
-
},
|
|
211
|
-
|
|
212
|
-
getSlices: (pattern: string) => {
|
|
213
|
-
return locateSlices(getSourceFiles(), program, pattern);
|
|
214
|
-
},
|
|
215
|
-
};
|
|
216
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import ts from 'typescript';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { createSourceFile } from '../testUtils';
|
|
4
|
-
import { locateProperties } from './locateProperties';
|
|
5
|
-
|
|
6
|
-
describe('locateProperties', () => {
|
|
7
|
-
it('should return all properties if no query options', () => {
|
|
8
|
-
const file1 = createSourceFile('class A { prop: string; }');
|
|
9
|
-
const properties: ts.PropertyDeclaration[] = [];
|
|
10
|
-
const visit = (node: ts.Node) => {
|
|
11
|
-
if (ts.isPropertyDeclaration(node)) properties.push(node);
|
|
12
|
-
ts.forEachChild(node, visit);
|
|
13
|
-
};
|
|
14
|
-
visit(file1);
|
|
15
|
-
// biome-ignore lint/suspicious/noExplicitAny: Mocking TS types for tests
|
|
16
|
-
const result = locateProperties(properties, {} as any);
|
|
17
|
-
expect(result.properties.length).toBe(1);
|
|
18
|
-
});
|
|
19
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import * as ts from 'typescript';
|
|
2
|
-
import type { PropertyLocatorData, PropertyQueryOptions } from './types';
|
|
3
|
-
|
|
4
|
-
export function locateProperties(
|
|
5
|
-
properties: ts.PropertyDeclaration[],
|
|
6
|
-
program: ts.Program,
|
|
7
|
-
options?: PropertyQueryOptions,
|
|
8
|
-
): PropertyLocatorData {
|
|
9
|
-
let filtered = properties;
|
|
10
|
-
|
|
11
|
-
if (options?.inFolder) {
|
|
12
|
-
filtered = filtered.filter((p) => {
|
|
13
|
-
const sourceFile = p.getSourceFile
|
|
14
|
-
? p.getSourceFile()
|
|
15
|
-
: p.parent
|
|
16
|
-
? ts.getSourceFileOfNode(p)
|
|
17
|
-
: undefined;
|
|
18
|
-
if (!sourceFile) return false;
|
|
19
|
-
return (
|
|
20
|
-
sourceFile.fileName.includes(`/${options.inFolder}/`) ||
|
|
21
|
-
sourceFile.fileName.includes(`\\${options.inFolder}\\`)
|
|
22
|
-
);
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (options?.matchNamePattern) {
|
|
27
|
-
const regex =
|
|
28
|
-
typeof options.matchNamePattern === 'string'
|
|
29
|
-
? new RegExp(options.matchNamePattern)
|
|
30
|
-
: options.matchNamePattern;
|
|
31
|
-
filtered = filtered.filter((p) => {
|
|
32
|
-
return ts.isIdentifier(p.name) && regex.test(p.name.text);
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
type: 'PropertyLocator',
|
|
38
|
-
properties: filtered,
|
|
39
|
-
program,
|
|
40
|
-
};
|
|
41
|
-
}
|