@archest/vitest 1.0.0 → 1.0.1
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.js +13 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +776 -489
- package/dist/index.mjs.map +1 -1
- package/dist/src/core/classes/classCheckExtendClass.d.ts +3 -0
- package/dist/src/core/classes/classCheckHaveMaxCyclomaticComplexity.d.ts +3 -0
- package/dist/src/core/classes/classCheckHaveModifier.d.ts +3 -0
- package/dist/src/core/classes/classCheckHaveNameMatchingFileName.d.ts +3 -0
- package/dist/src/core/classes/classCheckImplementInterface.d.ts +3 -0
- package/dist/src/core/classes/classCheckMatchNamePattern.d.ts +3 -0
- package/dist/src/core/classes/classCheckResideInFolder.d.ts +3 -0
- package/dist/src/core/classes/locateClasses.d.ts +3 -0
- package/dist/src/core/classes/types.d.ts +14 -0
- package/dist/src/core/files/checkDependOnFilesInFolder.d.ts +3 -0
- package/dist/src/core/files/fileCheckBeFreeOfCycles.d.ts +3 -0
- package/dist/src/core/files/fileCheckHaveMaxCyclomaticComplexity.d.ts +3 -0
- package/dist/src/core/files/fileCheckHaveMaxExportedFunctions.d.ts +3 -0
- package/dist/src/core/files/fileCheckHaveMinMaintainabilityIndex.d.ts +3 -0
- package/dist/src/core/files/fileCheckMatchNamePattern.d.ts +3 -0
- package/dist/src/core/files/getFileDependencies.d.ts +2 -0
- package/dist/src/core/files/locateFiles.d.ts +3 -0
- package/dist/src/core/files/types.d.ts +10 -0
- package/dist/src/core/functions/functionCheckHaveExplicitReturnType.d.ts +3 -0
- package/dist/src/core/functions/functionCheckHaveMaxCyclomaticComplexity.d.ts +3 -0
- package/dist/src/core/functions/functionCheckHaveMinMaintainabilityIndex.d.ts +3 -0
- package/dist/src/core/functions/functionCheckHaveModifier.d.ts +3 -0
- package/dist/src/core/functions/functionCheckHaveNameMatchingFileName.d.ts +3 -0
- package/dist/src/core/functions/functionCheckMatchNamePattern.d.ts +3 -0
- package/dist/src/core/functions/locateFunctions.d.ts +3 -0
- package/dist/src/core/functions/types.d.ts +11 -0
- package/dist/src/core/layers/checkLayeredArchitecture.d.ts +3 -0
- package/dist/src/core/layers/createLayeredArchitecture.d.ts +3 -0
- package/dist/src/core/layers/getLayerDependencies.d.ts +2 -0
- package/dist/src/core/layers/layer.d.ts +2 -0
- package/dist/src/core/layers/layerShouldNotBeAccessedByAnyLayer.d.ts +2 -0
- package/dist/src/core/layers/layerShouldOnlyBeAccessedBy.d.ts +2 -0
- package/dist/src/core/layers/types.d.ts +8 -0
- package/dist/src/core/metrics/calculateCyclomaticComplexity.d.ts +2 -0
- package/dist/src/core/metrics/calculateMaintainabilityIndex.d.ts +2 -0
- package/dist/src/core/project/parseProject.d.ts +22 -0
- package/dist/src/core/properties/locateProperties.d.ts +3 -0
- package/dist/src/core/properties/propertyCheckBeReadonly.d.ts +3 -0
- package/dist/src/core/properties/types.d.ts +10 -0
- package/dist/src/core/shared/sharedCheckHaveMaxCyclomaticComplexity.d.ts +1 -0
- package/dist/src/core/shared/sharedCheckHaveMinMaintainabilityIndex.d.ts +1 -0
- package/dist/src/core/shared/sharedCheckHaveModifier.d.ts +2 -0
- package/dist/src/core/shared/sharedCheckHaveNameMatchingFileName.d.ts +2 -0
- package/dist/src/core/shared/sharedCheckMatchNamePattern.d.ts +1 -0
- package/dist/src/core/slices/locateSlices.d.ts +3 -0
- package/dist/src/core/slices/sliceCheckBeFreeOfCycles.d.ts +3 -0
- package/dist/src/core/slices/sliceCheckHaveMaxDistanceFromMainSequence.d.ts +3 -0
- package/dist/src/core/slices/types.d.ts +8 -0
- package/dist/src/core/types.d.ts +7 -0
- package/dist/src/core/utils/ruleBuilder.d.ts +6 -0
- package/dist/src/index.d.ts +34 -8
- package/dist/src/matchers/index.d.ts +5 -0
- package/package.json +1 -1
- package/src/core/classes/classCheckExtendClass.test.ts +30 -0
- package/src/core/classes/classCheckExtendClass.ts +41 -0
- package/src/core/classes/classCheckHaveMaxCyclomaticComplexity.test.ts +8 -0
- package/src/core/classes/classCheckHaveMaxCyclomaticComplexity.ts +35 -0
- package/src/core/classes/classCheckHaveModifier.test.ts +30 -0
- package/src/core/classes/classCheckHaveModifier.ts +17 -0
- package/src/core/classes/classCheckHaveNameMatchingFileName.test.ts +30 -0
- package/src/core/classes/classCheckHaveNameMatchingFileName.ts +15 -0
- package/src/core/classes/classCheckImplementInterface.test.ts +30 -0
- package/src/core/classes/classCheckImplementInterface.ts +43 -0
- package/src/core/classes/classCheckMatchNamePattern.test.ts +8 -0
- package/src/core/classes/classCheckMatchNamePattern.ts +17 -0
- package/src/core/classes/classCheckResideInFolder.test.ts +8 -0
- package/src/core/classes/classCheckResideInFolder.ts +31 -0
- package/src/core/classes/locateClasses.test.ts +13 -0
- package/src/core/classes/locateClasses.ts +127 -0
- package/src/core/classes/types.ts +16 -0
- package/src/core/files/checkDependOnFilesInFolder.test.ts +7 -0
- package/src/core/files/checkDependOnFilesInFolder.ts +36 -0
- package/src/core/files/fileCheckBeFreeOfCycles.test.ts +7 -0
- package/src/core/files/fileCheckBeFreeOfCycles.ts +72 -0
- package/src/core/files/fileCheckHaveMaxCyclomaticComplexity.test.ts +8 -0
- package/src/core/files/fileCheckHaveMaxCyclomaticComplexity.ts +35 -0
- package/src/core/files/fileCheckHaveMaxExportedFunctions.test.ts +32 -0
- package/src/core/files/fileCheckHaveMaxExportedFunctions.ts +45 -0
- package/src/core/files/fileCheckHaveMinMaintainabilityIndex.test.ts +8 -0
- package/src/core/files/fileCheckHaveMinMaintainabilityIndex.ts +19 -0
- package/src/core/files/fileCheckMatchNamePattern.test.ts +30 -0
- package/src/core/files/fileCheckMatchNamePattern.ts +17 -0
- package/src/core/files/getFileDependencies.ts +43 -0
- package/src/core/files/locateFiles.test.ts +30 -0
- package/src/core/files/locateFiles.ts +31 -0
- package/src/core/files/types.ts +12 -0
- package/src/core/functions/functionCheckHaveExplicitReturnType.test.ts +30 -0
- package/src/core/functions/functionCheckHaveExplicitReturnType.ts +29 -0
- package/src/core/functions/functionCheckHaveMaxCyclomaticComplexity.test.ts +8 -0
- package/src/core/functions/functionCheckHaveMaxCyclomaticComplexity.ts +20 -0
- package/src/core/functions/functionCheckHaveMinMaintainabilityIndex.test.ts +8 -0
- package/src/core/functions/functionCheckHaveMinMaintainabilityIndex.ts +20 -0
- package/src/core/functions/functionCheckHaveModifier.test.ts +30 -0
- package/src/core/functions/functionCheckHaveModifier.ts +18 -0
- package/src/core/functions/functionCheckHaveNameMatchingFileName.test.ts +30 -0
- package/src/core/functions/functionCheckHaveNameMatchingFileName.ts +16 -0
- package/src/core/functions/functionCheckMatchNamePattern.test.ts +30 -0
- package/src/core/functions/functionCheckMatchNamePattern.ts +18 -0
- package/src/core/functions/locateFunctions.test.ts +16 -0
- package/src/core/functions/locateFunctions.ts +47 -0
- package/src/core/functions/types.ts +13 -0
- package/src/core/layers/checkLayeredArchitecture.test.ts +23 -0
- package/src/core/layers/checkLayeredArchitecture.ts +15 -0
- package/src/core/layers/createLayeredArchitecture.test.ts +13 -0
- package/src/core/layers/createLayeredArchitecture.ts +15 -0
- package/src/core/layers/getLayerDependencies.ts +45 -0
- package/src/core/layers/layer.test.ts +12 -0
- package/src/core/layers/layer.ts +10 -0
- package/src/core/layers/layerShouldNotBeAccessedByAnyLayer.test.ts +14 -0
- package/src/core/layers/layerShouldNotBeAccessedByAnyLayer.ts +40 -0
- package/src/core/layers/layerShouldOnlyBeAccessedBy.test.ts +15 -0
- package/src/core/layers/layerShouldOnlyBeAccessedBy.ts +48 -0
- package/src/core/layers/types.ts +9 -0
- package/src/core/metrics/calculateCyclomaticComplexity.test.ts +23 -0
- package/src/core/metrics/calculateCyclomaticComplexity.ts +36 -0
- package/src/core/metrics/calculateMaintainabilityIndex.test.ts +38 -0
- package/src/core/metrics/calculateMaintainabilityIndex.ts +47 -0
- package/src/core/project/parseProject.test.ts +19 -0
- package/src/core/project/parseProject.ts +216 -0
- package/src/core/properties/locateProperties.test.ts +19 -0
- package/src/core/properties/locateProperties.ts +41 -0
- package/src/core/properties/propertyCheckBeReadonly.test.ts +32 -0
- package/src/core/properties/propertyCheckBeReadonly.ts +27 -0
- package/src/core/properties/types.ts +12 -0
- package/src/core/shared/sharedCheckHaveMaxCyclomaticComplexity.test.ts +30 -0
- package/src/core/shared/sharedCheckHaveMaxCyclomaticComplexity.ts +23 -0
- package/src/core/shared/sharedCheckHaveMinMaintainabilityIndex.test.ts +30 -0
- package/src/core/shared/sharedCheckHaveMinMaintainabilityIndex.ts +23 -0
- package/src/core/shared/sharedCheckHaveModifier.test.ts +31 -0
- package/src/core/shared/sharedCheckHaveModifier.ts +51 -0
- package/src/core/shared/sharedCheckHaveNameMatchingFileName.test.ts +17 -0
- package/src/core/shared/sharedCheckHaveNameMatchingFileName.ts +36 -0
- package/src/core/shared/sharedCheckMatchNamePattern.test.ts +29 -0
- package/src/core/shared/sharedCheckMatchNamePattern.ts +22 -0
- package/src/core/slices/locateSlices.test.ts +22 -0
- package/src/core/slices/locateSlices.ts +35 -0
- package/src/core/slices/sliceCheckBeFreeOfCycles.test.ts +26 -0
- package/src/core/slices/sliceCheckBeFreeOfCycles.ts +91 -0
- package/src/core/slices/sliceCheckHaveMaxDistanceFromMainSequence.test.ts +27 -0
- package/src/core/slices/sliceCheckHaveMaxDistanceFromMainSequence.ts +110 -0
- package/src/core/slices/types.ts +9 -0
- package/src/core/testUtils.ts +61 -0
- package/src/core/types.ts +15 -0
- package/src/core/utils/ruleBuilder.test.ts +24 -0
- package/src/core/utils/ruleBuilder.ts +28 -0
- package/src/index.ts +34 -8
- package/src/matchers/index.ts +269 -51
- package/test/architecture.test.ts +109 -16
- package/tsconfig.json +2 -1
- package/vite.config.ts +2 -2
- package/dist/src/core/ClassLocator.d.ts +0 -20
- package/dist/src/core/FileLocator.d.ts +0 -15
- package/dist/src/core/FunctionLocator.d.ts +0 -15
- package/dist/src/core/LayerLocator.d.ts +0 -23
- package/dist/src/core/Project.d.ts +0 -20
- package/dist/src/core/PropertyLocator.d.ts +0 -12
- package/dist/src/core/SliceLocator.d.ts +0 -10
- package/src/core/ClassLocator.ts +0 -226
- package/src/core/FileLocator.ts +0 -168
- package/src/core/FunctionLocator.ts +0 -105
- package/src/core/LayerLocator.ts +0 -119
- package/src/core/Project.ts +0 -171
- package/src/core/PropertyLocator.ts +0 -50
- package/src/core/SliceLocator.ts +0 -92
package/dist/index.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`typescript`),require(`path`),require(`vitest`)):typeof define==`function`&&define.amd?define([`exports`,`typescript`,`path`,`vitest`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.VitestArch={},e.typescript,e.
|
|
2
|
-
`)}}
|
|
3
|
-
`)}}
|
|
4
|
-
`)}}
|
|
5
|
-
`)}}
|
|
6
|
-
`)}}
|
|
7
|
-
`)}}
|
|
8
|
-
`)}}
|
|
9
|
-
`)}}
|
|
10
|
-
`)}}},
|
|
11
|
-
`)}}
|
|
12
|
-
`)}}
|
|
13
|
-
`)}}
|
|
14
|
-
`)}}},v=class{slicePattern;sliceIds=new Set;sliceFiles=new Map;constructor(e,t,n){this.program=t;let r=n.replace(/[.+?^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`([^/\\\\]+)`);this.slicePattern=new RegExp(r);for(let t of e){let e=t.fileName.match(this.slicePattern);if(e&&e[1]){let n=e[1];this.sliceIds.add(n),this.sliceFiles.has(n)||this.sliceFiles.set(n,[]),this.sliceFiles.get(n).push(t)}}}checkBeFreeOfCycles(e){let n=new Map;for(let e of this.sliceIds)n.set(e,new Set);for(let[e,r]of this.sliceFiles.entries())for(let i of r)t.forEachChild(i,r=>{if(t.isImportDeclaration(r)&&r.moduleSpecifier&&t.isStringLiteral(r.moduleSpecifier)){let a=r.moduleSpecifier.text,o=t.resolveModuleName(a,i.fileName,this.program.getCompilerOptions(),t.sys);if(o.resolvedModule&&o.resolvedModule.resolvedFileName){let t=o.resolvedModule.resolvedFileName.match(this.slicePattern);if(t&&t[1]){let r=t[1];r!==e&&this.sliceIds.has(r)&&n.get(e).add(r)}}}});let r=new Set,i=new Set,a=[],o=(e,t)=>{r.add(e),i.add(e);for(let s of n.get(e)||[])if(!r.has(s)){if(o(s,[...t,s]))return!0}else if(i.has(s))return a.push(`Cycle detected between slices: ${t.join(` -> `)} -> ${s}`),!0;return i.delete(e),!1};for(let e of this.sliceIds)r.has(e)||o(e,[e]);return e?{pass:a.length>0,message:()=>a.length>0?``:`Expected cycles between slices but found none.`}:{pass:a.length===0,message:()=>a.join(`
|
|
15
|
-
`)}}},y=class{program;typeChecker;constructor(e={}){let r={},i=e.tsConfigFilePath||t.findConfigFile(process.cwd(),t.sys.fileExists,`tsconfig.json`);if(i){let e=t.readConfigFile(i,t.sys.readFile),a=t.parseJsonConfigFileContent(e.config,t.sys,n.dirname(i),void 0,i,void 0,[{extension:`.vue`,isMixedContent:!0,scriptKind:t.ScriptKind.TS},{extension:`.svelte`,isMixedContent:!0,scriptKind:t.ScriptKind.TS}]);r=a.options;let o=t.createCompilerHost(r),s=o.getSourceFile,c;try{c=require(`@vue/compiler-sfc`)}catch{}o.getSourceFile=(e,n,r,i)=>{if(e.endsWith(`.vue`)){let r=t.sys.readFile(e);if(r){let i=``;if(c){let e=c.parse(r),t=e.descriptor.script,n=e.descriptor.scriptSetup;t&&(i+=t.content+`
|
|
16
|
-
`),n&&(i+=n.content+`
|
|
17
|
-
`)}else{let e=r.match(/<script[^>]*>(.*?)<\/script>/s);e&&(i=e[1])}return t.createSourceFile(e,i,n,!0,t.ScriptKind.TS)}}if(e.endsWith(`.svelte`)){let r=t.sys.readFile(e);if(r){let i=``,a=r.match(/<script[^>]*>(.*?)<\/script>/s);return a&&(i=a[1]),t.createSourceFile(e,i,n,!0,t.ScriptKind.TS)}}return s(e,n,r,i)},this.program=t.createProgram({rootNames:a.fileNames,options:r,host:o})}else throw Error(`Could not find tsconfig.json`);this.typeChecker=this.program.getTypeChecker()}getFiles(e){return new f(this.program.getSourceFiles().filter(e=>!e.isDeclarationFile&&!e.fileName.includes(`node_modules`)),this.program,e)}getClasses(e){let n=this.program.getSourceFiles().filter(e=>!e.isDeclarationFile&&!e.fileName.includes(`node_modules`)),r=[];for(let e of n){let n=e=>{t.isClassDeclaration(e)&&r.push(e),t.forEachChild(e,n)};n(e)}return new p(r,this.program,e)}layeredArchitecture(){return new m(this.program.getSourceFiles().filter(e=>!e.isDeclarationFile&&!e.fileName.includes(`node_modules`)),this.program)}getFunctions(e){let n=this.program.getSourceFiles().filter(e=>!e.isDeclarationFile&&!e.fileName.includes(`node_modules`)),r=[];for(let e of n){let n=e=>{(t.isFunctionDeclaration(e)||t.isMethodDeclaration(e)||t.isArrowFunction(e))&&r.push(e),t.forEachChild(e,n)};n(e)}return new g(r,this.program,e)}getProperties(e){let n=this.program.getSourceFiles().filter(e=>!e.isDeclarationFile&&!e.fileName.includes(`node_modules`)),r=[];for(let e of n){let n=e=>{t.isPropertyDeclaration(e)&&r.push(e),t.forEachChild(e,n)};n(e)}return new _(r,this.program,e)}getSlices(e){return new v(this.program.getSourceFiles().filter(e=>!e.isDeclarationFile&&!e.fileName.includes(`node_modules`)),this.program,e)}};function b(e){return new y({tsConfigFilePath:e})}function x(){r.expect.extend({toPass(e){let{pass:t,message:n}=e instanceof m?e.check():e;return{pass:this.isNot?!t:t,message:t?()=>`Expected rule not to pass`:()=>n()}},toResideInFolder(e,t){let{pass:n,message:r}=e.checkResideInFolder(t,this.isNot);return{pass:this.isNot?!n:n,message:r}},toHaveModifier(e,t){let{pass:n,message:r}=e.checkHaveModifier(t,this.isNot);return{pass:this.isNot?!n:n,message:r}},toExtendClass(e,t){let{pass:n,message:r}=e.checkExtendClass(t,this.isNot);return{pass:this.isNot?!n:n,message:r}},toImplementInterface(e,t){let{pass:n,message:r}=e.checkImplementInterface(t,this.isNot);return{pass:this.isNot?!n:n,message:r}},toHaveExplicitReturnType(e){let{pass:t,message:n}=e.checkHaveExplicitReturnType(this.isNot);return{pass:this.isNot?!t:t,message:n}},toBeReadonly(e){let{pass:t,message:n}=e.checkBeReadonly(this.isNot);return{pass:this.isNot?!t:t,message:n}},toDependOnFilesInFolder(e,t){let{pass:n,message:r}=e.checkDependOnFilesInFolder(t,this.isNot);return{pass:this.isNot?!n:n,message:r}},toBeFreeOfCycles(e){let{pass:t,message:n}=e.checkBeFreeOfCycles(this.isNot);return{pass:this.isNot?!t:t,message:n}},toMatchNamePattern(e,t){let{pass:n,message:r}=e.checkMatchNamePattern(t,this.isNot);return{pass:this.isNot?!n:n,message:r}}})}e.ClassLocator=p,e.FileLocator=f,e.FunctionLocator=g,e.LayerAssertionBuilder=h,e.LayeredArchitectureBuilder=m,e.Project=y,e.PropertyLocator=_,e.SliceLocator=v,e.parseProject=b,e.setupMatchers=x});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require(`typescript`),require(`node:path`),require(`vitest`)):typeof define==`function`&&define.amd?define([`exports`,`typescript`,`node:path`,`vitest`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.VitestArch={},e.typescript,e.node_path,e.vitest))})(this,function(e,t,n,r){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var i=Object.create,a=Object.defineProperty,o=Object.getOwnPropertyDescriptor,s=Object.getOwnPropertyNames,c=Object.getPrototypeOf,l=Object.prototype.hasOwnProperty,u=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var i=s(t),c=0,u=i.length,d;c<u;c++)d=i[c],!l.call(e,d)&&d!==n&&a(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=o(t,d))||r.enumerable});return e},d=(e,t,n)=>(n=e==null?{}:i(c(e)),u(t||!e||!e.__esModule?a(n,`default`,{value:e,enumerable:!0}):n,e));t=d(t),n=d(n);function f(e,n,r){let i=[];for(let a of e.classes){let e=a.name?.text||`Anonymous`,o=!1;if(a.heritageClauses){for(let e of a.heritageClauses)if(e.token===t.SyntaxKind.ExtendsKeyword){for(let r of e.types)if(t.isIdentifier(r.expression)&&r.expression.text===n){o=!0;break}}}r&&o?i.push(`Class ${e} extends ${n}, but it shouldn't.`):!r&&!o&&i.push(`Class ${e} does not extend ${n}, but it should.`)}return{pass:i.length===0,message:()=>i.join(`
|
|
2
|
+
`)}}function p(e){let n=1,r=e=>{switch(e.kind){case t.SyntaxKind.IfStatement:case t.SyntaxKind.ForStatement:case t.SyntaxKind.ForInStatement:case t.SyntaxKind.ForOfStatement:case t.SyntaxKind.WhileStatement:case t.SyntaxKind.DoStatement:case t.SyntaxKind.CaseClause:case t.SyntaxKind.CatchClause:case t.SyntaxKind.ConditionalExpression:n++;break;case t.SyntaxKind.BinaryExpression:{let r=e;(r.operatorToken.kind===t.SyntaxKind.AmpersandAmpersandToken||r.operatorToken.kind===t.SyntaxKind.BarBarToken||r.operatorToken.kind===t.SyntaxKind.QuestionQuestionToken)&&n++;break}}t.forEachChild(e,r)};return t.forEachChild(e,r),n}function m(e,t,n){let r=[];for(let i of e){let{passes:e,failMessage:a,failNotMessage:o}=n(i);t&&e?o&&r.push(o):!t&&!e&&a&&r.push(a)}return{pass:r.length===0,message:()=>r.join(`
|
|
3
|
+
`)}}function h(e,t,n,r,i,a){return m(e,a,e=>{let a=t(e),o=n(e),s=o>i,c=`${r} ${a||`Anonymous`}`;return{passes:!s,failMessage:`${c} has a total cyclomatic complexity of ${o}, which exceeds the maximum of ${i}.`,failNotMessage:`${c} has a total cyclomatic complexity of ${o}, which exceeds the maximum of ${i}, but it shouldn't.`}})}function g(e,n,r){return h(e.classes,e=>e.name?.text,e=>{let n=0,r=e=>{(t.isMethodDeclaration(e)||t.isConstructorDeclaration(e)||t.isGetAccessor(e)||t.isSetAccessor(e))&&(n+=p(e)),t.forEachChild(e,r)};return r(e),n},`Class`,n,r)}function _(e,n,r,i,a){let o;switch(i){case`export`:o=t.SyntaxKind.ExportKeyword;break;case`default`:o=t.SyntaxKind.DefaultKeyword;break;case`abstract`:o=t.SyntaxKind.AbstractKeyword;break;case`async`:o=t.SyntaxKind.AsyncKeyword;break;case`public`:o=t.SyntaxKind.PublicKeyword;break;case`private`:o=t.SyntaxKind.PrivateKeyword;break;default:throw Error(`Modifier ${i} is not fully supported.`)}return m(e,a,e=>{let a=n(e),s=t.canHaveModifiers(e)?t.getModifiers(e):void 0,c=s?s.some(e=>e.kind===o):!1,l=`${r} ${a||`Anonymous`}`;return{passes:c,failMessage:`${l} does not have modifier ${i}, but it should.`,failNotMessage:`${l} has modifier ${i}, but it shouldn't.`}})}function v(e,t,n){return _(e.classes,e=>e.name?.text,`Class`,t,n)}function y(e,r,i,a){return m(e,a,e=>{let a=r(e),o=e.getSourceFile?e.getSourceFile():e.parent?t.getSourceFileOfNode(e):void 0;if(!o)return{passes:!0,failMessage:``,failNotMessage:``};let s=n.basename(o.fileName,n.extname(o.fileName)),c=a===s,l=`${i} ${a||`Anonymous`}`;return{passes:c,failMessage:`${l} does not have a name matching its filename ${s}, but it should.`,failNotMessage:`${l} has a name matching its filename ${s}, but it shouldn't.`}})}function b(e,t){return y(e.classes,e=>e.name?.text,`Class`,t)}function x(e,n,r){let i=[];for(let a of e.classes){let e=a.name?.text||`Anonymous`,o=!1;if(a.heritageClauses){for(let e of a.heritageClauses)if(e.token===t.SyntaxKind.ImplementsKeyword){for(let r of e.types)if(t.isIdentifier(r.expression)&&r.expression.text===n){o=!0;break}}}r&&o?i.push(`Class ${e} implements ${n}, but it shouldn't.`):!r&&!o&&i.push(`Class ${e} does not implement ${n}, but it should.`)}return{pass:i.length===0,message:()=>i.join(`
|
|
4
|
+
`)}}function S(e,t,n,r,i){let a=typeof r==`string`?new RegExp(r):r;return m(e,i,e=>{let i=t(e),o=i?a.test(i):!1,s=`${n} ${i||`Anonymous`}`;return{passes:o,failMessage:`${s} does not match pattern ${r}, but it should.`,failNotMessage:`${s} matches pattern ${r}, but it shouldn't.`}})}function C(e,t,n){return S(e.classes,e=>e.name?.text,`Class`,t,n)}function w(e,t,n){let r=[];for(let i of e.classes){let e=i.name?.text||`Anonymous Class`,a=i.getSourceFile(),o=a.fileName.includes(`/${t}/`)||a.fileName.includes(`\\${t}\\`);n&&o?r.push(`Class ${e} resides in ${t}, but it shouldn't.`):!n&&!o&&r.push(`Class ${e} does not reside in ${t}, but it should.`)}return{pass:r.length===0,message:()=>r.join(`
|
|
5
|
+
`)}}function T(e,n,r){let i=e;if(r?.inFolder&&(i=i.filter(e=>{let n=e.getSourceFile?e.getSourceFile():e.parent?t.getSourceFileOfNode(e):void 0;return n?n.fileName.includes(`/${r.inFolder}/`)||n.fileName.includes(`\\${r.inFolder}\\`):!1})),r?.matchNamePattern){let e=typeof r.matchNamePattern==`string`?new RegExp(r.matchNamePattern):r.matchNamePattern;i=i.filter(t=>{let n=t.name?.text;return n&&e.test(n)})}if(r?.withDecorator&&(i=i.filter(e=>{let n=t.canHaveDecorators(e)?t.getDecorators(e):void 0,i=!1;if(n)for(let e of n){let n=e.expression,a=``;t.isIdentifier(n)?a=n.text:t.isCallExpression(n)&&t.isIdentifier(n.expression)&&(a=n.expression.text),a===r.withDecorator&&(i=!0)}return i})),r?.extending&&(i=i.filter(e=>{if(e.heritageClauses){for(let n of e.heritageClauses)if(n.token===t.SyntaxKind.ExtendsKeyword){for(let e of n.types)if(t.isIdentifier(e.expression)&&e.expression.text===r.extending)return!0}}return!1})),r?.implementing&&(i=i.filter(e=>{if(e.heritageClauses){for(let n of e.heritageClauses)if(n.token===t.SyntaxKind.ImplementsKeyword){for(let e of n.types)if(t.isIdentifier(e.expression)&&e.expression.text===r.implementing)return!0}}return!1})),r?.havingModifier){let e;switch(r.havingModifier){case`export`:e=t.SyntaxKind.ExportKeyword;break;case`default`:e=t.SyntaxKind.DefaultKeyword;break;case`abstract`:e=t.SyntaxKind.AbstractKeyword;break;default:throw Error(`Modifier ${r.havingModifier} is not fully supported.`)}i=i.filter(n=>(t.canHaveModifiers(n)?t.getModifiers(n):void 0)?.some(t=>t.kind===e))}return{type:`ClassLocator`,classes:i,program:n}}function E(e,n){let r=[],i=n.getCompilerOptions(),a=n=>{if(t.isImportDeclaration(n)){let a=n.moduleSpecifier.text,o=t.resolveModuleName(a,e.fileName,i,t.sys);o.resolvedModule?.resolvedFileName&&(o.resolvedModule.isExternalLibraryImport||r.push(o.resolvedModule.resolvedFileName))}else if(t.isExportDeclaration(n)&&n.moduleSpecifier){let a=n.moduleSpecifier.text,o=t.resolveModuleName(a,e.fileName,i,t.sys);o.resolvedModule?.resolvedFileName&&(o.resolvedModule.isExternalLibraryImport||r.push(o.resolvedModule.resolvedFileName))}t.forEachChild(n,a)};return a(e),r}function D(e,t,n){let r=[];for(let i of e.files){let a=E(i,e.program).some(e=>e.includes(`/${t}/`)||e.includes(`\\${t}\\`));n&&a?r.push(`File ${i.fileName} depends on files in ${t}, but it shouldn't.`):!n&&!a&&r.push(`File ${i.fileName} does not depend on files in ${t}, but it should.`)}return{pass:r.length===0,message:()=>r.join(`
|
|
6
|
+
`)}}function O(e,t){let n=[],r=new Set(e.files.map(e=>e.fileName)),i=new Map;for(let t of e.files){let n=t.fileName,a=E(t,e.program).filter(e=>r.has(e));i.set(n,a)}let a=new Set,o=new Set,s=[],c=(e,t)=>{if(o.has(e)){let n=t.indexOf(e),r=[...t.slice(n),e].join(`->`);return s.some(e=>e.join(`->`)===r)||s.push([...t.slice(n),e]),!0}if(a.has(e))return!1;a.add(e),o.add(e),t.push(e);let n=i.get(e)||[];for(let e of n)c(e,t);return o.delete(e),t.pop(),!1};for(let e of i.keys())a.has(e)||c(e,[]);if(t&&s.length===0)n.push(`Expected cyclic dependencies, but found none.`);else if(!t&&s.length>0)for(let e of s)n.push(`Cycle detected: ${e.join(` -> `)}`);return{pass:n.length===0,message:()=>n.join(`
|
|
7
|
+
`)}}function k(e,n,r){return h(e.files,e=>e.fileName,e=>{let n=0,r=e=>{(t.isFunctionDeclaration(e)||t.isMethodDeclaration(e)||t.isArrowFunction(e)||t.isFunctionExpression(e))&&(n+=p(e)),t.forEachChild(e,r)};return r(e),n},`File`,n,r)}function A(e,n,r){let i=[];for(let a of e.files){let e=0;t.forEachChild(a,n=>{t.isFunctionDeclaration(n)&&(t.canHaveModifiers(n)?t.getModifiers(n):void 0)?.some(e=>e.kind===t.SyntaxKind.ExportKeyword)&&e++});let o=e>n;r&&o?i.push(`File ${a.fileName} has ${e} exported functions, which exceeds the maximum of ${n}, but it shouldn't.`):!r&&o&&i.push(`File ${a.fileName} has ${e} exported functions, which exceeds the maximum of ${n}.`)}return{pass:r?i.length>0:i.length===0,message:()=>i.join(`
|
|
8
|
+
`)||(r?`Expected some files to exceed maximum exported functions, but none did.`:``)}}function j(e){let n=0,r=0,i=new Set,a=new Set,o=1,s=e.getSourceFile();if(s){let t=s.getLineAndCharacterOfPosition(e.getStart());o=s.getLineAndCharacterOfPosition(e.getEnd()).line-t.line+1}let c=e=>{t.isBinaryExpression(e)||t.isPrefixUnaryExpression(e)||t.isPostfixUnaryExpression(e)?(n++,i.add(e.kind)):(t.isIdentifier(e)||t.isLiteralExpression(e))&&(r++,a.add(e.getText(s))),t.forEachChild(e,c)};c(e);let l=n+r,u=i.size+a.size,d=u===0?0:l*Math.log2(u),f=p(e);return Math.max(0,(171-5.2*Math.log(d||1)-.23*f-16.2*Math.log(o))*100/171)}function M(e,t,n,r,i,a){return m(e,a,e=>{let a=t(e),o=n(e),s=o<i,c=`${r} ${a||`Anonymous`}`;return{passes:!s,failMessage:`${c} has a maintainability index of ${o.toFixed(2)}, which falls below the minimum of ${i}.`,failNotMessage:`${c} has a maintainability index of ${o.toFixed(2)}, which falls below the minimum of ${i}, but it shouldn't.`}})}function N(e,t,n){return M(e.files,e=>e.fileName,j,`File`,t,n)}function P(e,t,n){return S(e.files,e=>e.fileName,`File`,t,n)}function F(e,t,n){let r=e;if(n?.inFolder&&(r=r.filter(e=>e.fileName.includes(`/${n.inFolder}/`)||e.fileName.includes(`\\${n.inFolder}\\`))),n?.matchNamePattern){let e=typeof n.matchNamePattern==`string`?new RegExp(n.matchNamePattern):n.matchNamePattern;r=r.filter(t=>e.test(t.fileName))}return{type:`FileLocator`,files:r,program:t}}function I(e,n){let r=[];for(let i of e.functions){let e=i.name&&t.isIdentifier(i.name)?i.name.text:`Anonymous Function`,a=!!i.type;n&&a?r.push(`Function ${e} has an explicit return type, but it shouldn't.`):!n&&!a&&r.push(`Function ${e} does not have an explicit return type, but it should.`)}return{pass:r.length===0,message:()=>r.join(`
|
|
9
|
+
`)}}function L(e,n,r){return h(e.functions,e=>e.name&&t.isIdentifier(e.name)?e.name.text:void 0,p,`Function`,n,r)}function R(e,n,r){return M(e.functions,e=>e.name&&t.isIdentifier(e.name)?e.name.text:void 0,j,`Function`,n,r)}function z(e,n,r){return _(e.functions,e=>e.name&&t.isIdentifier(e.name)?e.name.text:void 0,`Function`,n,r)}function B(e,n){return y(e.functions,e=>e.name&&t.isIdentifier(e.name)?e.name.text:void 0,`Function`,n)}function V(e,n,r){return S(e.functions,e=>e.name&&t.isIdentifier(e.name)?e.name.text:void 0,`Function`,n,r)}function H(e,n,r){let i=e;if(r?.inFolder&&(i=i.filter(e=>{let n=e.getSourceFile?e.getSourceFile():e.parent?t.getSourceFileOfNode(e):void 0;return n?n.fileName.includes(`/${r.inFolder}/`)||n.fileName.includes(`\\${r.inFolder}\\`):!1})),r?.matchNamePattern){let e=typeof r.matchNamePattern==`string`?new RegExp(r.matchNamePattern):r.matchNamePattern;i=i.filter(n=>n.name&&t.isIdentifier(n.name)&&e.test(n.name.text))}return r?.isTopLevel&&(i=i.filter(e=>t.isSourceFile(e.parent))),{type:`FunctionLocator`,functions:i,program:n}}function U(e){let t=[];for(let n of e.assertions)t.push(...n(e.files));return{pass:t.length===0,message:()=>t.join(`
|
|
10
|
+
`)}}function W(e,t){return{type:`LayeredArchitecture`,files:e,layers:new Map,assertions:[],program:t}}function G(e,t,n){return e.layers.set(t,n),e}function K(e,n){let r=[],i=n.getCompilerOptions(),a=n=>{if(t.isImportDeclaration(n)){let a=n.moduleSpecifier.text,o=t.resolveModuleName(a,e.fileName,i,t.sys);o.resolvedModule?.resolvedFileName&&!o.resolvedModule.isExternalLibraryImport&&r.push(o.resolvedModule.resolvedFileName)}else if(t.isExportDeclaration(n)&&n.moduleSpecifier){let a=n.moduleSpecifier.text,o=t.resolveModuleName(a,e.fileName,i,t.sys);o.resolvedModule?.resolvedFileName&&!o.resolvedModule.isExternalLibraryImport&&r.push(o.resolvedModule.resolvedFileName)}t.forEachChild(n,a)};return a(e),r}function q(e,t){if(!e.layers.has(t))throw Error(`Layer ${t} is not defined`);return e.assertions.push(n=>{let r=[],i=e.layers.get(t);for(let a of n){let n=a.fileName;!n.includes(`/${i}/`)&&!n.includes(`\\${i}\\`)&&K(a,e.program).some(e=>e.includes(`/${i}/`)||e.includes(`\\${i}\\`))&&r.push(`File ${n} accesses layer ${t} but it shouldn't.`)}return r}),e}function J(e,t,n){if(!e.layers.has(t))throw Error(`Layer ${t} is not defined`);return e.assertions.push(r=>{let i=[],a=e.layers.get(t),o=n.map(t=>e.layers.get(t));for(let s of r){let r=s.fileName,c=o.some(e=>r.includes(`/${e}/`)||r.includes(`\\${e}\\`));!r.includes(`/${a}/`)&&!r.includes(`\\${a}\\`)&&!c&&K(s,e.program).some(e=>e.includes(`/${a}/`)||e.includes(`\\${a}\\`))&&i.push(`File ${r} accesses layer ${t} but only ${n.join(`, `)} are allowed.`)}return i}),e}function Y(e,n,r){let i=e;if(r?.inFolder&&(i=i.filter(e=>{let n=e.getSourceFile?e.getSourceFile():e.parent?t.getSourceFileOfNode(e):void 0;return n?n.fileName.includes(`/${r.inFolder}/`)||n.fileName.includes(`\\${r.inFolder}\\`):!1})),r?.matchNamePattern){let e=typeof r.matchNamePattern==`string`?new RegExp(r.matchNamePattern):r.matchNamePattern;i=i.filter(n=>t.isIdentifier(n.name)&&e.test(n.name.text))}return{type:`PropertyLocator`,properties:i,program:n}}function X(e,t,n){let r=n.replace(/[.+?^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`([^/\\\\]+)`),i=new RegExp(r),a=new Set,o=new Map;for(let t of e){let e=t.fileName.match(i);if(e?.[1]){let n=e[1];a.add(n),o.has(n)||o.set(n,[]),o.get(n)?.push(t)}}return{type:`SliceLocator`,slicePattern:i,sliceIds:a,sliceFiles:o,program:t}}function ee(e={}){let r={},i=e.tsConfigFilePath||t.findConfigFile(process.cwd(),t.sys.fileExists,`tsconfig.json`),a;if(i){let e=t.readConfigFile(i,t.sys.readFile),o=t.parseJsonConfigFileContent(e.config,t.sys,(0,n.dirname)(i),void 0,i,void 0,[{extension:`.vue`,isMixedContent:!0,scriptKind:t.ScriptKind.TS},{extension:`.svelte`,isMixedContent:!0,scriptKind:t.ScriptKind.TS}]);r=o.options;let s=t.createCompilerHost(r),c=s.getSourceFile,l;try{l=require(`@vue/compiler-sfc`)}catch{}s.getSourceFile=(e,n,r,i)=>{if(e.endsWith(`.vue`)){let r=t.sys.readFile(e);if(r){let i=``;if(l){let e=l.parse(r),t=e.descriptor.script,n=e.descriptor.scriptSetup;t&&(i+=`${t.content}\n`),n&&(i+=`${n.content}\n`)}else{let e=r.match(/<script[^>]*>(.*?)<\/script>/s);e&&(i=e[1])}return t.createSourceFile(e,i,n,!0,t.ScriptKind.TS)}}if(e.endsWith(`.svelte`)){let r=t.sys.readFile(e);if(r){let i=``,a=r.match(/<script[^>]*>(.*?)<\/script>/s);return a&&(i=a[1]),t.createSourceFile(e,i,n,!0,t.ScriptKind.TS)}}return c(e,n,r,i)},a=t.createProgram({rootNames:o.fileNames,options:r,host:s}),a.getTypeChecker()}else throw Error(`Could not find tsconfig.json`);let o=()=>a.getSourceFiles().filter(e=>!e.isDeclarationFile&&!e.fileName.includes(`node_modules`));return{getFiles:e=>F(o(),a,e),getClasses:e=>{let n=[];for(let e of o()){let r=e=>{t.isClassDeclaration(e)&&n.push(e),t.forEachChild(e,r)};r(e)}return T(n,a,e)},layeredArchitecture:()=>{let e=W(o(),a),t={layer:(n,r)=>(e=G(e,n,r),t),whereLayer:n=>({shouldNotBeAccessedByAnyLayer:()=>(e=q(e,n),t),shouldOnlyBeAccessedBy:(...r)=>(e=J(e,n,r),t)}),check:()=>U(e),get data(){return e}};return t},getFunctions:e=>{let n=[];for(let e of o()){let r=e=>{(t.isFunctionDeclaration(e)||t.isMethodDeclaration(e)||t.isArrowFunction(e))&&n.push(e),t.forEachChild(e,r)};r(e)}return H(n,a,e)},getProperties:e=>{let n=[];for(let e of o()){let r=e=>{t.isPropertyDeclaration(e)&&n.push(e),t.forEachChild(e,r)};r(e)}return Y(n,a,e)},getSlices:e=>X(o(),a,e)}}function Z(e,n){let r=[];for(let i of e.properties){let e=t.isIdentifier(i.name)?i.name.text:`Anonymous Property`,a=(t.canHaveModifiers(i)?t.getModifiers(i):void 0)?.some(e=>e.kind===t.SyntaxKind.ReadonlyKeyword);n&&a?r.push(`Property ${e} is readonly, but it shouldn't be.`):!n&&!a&&r.push(`Property ${e} is not readonly, but it should be.`)}return{pass:r.length===0,message:()=>r.join(`
|
|
11
|
+
`)}}function Q(e,n){let r=new Map;for(let t of e.sliceIds)r.set(t,new Set);for(let[n,i]of e.sliceFiles.entries())for(let a of i)t.forEachChild(a,i=>{if(t.isImportDeclaration(i)&&i.moduleSpecifier&&t.isStringLiteral(i.moduleSpecifier)){let o=i.moduleSpecifier.text,s=t.resolveModuleName(o,a.fileName,e.program.getCompilerOptions(),t.sys);if(s.resolvedModule?.resolvedFileName){let t=s.resolvedModule.resolvedFileName.match(e.slicePattern);if(t?.[1]){let i=t[1];i!==n&&e.sliceIds.has(i)&&r.get(n)?.add(i)}}}});let i=new Set,a=new Set,o=[],s=(e,t)=>{i.add(e),a.add(e);for(let n of r.get(e)||[])if(!i.has(n)){if(s(n,[...t,n]))return!0}else if(a.has(n))return o.push(`Cycle detected between slices: ${t.join(` -> `)} -> ${n}`),!0;return a.delete(e),!1};for(let t of e.sliceIds)i.has(t)||s(t,[t]);return n?{pass:o.length>0,message:()=>o.length>0?``:`Expected cycles between slices but found none.`}:{pass:o.length===0,message:()=>o.join(`
|
|
12
|
+
`)}}function $(e,n,r){let i=[],a=new Map,o=new Map;for(let t of e.sliceIds)a.set(t,new Set),o.set(t,new Set);for(let[n,r]of e.sliceFiles.entries())for(let i of r)t.forEachChild(i,r=>{if(t.isImportDeclaration(r)&&r.moduleSpecifier&&t.isStringLiteral(r.moduleSpecifier)){let s=r.moduleSpecifier.text,c=t.resolveModuleName(s,i.fileName,e.program.getCompilerOptions(),t.sys);if(c.resolvedModule?.resolvedFileName){let t=c.resolvedModule.resolvedFileName.match(e.slicePattern);if(t?.[1]){let r=t[1];r!==n&&e.sliceIds.has(r)&&(a.get(n)?.add(r),o.get(r)?.add(n))}}}});for(let s of e.sliceIds){let c=a.get(s)?.size,l=o.get(s)?.size,u=e.sliceFiles.get(s),d=0,f=0;for(let e of u){let n=e=>{t.isClassDeclaration(e)?(f++,(t.canHaveModifiers(e)?t.getModifiers(e):void 0)?.some(e=>e.kind===t.SyntaxKind.AbstractKeyword)&&d++):t.isInterfaceDeclaration(e)&&(f++,d++),t.forEachChild(e,n)};n(e)}let p=c+l===0?0:c/(l+c),m=f===0?0:d/f,h=Math.abs(m+p-1),g=h>n;r&&g?i.push(`Slice ${s} has a Distance from the Main Sequence of ${h.toFixed(2)}, which exceeds the maximum of ${n}, but it shouldn't.`):!r&&g&&i.push(`Slice ${s} has a Distance from the Main Sequence of ${h.toFixed(2)}, which exceeds the maximum of ${n}.`)}return{pass:r?i.length>0:i.length===0,message:()=>i.join(`
|
|
13
|
+
`)||(r?`Expected some slices to exceed maximum distance from main sequence, but none did.`:``)}}function te(){r.expect.extend({toPass(e){let t;t=e?.data&&e.data.type===`LayeredArchitecture`?U(e.data):e;let{pass:n,message:r}=t;return{pass:this.isNot?!n:n,message:n?()=>`Expected rule not to pass`:()=>r()}},toResideInFolder(e,t){let n;if(e.type===`ClassLocator`)n=w(e,t,this.isNot);else throw Error(`toResideInFolder matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toHaveModifier(e,t){let n;if(e.type===`ClassLocator`)n=v(e,t,this.isNot);else if(e.type===`FunctionLocator`)n=z(e,t,this.isNot);else throw Error(`toHaveModifier matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toExtendClass(e,t){let n;if(e.type===`ClassLocator`)n=f(e,t,this.isNot);else throw Error(`toExtendClass matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toImplementInterface(e,t){let n;if(e.type===`ClassLocator`)n=x(e,t,this.isNot);else throw Error(`toImplementInterface matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toHaveExplicitReturnType(e){let t;if(e.type===`FunctionLocator`)t=I(e,this.isNot);else throw Error(`toHaveExplicitReturnType matcher does not support ${e.type}`);return{pass:this.isNot?!t.pass:t.pass,message:t.message}},toBeReadonly(e){let t;if(e.type===`PropertyLocator`)t=Z(e,this.isNot);else throw Error(`toBeReadonly matcher does not support ${e.type}`);return{pass:this.isNot?!t.pass:t.pass,message:t.message}},toDependOnFilesInFolder(e,t){let n;if(e.type===`FileLocator`)n=D(e,t,this.isNot);else throw Error(`toDependOnFilesInFolder matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toBeFreeOfCycles(e){let t;if(e.type===`FileLocator`)t=O(e,this.isNot);else if(e.type===`SliceLocator`)t=Q(e,this.isNot);else throw Error(`toBeFreeOfCycles matcher does not support ${e.type}`);return{pass:this.isNot?!t.pass:t.pass,message:t.message}},toMatchNamePattern(e,t){let n;if(e.type===`FileLocator`)n=P(e,t,this.isNot);else if(e.type===`ClassLocator`)n=C(e,t,this.isNot);else if(e.type===`FunctionLocator`)n=V(e,t,this.isNot);else throw Error(`toMatchNamePattern matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toHaveMaxCyclomaticComplexity(e,t){let n;if(e.type===`FileLocator`)n=k(e,t,this.isNot);else if(e.type===`ClassLocator`)n=g(e,t,this.isNot);else if(e.type===`FunctionLocator`)n=L(e,t,this.isNot);else throw Error(`toHaveMaxCyclomaticComplexity matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toHaveMinMaintainabilityIndex(e,t){let n;if(e.type===`FileLocator`)n=N(e,t,this.isNot);else if(e.type===`FunctionLocator`)n=R(e,t,this.isNot);else throw Error(`toHaveMinMaintainabilityIndex matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toHaveMaxDistanceFromMainSequence(e,t){let n;if(e.type===`SliceLocator`)n=$(e,t,this.isNot);else throw Error(`toHaveMaxDistanceFromMainSequence matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}},toHaveNameMatchingFileName(e){let t;if(e.type===`FunctionLocator`)t=B(e,this.isNot);else if(e.type===`ClassLocator`)t=b(e,this.isNot);else throw Error(`toHaveNameMatchingFileName matcher does not support ${e.type}`);return{pass:this.isNot?!t.pass:t.pass,message:t.message}},toHaveMaxExportedFunctions(e,t){let n;if(e.type===`FileLocator`)n=A(e,t,this.isNot);else throw Error(`toHaveMaxExportedFunctions matcher does not support ${e.type}`);return{pass:this.isNot?!n.pass:n.pass,message:n.message}}})}e.checkDependOnFilesInFolder=D,e.checkLayeredArchitecture=U,e.classCheckExtendClass=f,e.classCheckHaveMaxCyclomaticComplexity=g,e.classCheckHaveModifier=v,e.classCheckHaveNameMatchingFileName=b,e.classCheckImplementInterface=x,e.classCheckMatchNamePattern=C,e.classCheckResideInFolder=w,e.createLayeredArchitecture=W,e.fileCheckBeFreeOfCycles=O,e.fileCheckHaveMaxCyclomaticComplexity=k,e.fileCheckHaveMaxExportedFunctions=A,e.fileCheckHaveMinMaintainabilityIndex=N,e.fileCheckMatchNamePattern=P,e.functionCheckHaveExplicitReturnType=I,e.functionCheckHaveMaxCyclomaticComplexity=L,e.functionCheckHaveMinMaintainabilityIndex=R,e.functionCheckHaveModifier=z,e.functionCheckHaveNameMatchingFileName=B,e.functionCheckMatchNamePattern=V,e.layer=G,e.layerShouldNotBeAccessedByAnyLayer=q,e.layerShouldOnlyBeAccessedBy=J,e.locateClasses=T,e.locateFiles=F,e.locateFunctions=H,e.locateProperties=Y,e.locateSlices=X,e.parseProject=ee,e.propertyCheckBeReadonly=Z,e.setupMatchers=te,e.sliceCheckBeFreeOfCycles=Q,e.sliceCheckHaveMaxDistanceFromMainSequence=$});
|
|
18
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/core/FileLocator.ts","../src/core/ClassLocator.ts","../src/core/LayerLocator.ts","../src/core/FunctionLocator.ts","../src/core/PropertyLocator.ts","../src/core/SliceLocator.ts","../src/core/Project.ts","../src/matchers/index.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface FileQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n}\n\nexport class FileLocator {\n public readonly files: ts.SourceFile[];\n\n constructor(sourceFiles: ts.SourceFile[], private program: ts.Program, options?: FileQueryOptions) {\n let filtered = sourceFiles;\n\n if (options?.inFolder) {\n filtered = filtered.filter((file) => file.fileName.includes(`/${options.inFolder}/`) || file.fileName.includes(`\\\\${options.inFolder}\\\\`));\n }\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((file) => regex.test(file.fileName));\n }\n\n this.files = filtered;\n }\n\n private getFileDependencies(sourceFile: ts.SourceFile): string[] {\n const dependencies: string[] = [];\n const compilerOptions = this.program.getCompilerOptions();\n\n const visit = (node: ts.Node) => {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys\n );\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName) {\n if (!resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n } else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys\n );\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName) {\n if (!resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return dependencies;\n }\n\n checkDependOnFilesInFolder(targetFolder: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n\n for (const file of this.files) {\n const dependencies = this.getFileDependencies(file);\n \n const dependsOnTarget = dependencies.some((depPath) => depPath.includes(`/${targetFolder}/`) || depPath.includes(`\\\\${targetFolder}\\\\`));\n\n if (isNot && dependsOnTarget) {\n violations.push(`File ${file.fileName} depends on files in ${targetFolder}, but it shouldn't.`);\n } else if (!isNot && !dependsOnTarget) {\n violations.push(`File ${file.fileName} does not depend on files in ${targetFolder}, but it should.`);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkBeFreeOfCycles(isNot: boolean): RuleResult {\n const violations: string[] = [];\n const targetedFilePaths = new Set<string>(this.files.map(f => f.fileName));\n const graph = new Map<string, string[]>();\n\n for (const file of this.files) {\n const filePath = file.fileName;\n const dependencies = this.getFileDependencies(file)\n .filter((p) => targetedFilePaths.has(p));\n \n graph.set(filePath, dependencies);\n }\n\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const cycles: string[][] = [];\n\n const isCyclicUtil = (node: string, path: string[]) => {\n if (recStack.has(node)) {\n const cycleStartIndex = path.indexOf(node);\n const cycleStr = [...path.slice(cycleStartIndex), node].join('->');\n if (!cycles.some(c => c.join('->') === cycleStr)) {\n cycles.push([...path.slice(cycleStartIndex), node]);\n }\n return true;\n }\n\n if (visited.has(node)) return false;\n\n visited.add(node);\n recStack.add(node);\n path.push(node);\n\n const neighbors = graph.get(node) || [];\n for (const neighbor of neighbors) {\n isCyclicUtil(neighbor, path);\n }\n\n recStack.delete(node);\n path.pop();\n return false;\n };\n\n for (const node of graph.keys()) {\n if (!visited.has(node)) {\n isCyclicUtil(node, []);\n }\n }\n\n if (isNot && cycles.length === 0) {\n violations.push('Expected cyclic dependencies, but found none.');\n } else if (!isNot && cycles.length > 0) {\n for (const cycle of cycles) {\n violations.push(`Cycle detected: ${cycle.join(' -> ')}`);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkMatchNamePattern(pattern: string | RegExp, isNot: boolean): RuleResult {\n const violations: string[] = [];\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const file of this.files) {\n const matches = regex.test(file.fileName);\n\n if (isNot && matches) {\n violations.push(`File ${file.fileName} matches pattern ${pattern}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`File ${file.fileName} does not match pattern ${pattern}, but it should.`);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface ClassQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n withDecorator?: string;\n extending?: string;\n implementing?: string;\n havingModifier?: string;\n}\n\nexport class ClassLocator {\n public readonly classes: ts.ClassDeclaration[];\n\n constructor(classes: ts.ClassDeclaration[], private program: ts.Program, options?: ClassQueryOptions) {\n let filtered = classes;\n\n if (options?.inFolder) {\n filtered = filtered.filter((c) => {\n const sourceFile = c.getSourceFile();\n return sourceFile.fileName.includes(`/${options.inFolder}/`) || sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`);\n });\n }\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((c) => {\n const name = c.name?.text;\n return name && regex.test(name);\n });\n }\n if (options?.withDecorator) {\n filtered = filtered.filter((c) => {\n const decorators = ts.canHaveDecorators(c) ? ts.getDecorators(c) : undefined;\n let hasDecorator = false;\n if (decorators) {\n for (const dec of decorators) {\n const exp = dec.expression;\n let name = '';\n if (ts.isIdentifier(exp)) {\n name = exp.text;\n } else if (ts.isCallExpression(exp) && ts.isIdentifier(exp.expression)) {\n name = exp.expression.text;\n }\n if (name === options.withDecorator) {\n hasDecorator = true;\n }\n }\n }\n return hasDecorator;\n });\n }\n if (options?.extending) {\n filtered = filtered.filter((c) => {\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === options.extending) {\n return true;\n }\n }\n }\n }\n }\n return false;\n });\n }\n if (options?.implementing) {\n filtered = filtered.filter((c) => {\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ImplementsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === options.implementing) {\n return true;\n }\n }\n }\n }\n }\n return false;\n });\n }\n if (options?.havingModifier) {\n let targetKind: ts.SyntaxKind;\n switch (options.havingModifier) {\n case 'export': targetKind = ts.SyntaxKind.ExportKeyword; break;\n case 'default': targetKind = ts.SyntaxKind.DefaultKeyword; break;\n case 'abstract': targetKind = ts.SyntaxKind.AbstractKeyword; break;\n default:\n throw new Error(`Modifier ${options.havingModifier} is not fully supported.`);\n }\n filtered = filtered.filter((c) => {\n const modifiers = ts.canHaveModifiers(c) ? ts.getModifiers(c) : undefined;\n return modifiers && modifiers.some((m: ts.Modifier) => m.kind === targetKind);\n });\n }\n\n this.classes = filtered;\n }\n\n checkResideInFolder(targetFolder: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const c of this.classes) {\n const className = c.name?.text || 'Anonymous Class';\n const sourceFile = c.getSourceFile();\n const inTargetFolder = sourceFile.fileName.includes(`/${targetFolder}/`) || sourceFile.fileName.includes(`\\\\${targetFolder}\\\\`);\n\n if (isNot && inTargetFolder) {\n violations.push(`Class ${className} resides in ${targetFolder}, but it shouldn't.`);\n } else if (!isNot && !inTargetFolder) {\n violations.push(`Class ${className} does not reside in ${targetFolder}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkMatchNamePattern(pattern: string | RegExp, isNot: boolean): RuleResult {\n const violations: string[] = [];\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const c of this.classes) {\n const name = c.name?.text;\n const matches = name && regex.test(name);\n if (isNot && matches) {\n violations.push(`Class ${name} matches pattern ${pattern}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name || 'Anonymous'} does not match pattern ${pattern}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkExtendClass(className: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const c of this.classes) {\n const name = c.name?.text || 'Anonymous';\n let matches = false;\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === className) {\n matches = true;\n break;\n }\n }\n }\n }\n }\n if (isNot && matches) {\n violations.push(`Class ${name} extends ${className}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name} does not extend ${className}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkImplementInterface(interfaceName: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const c of this.classes) {\n const name = c.name?.text || 'Anonymous';\n let matches = false;\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ImplementsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === interfaceName) {\n matches = true;\n break;\n }\n }\n }\n }\n }\n if (isNot && matches) {\n violations.push(`Class ${name} implements ${interfaceName}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name} does not implement ${interfaceName}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkHaveModifier(modifierStr: string, isNot: boolean): RuleResult {\n let targetKind: ts.SyntaxKind;\n switch (modifierStr) {\n case 'export': targetKind = ts.SyntaxKind.ExportKeyword; break;\n case 'default': targetKind = ts.SyntaxKind.DefaultKeyword; break;\n case 'abstract': targetKind = ts.SyntaxKind.AbstractKeyword; break;\n default:\n throw new Error(`Modifier ${modifierStr} is not fully supported.`);\n }\n\n const violations: string[] = [];\n for (const c of this.classes) {\n const name = c.name?.text || 'Anonymous';\n const modifiers = ts.canHaveModifiers(c) ? ts.getModifiers(c) : undefined;\n const matches = modifiers && modifiers.some((m: ts.Modifier) => m.kind === targetKind);\n\n if (isNot && matches) {\n violations.push(`Class ${name} has modifier ${modifierStr}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name} does not have modifier ${modifierStr}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport class LayeredArchitectureBuilder {\n private files: ts.SourceFile[];\n private layers = new Map<string, string>();\n private assertions: Array<(files: ts.SourceFile[]) => string[]> = [];\n\n constructor(files: ts.SourceFile[], public program: ts.Program) {\n this.files = files;\n }\n\n layer(name: string, folderPattern: string): this {\n this.layers.set(name, folderPattern);\n return this;\n }\n\n whereLayer(name: string): LayerAssertionBuilder {\n if (!this.layers.has(name)) {\n throw new Error(`Layer ${name} is not defined`);\n }\n return new LayerAssertionBuilder(this, name);\n }\n\n addAssertion(assertion: (files: ts.SourceFile[]) => string[]) {\n this.assertions.push(assertion);\n }\n\n getFiles(): ts.SourceFile[] {\n return this.files;\n }\n\n getLayerPattern(name: string): string {\n return this.layers.get(name)!;\n }\n\n getFileDependencies(sourceFile: ts.SourceFile): string[] {\n const dependencies: string[] = [];\n const compilerOptions = this.program.getCompilerOptions();\n\n const visit = (node: ts.Node) => {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(moduleSpecifier, sourceFile.fileName, compilerOptions, ts.sys);\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName && !resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n } else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(moduleSpecifier, sourceFile.fileName, compilerOptions, ts.sys);\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName && !resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return dependencies;\n }\n\n check(): RuleResult {\n const violations: string[] = [];\n for (const assertion of this.assertions) {\n violations.push(...assertion(this.files));\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n')\n };\n }\n}\n\nexport class LayerAssertionBuilder {\n constructor(private parent: LayeredArchitectureBuilder, private targetLayer: string) {}\n\n shouldNotBeAccessedByAnyLayer(): LayeredArchitectureBuilder {\n this.parent.addAssertion((files) => {\n const violations: string[] = [];\n const targetPattern = this.parent.getLayerPattern(this.targetLayer);\n\n for (const file of files) {\n const filePath = file.fileName;\n if (!filePath.includes(`/${targetPattern}/`) && !filePath.includes(`\\\\${targetPattern}\\\\`)) {\n const dependencies = this.parent.getFileDependencies(file);\n const importsTarget = dependencies.some(dep => dep.includes(`/${targetPattern}/`) || dep.includes(`\\\\${targetPattern}\\\\`));\n if (importsTarget) {\n violations.push(`File ${filePath} accesses layer ${this.targetLayer} but it shouldn't.`);\n }\n }\n }\n return violations;\n });\n return this.parent;\n }\n\n shouldOnlyBeAccessedBy(...allowedLayers: string[]): LayeredArchitectureBuilder {\n this.parent.addAssertion((files) => {\n const violations: string[] = [];\n const targetPattern = this.parent.getLayerPattern(this.targetLayer);\n const allowedPatterns = allowedLayers.map(l => this.parent.getLayerPattern(l));\n\n for (const file of files) {\n const filePath = file.fileName;\n const isInAllowedLayer = allowedPatterns.some(p => filePath.includes(`/${p}/`) || filePath.includes(`\\\\${p}\\\\`));\n \n if (!filePath.includes(`/${targetPattern}/`) && !filePath.includes(`\\\\${targetPattern}\\\\`) && !isInAllowedLayer) {\n const dependencies = this.parent.getFileDependencies(file);\n const importsTarget = dependencies.some(dep => dep.includes(`/${targetPattern}/`) || dep.includes(`\\\\${targetPattern}\\\\`));\n if (importsTarget) {\n violations.push(`File ${filePath} accesses layer ${this.targetLayer} but only ${allowedLayers.join(', ')} are allowed.`);\n }\n }\n }\n return violations;\n });\n return this.parent;\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface FunctionQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n isTopLevel?: boolean;\n}\n\nexport class FunctionLocator {\n public readonly functions: ts.FunctionLikeDeclaration[];\n\n constructor(functions: ts.FunctionLikeDeclaration[], private program: ts.Program, options?: FunctionQueryOptions) {\n let filtered = functions;\n\n if (options?.inFolder) {\n filtered = filtered.filter((f) => {\n const sourceFile = f.getSourceFile();\n return sourceFile.fileName.includes(`/${options.inFolder}/`) || sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`);\n });\n }\n\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((f) => {\n return f.name && ts.isIdentifier(f.name) && regex.test(f.name.text);\n });\n }\n\n if (options?.isTopLevel) {\n filtered = filtered.filter((f) => {\n return ts.isSourceFile(f.parent);\n });\n }\n\n this.functions = filtered;\n }\n\n checkHaveModifier(modifierStr: string, isNot: boolean): RuleResult {\n let targetKind: ts.SyntaxKind;\n switch (modifierStr) {\n case 'export': targetKind = ts.SyntaxKind.ExportKeyword; break;\n case 'async': targetKind = ts.SyntaxKind.AsyncKeyword; break;\n case 'private': targetKind = ts.SyntaxKind.PrivateKeyword; break;\n case 'public': targetKind = ts.SyntaxKind.PublicKeyword; break;\n default:\n throw new Error(`Modifier ${modifierStr} is not fully supported.`);\n }\n\n const violations: string[] = [];\n for (const f of this.functions) {\n const name = f.name && ts.isIdentifier(f.name) ? f.name.text : 'Anonymous Function';\n const modifiers = ts.canHaveModifiers(f) ? ts.getModifiers(f) : undefined;\n const matches = modifiers && modifiers.some((m: ts.Modifier) => m.kind === targetKind);\n\n if (isNot && matches) {\n violations.push(`Function ${name} has modifier ${modifierStr}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Function ${name} does not have modifier ${modifierStr}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkHaveExplicitReturnType(isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const f of this.functions) {\n const name = f.name && ts.isIdentifier(f.name) ? f.name.text : 'Anonymous Function';\n const hasType = !!f.type;\n\n if (isNot && hasType) {\n violations.push(`Function ${name} has an explicit return type, but it shouldn't.`);\n } else if (!isNot && !hasType) {\n violations.push(`Function ${name} does not have an explicit return type, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkMatchNamePattern(pattern: string | RegExp, isNot: boolean): RuleResult {\n const violations: string[] = [];\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const f of this.functions) {\n const name = f.name && ts.isIdentifier(f.name) ? f.name.text : undefined;\n const matches = name && regex.test(name);\n \n if (isNot && matches) {\n violations.push(`Function ${name} matches pattern ${pattern}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Function ${name || 'Anonymous Function'} does not match pattern ${pattern}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface PropertyQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n}\n\nexport class PropertyLocator {\n public readonly properties: ts.PropertyDeclaration[];\n\n constructor(properties: ts.PropertyDeclaration[], private program: ts.Program, options?: PropertyQueryOptions) {\n let filtered = properties;\n\n if (options?.inFolder) {\n filtered = filtered.filter((p) => {\n const sourceFile = p.getSourceFile();\n return sourceFile.fileName.includes(`/${options.inFolder}/`) || sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`);\n });\n }\n\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((p) => {\n return ts.isIdentifier(p.name) && regex.test(p.name.text);\n });\n }\n\n this.properties = filtered;\n }\n\n checkBeReadonly(isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const p of this.properties) {\n const name = ts.isIdentifier(p.name) ? p.name.text : 'Anonymous Property';\n const modifiers = ts.canHaveModifiers(p) ? ts.getModifiers(p) : undefined;\n const matches = modifiers && modifiers.some((m: ts.Modifier) => m.kind === ts.SyntaxKind.ReadonlyKeyword);\n\n if (isNot && matches) {\n violations.push(`Property ${name} is readonly, but it shouldn't be.`);\n } else if (!isNot && !matches) {\n violations.push(`Property ${name} is not readonly, but it should be.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport class SliceLocator {\n private slicePattern: RegExp;\n private sliceIds: Set<string> = new Set();\n private sliceFiles: Map<string, ts.SourceFile[]> = new Map();\n\n constructor(sourceFiles: ts.SourceFile[], private program: ts.Program, pattern: string) {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regexStr = escaped.replace(/\\*/g, '([^/\\\\\\\\]+)');\n this.slicePattern = new RegExp(regexStr);\n\n for (const sf of sourceFiles) {\n const match = sf.fileName.match(this.slicePattern);\n if (match && match[1]) {\n const sliceId = match[1];\n this.sliceIds.add(sliceId);\n if (!this.sliceFiles.has(sliceId)) {\n this.sliceFiles.set(sliceId, []);\n }\n this.sliceFiles.get(sliceId)!.push(sf);\n }\n }\n }\n\n checkBeFreeOfCycles(isNot: boolean): RuleResult {\n const graph: Map<string, Set<string>> = new Map();\n for (const slice of this.sliceIds) {\n graph.set(slice, new Set());\n }\n\n for (const [sliceId, files] of this.sliceFiles.entries()) {\n for (const sf of files) {\n ts.forEachChild(sf, (node) => {\n if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {\n const importPath = node.moduleSpecifier.text;\n const resolved = ts.resolveModuleName(importPath, sf.fileName, this.program.getCompilerOptions(), ts.sys);\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName) {\n const targetMatch = resolved.resolvedModule.resolvedFileName.match(this.slicePattern);\n if (targetMatch && targetMatch[1]) {\n const targetSlice = targetMatch[1];\n if (targetSlice !== sliceId && this.sliceIds.has(targetSlice)) {\n graph.get(sliceId)!.add(targetSlice);\n }\n }\n }\n }\n });\n }\n }\n\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n const violations: string[] = [];\n\n const dfs = (node: string, path: string[]): boolean => {\n visited.add(node);\n recursionStack.add(node);\n\n for (const neighbor of (graph.get(node) || [])) {\n if (!visited.has(neighbor)) {\n if (dfs(neighbor, [...path, neighbor])) return true;\n } else if (recursionStack.has(neighbor)) {\n violations.push(`Cycle detected between slices: ${path.join(' -> ')} -> ${neighbor}`);\n return true;\n }\n }\n\n recursionStack.delete(node);\n return false;\n };\n\n for (const slice of this.sliceIds) {\n if (!visited.has(slice)) {\n dfs(slice, [slice]);\n }\n }\n\n if (isNot) {\n return {\n pass: violations.length > 0,\n message: () => violations.length > 0 ? '' : 'Expected cycles between slices but found none.'\n };\n } else {\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n')\n };\n }\n }\n}\n","import * as ts from 'typescript';\nimport * as path from 'path';\nimport { FileLocator, FileQueryOptions } from './FileLocator';\nimport { ClassLocator, ClassQueryOptions } from './ClassLocator';\nimport { LayeredArchitectureBuilder } from './LayerLocator';\nimport { FunctionLocator, FunctionQueryOptions } from './FunctionLocator';\nimport { PropertyLocator, PropertyQueryOptions } from './PropertyLocator';\nimport { SliceLocator } from './SliceLocator';\n\nexport class Project {\n private program: ts.Program;\n private typeChecker: ts.TypeChecker;\n\n constructor(options: { tsConfigFilePath?: string } = {}) {\n let compilerOptions: ts.CompilerOptions = {};\n const configPath = options.tsConfigFilePath || ts.findConfigFile(\n process.cwd(),\n ts.sys.fileExists,\n 'tsconfig.json'\n );\n\n if (configPath) {\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n const parsedCommandLine = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n path.dirname(configPath),\n undefined,\n configPath,\n undefined,\n [\n { extension: '.vue', isMixedContent: true, scriptKind: ts.ScriptKind.TS },\n { extension: '.svelte', isMixedContent: true, scriptKind: ts.ScriptKind.TS }\n ]\n );\n compilerOptions = parsedCommandLine.options;\n\n const host = ts.createCompilerHost(compilerOptions);\n const originalGetSourceFile = host.getSourceFile;\n\n let vueCompiler: any;\n try {\n vueCompiler = require('@vue/compiler-sfc');\n } catch (e) {\n // Not a Vue project\n }\n\n host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {\n if (fileName.endsWith('.vue')) {\n const content = ts.sys.readFile(fileName);\n if (content) {\n let scriptContent = '';\n if (vueCompiler) {\n const parsed = vueCompiler.parse(content);\n const script = parsed.descriptor.script;\n const scriptSetup = parsed.descriptor.scriptSetup;\n if (script) scriptContent += script.content + '\\n';\n if (scriptSetup) scriptContent += scriptSetup.content + '\\n';\n } else {\n // Fallback for Svelte or if compiler-sfc is missing (fragile but works for simple cases)\n const match = content.match(/<script[^>]*>(.*?)<\\/script>/s);\n if (match) scriptContent = match[1];\n }\n return ts.createSourceFile(fileName, scriptContent, languageVersion, true, ts.ScriptKind.TS);\n }\n }\n \n if (fileName.endsWith('.svelte')) {\n const content = ts.sys.readFile(fileName);\n if (content) {\n let scriptContent = '';\n const match = content.match(/<script[^>]*>(.*?)<\\/script>/s);\n if (match) scriptContent = match[1];\n return ts.createSourceFile(fileName, scriptContent, languageVersion, true, ts.ScriptKind.TS);\n }\n }\n\n return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);\n };\n\n this.program = ts.createProgram({\n rootNames: parsedCommandLine.fileNames,\n options: compilerOptions,\n host: host\n });\n } else {\n throw new Error(\"Could not find tsconfig.json\");\n }\n\n this.typeChecker = this.program.getTypeChecker();\n }\n\n getFiles(options?: FileQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n return new FileLocator(sourceFiles, this.program, options);\n }\n\n getClasses(options?: ClassQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n \n const allClasses: ts.ClassDeclaration[] = [];\n for (const sf of sourceFiles) {\n const visit = (node: ts.Node) => {\n if (ts.isClassDeclaration(node)) {\n allClasses.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return new ClassLocator(allClasses, this.program, options);\n }\n\n layeredArchitecture() {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n return new LayeredArchitectureBuilder(sourceFiles, this.program);\n }\n\n getFunctions(options?: FunctionQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n \n const allFunctions: ts.FunctionLikeDeclaration[] = [];\n for (const sf of sourceFiles) {\n const visit = (node: ts.Node) => {\n if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isArrowFunction(node)) {\n allFunctions.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return new FunctionLocator(allFunctions, this.program, options);\n }\n\n getProperties(options?: PropertyQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n \n const allProperties: ts.PropertyDeclaration[] = [];\n for (const sf of sourceFiles) {\n const visit = (node: ts.Node) => {\n if (ts.isPropertyDeclaration(node)) {\n allProperties.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return new PropertyLocator(allProperties, this.program, options);\n }\n\n getSlices(pattern: string) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n return new SliceLocator(sourceFiles, this.program, pattern);\n }\n}\n\nexport function parseProject(tsConfigFilePath?: string): Project {\n return new Project({ tsConfigFilePath });\n}\n","import { expect } from 'vitest';\nimport { RuleResult } from '../core/types';\nimport { ClassLocator } from '../core/ClassLocator';\nimport { FunctionLocator } from '../core/FunctionLocator';\nimport { PropertyLocator } from '../core/PropertyLocator';\nimport { FileLocator } from '../core/FileLocator';\nimport { SliceLocator } from '../core/SliceLocator';\nimport { LayeredArchitectureBuilder } from '../core/LayerLocator';\n\nexport function setupMatchers() {\n expect.extend({\n toPass(received: RuleResult | LayeredArchitectureBuilder) {\n const result = received instanceof LayeredArchitectureBuilder ? received.check() : received;\n const { pass, message } = result;\n return {\n pass: this.isNot ? !pass : pass,\n message: pass \n ? () => 'Expected rule not to pass' \n : () => message()\n };\n },\n\n toResideInFolder(received: ClassLocator, folder: string) {\n const { pass, message } = received.checkResideInFolder(folder, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toHaveModifier(received: ClassLocator | FunctionLocator, modifier: string) {\n const { pass, message } = received.checkHaveModifier(modifier, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n\n\n toExtendClass(received: ClassLocator, className: string) {\n const { pass, message } = received.checkExtendClass(className, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toImplementInterface(received: ClassLocator, interfaceName: string) {\n const { pass, message } = received.checkImplementInterface(interfaceName, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toHaveExplicitReturnType(received: FunctionLocator) {\n const { pass, message } = received.checkHaveExplicitReturnType(this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toBeReadonly(received: PropertyLocator) {\n const { pass, message } = received.checkBeReadonly(this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toDependOnFilesInFolder(received: FileLocator, folder: string) {\n const { pass, message } = received.checkDependOnFilesInFolder(folder, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toBeFreeOfCycles(received: FileLocator | SliceLocator) {\n const { pass, message } = received.checkBeFreeOfCycles(this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toMatchNamePattern(received: FileLocator | ClassLocator | FunctionLocator, pattern: string | RegExp) {\n const { pass, message } = received.checkMatchNamePattern(pattern, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n }\n });\n}\n\ndeclare module 'vitest' {\n interface Assertion<T = any> {\n toPass(): void;\n toResideInFolder(folder: string): void;\n toHaveModifier(modifier: 'export' | 'default' | 'abstract' | 'async' | 'private' | 'public'): void;\n\n toExtendClass(className: string): void;\n toImplementInterface(interfaceName: string): void;\n toHaveExplicitReturnType(): void;\n toBeReadonly(): void;\n toDependOnFilesInFolder(folder: string): void;\n toBeFreeOfCycles(): void;\n toMatchNamePattern(pattern: string | RegExp): void;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/core/classes/classCheckExtendClass.ts","../src/core/metrics/calculateCyclomaticComplexity.ts","../src/core/utils/ruleBuilder.ts","../src/core/shared/sharedCheckHaveMaxCyclomaticComplexity.ts","../src/core/classes/classCheckHaveMaxCyclomaticComplexity.ts","../src/core/shared/sharedCheckHaveModifier.ts","../src/core/classes/classCheckHaveModifier.ts","../src/core/shared/sharedCheckHaveNameMatchingFileName.ts","../src/core/classes/classCheckHaveNameMatchingFileName.ts","../src/core/classes/classCheckImplementInterface.ts","../src/core/shared/sharedCheckMatchNamePattern.ts","../src/core/classes/classCheckMatchNamePattern.ts","../src/core/classes/classCheckResideInFolder.ts","../src/core/classes/locateClasses.ts","../src/core/files/getFileDependencies.ts","../src/core/files/checkDependOnFilesInFolder.ts","../src/core/files/fileCheckBeFreeOfCycles.ts","../src/core/files/fileCheckHaveMaxCyclomaticComplexity.ts","../src/core/files/fileCheckHaveMaxExportedFunctions.ts","../src/core/metrics/calculateMaintainabilityIndex.ts","../src/core/shared/sharedCheckHaveMinMaintainabilityIndex.ts","../src/core/files/fileCheckHaveMinMaintainabilityIndex.ts","../src/core/files/fileCheckMatchNamePattern.ts","../src/core/files/locateFiles.ts","../src/core/functions/functionCheckHaveExplicitReturnType.ts","../src/core/functions/functionCheckHaveMaxCyclomaticComplexity.ts","../src/core/functions/functionCheckHaveMinMaintainabilityIndex.ts","../src/core/functions/functionCheckHaveModifier.ts","../src/core/functions/functionCheckHaveNameMatchingFileName.ts","../src/core/functions/functionCheckMatchNamePattern.ts","../src/core/functions/locateFunctions.ts","../src/core/layers/checkLayeredArchitecture.ts","../src/core/layers/createLayeredArchitecture.ts","../src/core/layers/layer.ts","../src/core/layers/getLayerDependencies.ts","../src/core/layers/layerShouldNotBeAccessedByAnyLayer.ts","../src/core/layers/layerShouldOnlyBeAccessedBy.ts","../src/core/properties/locateProperties.ts","../src/core/slices/locateSlices.ts","../src/core/project/parseProject.ts","../src/core/properties/propertyCheckBeReadonly.ts","../src/core/slices/sliceCheckBeFreeOfCycles.ts","../src/core/slices/sliceCheckHaveMaxDistanceFromMainSequence.ts","../src/matchers/index.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport type { RuleResult } from '../types';\nimport type { ClassLocatorData } from './types';\n\nexport function classCheckExtendClass(\n locator: ClassLocatorData,\n className: string,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n for (const c of locator.classes) {\n const name = c.name?.text || 'Anonymous';\n let matches = false;\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n for (const type of clause.types) {\n if (\n ts.isIdentifier(type.expression) &&\n type.expression.text === className\n ) {\n matches = true;\n break;\n }\n }\n }\n }\n }\n if (isNot && matches) {\n violations.push(`Class ${name} extends ${className}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(\n `Class ${name} does not extend ${className}, but it should.`,\n );\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import * as ts from 'typescript';\n\nexport function calculateCyclomaticComplexity(node: ts.Node): number {\n let complexity = 1;\n\n const visit = (n: ts.Node) => {\n switch (n.kind) {\n case ts.SyntaxKind.IfStatement:\n case ts.SyntaxKind.ForStatement:\n case ts.SyntaxKind.ForInStatement:\n case ts.SyntaxKind.ForOfStatement:\n case ts.SyntaxKind.WhileStatement:\n case ts.SyntaxKind.DoStatement:\n case ts.SyntaxKind.CaseClause:\n case ts.SyntaxKind.CatchClause:\n case ts.SyntaxKind.ConditionalExpression:\n complexity++;\n break;\n case ts.SyntaxKind.BinaryExpression: {\n const binary = n as ts.BinaryExpression;\n if (\n binary.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken ||\n binary.operatorToken.kind === ts.SyntaxKind.BarBarToken ||\n binary.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken\n ) {\n complexity++;\n }\n break;\n }\n }\n ts.forEachChild(n, visit);\n };\n\n ts.forEachChild(node, visit);\n return complexity;\n}\n","import type { RuleResult } from '../types';\n\nexport function ruleBuilder<T>(\n items: T[],\n isNot: boolean,\n evaluate: (item: T) => {\n passes: boolean;\n failMessage: string;\n failNotMessage: string;\n },\n): RuleResult {\n const violations: string[] = [];\n\n for (const item of items) {\n const { passes, failMessage, failNotMessage } = evaluate(item);\n\n if (isNot && passes) {\n if (failNotMessage) violations.push(failNotMessage);\n } else if (!isNot && !passes) {\n if (failMessage) violations.push(failMessage);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import { ruleBuilder } from '../utils/ruleBuilder';\n\nexport function sharedCheckHaveMaxCyclomaticComplexity<T>(\n items: T[],\n getName: (item: T) => string | undefined,\n getComplexity: (item: T) => number,\n label: string,\n max: number,\n isNot: boolean,\n) {\n return ruleBuilder(items, isNot, (item) => {\n const name = getName(item);\n const complexity = getComplexity(item);\n const exceeds = complexity > max;\n const desc = `${label} ${name || 'Anonymous'}`;\n\n return {\n passes: !exceeds,\n failMessage: `${desc} has a total cyclomatic complexity of ${complexity}, which exceeds the maximum of ${max}.`,\n failNotMessage: `${desc} has a total cyclomatic complexity of ${complexity}, which exceeds the maximum of ${max}, but it shouldn't.`,\n };\n });\n}\n","import * as ts from 'typescript';\nimport { calculateCyclomaticComplexity } from '../metrics/calculateCyclomaticComplexity';\nimport { sharedCheckHaveMaxCyclomaticComplexity } from '../shared/sharedCheckHaveMaxCyclomaticComplexity';\nimport type { RuleResult } from '../types';\nimport type { ClassLocatorData } from './types';\n\nexport function classCheckHaveMaxCyclomaticComplexity(\n locator: ClassLocatorData,\n max: number,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveMaxCyclomaticComplexity(\n locator.classes,\n (c) => c.name?.text,\n (c) => {\n let complexity = 0;\n const visit = (node: ts.Node) => {\n if (\n ts.isMethodDeclaration(node) ||\n ts.isConstructorDeclaration(node) ||\n ts.isGetAccessor(node) ||\n ts.isSetAccessor(node)\n ) {\n complexity += calculateCyclomaticComplexity(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(c);\n return complexity;\n },\n 'Class',\n max,\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport { ruleBuilder } from '../utils/ruleBuilder';\n\nexport function sharedCheckHaveModifier<T extends ts.Node>(\n items: T[],\n getName: (item: T) => string | undefined,\n label: string,\n modifierStr: string,\n isNot: boolean,\n) {\n let targetKind: ts.SyntaxKind;\n switch (modifierStr) {\n case 'export':\n targetKind = ts.SyntaxKind.ExportKeyword;\n break;\n case 'default':\n targetKind = ts.SyntaxKind.DefaultKeyword;\n break;\n case 'abstract':\n targetKind = ts.SyntaxKind.AbstractKeyword;\n break;\n case 'async':\n targetKind = ts.SyntaxKind.AsyncKeyword;\n break;\n case 'public':\n targetKind = ts.SyntaxKind.PublicKeyword;\n break;\n case 'private':\n targetKind = ts.SyntaxKind.PrivateKeyword;\n break;\n default:\n throw new Error(`Modifier ${modifierStr} is not fully supported.`);\n }\n\n return ruleBuilder(items, isNot, (item) => {\n const name = getName(item);\n const modifiers = ts.canHaveModifiers(item)\n ? ts.getModifiers(item)\n : undefined;\n const passes = modifiers\n ? modifiers.some((m: ts.Modifier) => m.kind === targetKind)\n : false;\n const desc = `${label} ${name || 'Anonymous'}`;\n\n return {\n passes,\n failMessage: `${desc} does not have modifier ${modifierStr}, but it should.`,\n failNotMessage: `${desc} has modifier ${modifierStr}, but it shouldn't.`,\n };\n });\n}\n","import { sharedCheckHaveModifier } from '../shared/sharedCheckHaveModifier';\nimport type { RuleResult } from '../types';\nimport type { ClassLocatorData } from './types';\n\nexport function classCheckHaveModifier(\n locator: ClassLocatorData,\n modifierStr: string,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveModifier(\n locator.classes,\n (c) => c.name?.text,\n 'Class',\n modifierStr,\n isNot,\n );\n}\n","import * as path from 'node:path';\nimport * as ts from 'typescript';\nimport { ruleBuilder } from '../utils/ruleBuilder';\n\nexport function sharedCheckHaveNameMatchingFileName<T extends ts.Node>(\n items: T[],\n getName: (item: T) => string | undefined,\n label: string,\n isNot: boolean,\n) {\n return ruleBuilder(items, isNot, (item) => {\n const name = getName(item);\n const sourceFile = item.getSourceFile\n ? item.getSourceFile()\n : item.parent\n ? ts.getSourceFileOfNode(item)\n : undefined;\n\n if (!sourceFile) {\n return { passes: true, failMessage: '', failNotMessage: '' };\n }\n\n const basename = path.basename(\n sourceFile.fileName,\n path.extname(sourceFile.fileName),\n );\n const passes = name === basename;\n const desc = `${label} ${name || 'Anonymous'}`;\n\n return {\n passes,\n failMessage: `${desc} does not have a name matching its filename ${basename}, but it should.`,\n failNotMessage: `${desc} has a name matching its filename ${basename}, but it shouldn't.`,\n };\n });\n}\n","import { sharedCheckHaveNameMatchingFileName } from '../shared/sharedCheckHaveNameMatchingFileName';\nimport type { RuleResult } from '../types';\nimport type { ClassLocatorData } from './types';\n\nexport function classCheckHaveNameMatchingFileName(\n locator: ClassLocatorData,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveNameMatchingFileName(\n locator.classes,\n (c) => c.name?.text,\n 'Class',\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport type { RuleResult } from '../types';\nimport type { ClassLocatorData } from './types';\n\nexport function classCheckImplementInterface(\n locator: ClassLocatorData,\n interfaceName: string,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n for (const c of locator.classes) {\n const name = c.name?.text || 'Anonymous';\n let matches = false;\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ImplementsKeyword) {\n for (const type of clause.types) {\n if (\n ts.isIdentifier(type.expression) &&\n type.expression.text === interfaceName\n ) {\n matches = true;\n break;\n }\n }\n }\n }\n }\n if (isNot && matches) {\n violations.push(\n `Class ${name} implements ${interfaceName}, but it shouldn't.`,\n );\n } else if (!isNot && !matches) {\n violations.push(\n `Class ${name} does not implement ${interfaceName}, but it should.`,\n );\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import { ruleBuilder } from '../utils/ruleBuilder';\n\nexport function sharedCheckMatchNamePattern<T>(\n items: T[],\n getName: (item: T) => string | undefined,\n label: string,\n pattern: string | RegExp,\n isNot: boolean,\n) {\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n return ruleBuilder(items, isNot, (item) => {\n const name = getName(item);\n const passes = name ? regex.test(name) : false;\n const desc = `${label} ${name || 'Anonymous'}`;\n return {\n passes,\n failMessage: `${desc} does not match pattern ${pattern}, but it should.`,\n failNotMessage: `${desc} matches pattern ${pattern}, but it shouldn't.`,\n };\n });\n}\n","import { sharedCheckMatchNamePattern } from '../shared/sharedCheckMatchNamePattern';\nimport type { RuleResult } from '../types';\nimport type { ClassLocatorData } from './types';\n\nexport function classCheckMatchNamePattern(\n locator: ClassLocatorData,\n pattern: string | RegExp,\n isNot: boolean,\n): RuleResult {\n return sharedCheckMatchNamePattern(\n locator.classes,\n (c) => c.name?.text,\n 'Class',\n pattern,\n isNot,\n );\n}\n","import type { RuleResult } from '../types';\nimport type { ClassLocatorData } from './types';\n\nexport function classCheckResideInFolder(\n locator: ClassLocatorData,\n targetFolder: string,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n for (const c of locator.classes) {\n const className = c.name?.text || 'Anonymous Class';\n const sourceFile = c.getSourceFile();\n const inTargetFolder =\n sourceFile.fileName.includes(`/${targetFolder}/`) ||\n sourceFile.fileName.includes(`\\\\${targetFolder}\\\\`);\n\n if (isNot && inTargetFolder) {\n violations.push(\n `Class ${className} resides in ${targetFolder}, but it shouldn't.`,\n );\n } else if (!isNot && !inTargetFolder) {\n violations.push(\n `Class ${className} does not reside in ${targetFolder}, but it should.`,\n );\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import * as ts from 'typescript';\nimport type { ClassLocatorData, ClassQueryOptions } from './types';\n\nexport function locateClasses(\n classes: ts.ClassDeclaration[],\n program: ts.Program,\n options?: ClassQueryOptions,\n): ClassLocatorData {\n let filtered = classes;\n\n if (options?.inFolder) {\n filtered = filtered.filter((c) => {\n const sourceFile = c.getSourceFile\n ? c.getSourceFile()\n : c.parent\n ? ts.getSourceFileOfNode(c)\n : undefined;\n if (!sourceFile) return false;\n return (\n sourceFile.fileName.includes(`/${options.inFolder}/`) ||\n sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`)\n );\n });\n }\n if (options?.matchNamePattern) {\n const regex =\n typeof options.matchNamePattern === 'string'\n ? new RegExp(options.matchNamePattern)\n : options.matchNamePattern;\n filtered = filtered.filter((c) => {\n const name = c.name?.text;\n return name && regex.test(name);\n });\n }\n if (options?.withDecorator) {\n filtered = filtered.filter((c) => {\n const decorators = ts.canHaveDecorators(c)\n ? ts.getDecorators(c)\n : undefined;\n let hasDecorator = false;\n if (decorators) {\n for (const dec of decorators) {\n const exp = dec.expression;\n let name = '';\n if (ts.isIdentifier(exp)) {\n name = exp.text;\n } else if (\n ts.isCallExpression(exp) &&\n ts.isIdentifier(exp.expression)\n ) {\n name = exp.expression.text;\n }\n if (name === options.withDecorator) {\n hasDecorator = true;\n }\n }\n }\n return hasDecorator;\n });\n }\n if (options?.extending) {\n filtered = filtered.filter((c) => {\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n for (const type of clause.types) {\n if (\n ts.isIdentifier(type.expression) &&\n type.expression.text === options.extending\n ) {\n return true;\n }\n }\n }\n }\n }\n return false;\n });\n }\n if (options?.implementing) {\n filtered = filtered.filter((c) => {\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ImplementsKeyword) {\n for (const type of clause.types) {\n if (\n ts.isIdentifier(type.expression) &&\n type.expression.text === options.implementing\n ) {\n return true;\n }\n }\n }\n }\n }\n return false;\n });\n }\n if (options?.havingModifier) {\n let targetKind: ts.SyntaxKind;\n switch (options.havingModifier) {\n case 'export':\n targetKind = ts.SyntaxKind.ExportKeyword;\n break;\n case 'default':\n targetKind = ts.SyntaxKind.DefaultKeyword;\n break;\n case 'abstract':\n targetKind = ts.SyntaxKind.AbstractKeyword;\n break;\n default:\n throw new Error(\n `Modifier ${options.havingModifier} is not fully supported.`,\n );\n }\n filtered = filtered.filter((c) => {\n const modifiers = ts.canHaveModifiers(c) ? ts.getModifiers(c) : undefined;\n return modifiers?.some((m: ts.Modifier) => m.kind === targetKind);\n });\n }\n\n return {\n type: 'ClassLocator',\n classes: filtered,\n program,\n };\n}\n","import * as ts from 'typescript';\n\nexport function getFileDependencies(\n sourceFile: ts.SourceFile,\n program: ts.Program,\n): string[] {\n const dependencies: string[] = [];\n const compilerOptions = program.getCompilerOptions();\n\n const visit = (node: ts.Node) => {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys,\n );\n if (resolved.resolvedModule?.resolvedFileName) {\n if (!resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n } else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys,\n );\n if (resolved.resolvedModule?.resolvedFileName) {\n if (!resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return dependencies;\n}\n","import type { RuleResult } from '../types';\nimport { getFileDependencies } from './getFileDependencies';\nimport type { FileLocatorData } from './types';\n\nexport function checkDependOnFilesInFolder(\n locator: FileLocatorData,\n targetFolder: string,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n\n for (const file of locator.files) {\n const dependencies = getFileDependencies(file, locator.program);\n\n const dependsOnTarget = dependencies.some(\n (depPath) =>\n depPath.includes(`/${targetFolder}/`) ||\n depPath.includes(`\\\\${targetFolder}\\\\`),\n );\n\n if (isNot && dependsOnTarget) {\n violations.push(\n `File ${file.fileName} depends on files in ${targetFolder}, but it shouldn't.`,\n );\n } else if (!isNot && !dependsOnTarget) {\n violations.push(\n `File ${file.fileName} does not depend on files in ${targetFolder}, but it should.`,\n );\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import type { RuleResult } from '../types';\nimport { getFileDependencies } from './getFileDependencies';\nimport type { FileLocatorData } from './types';\n\nexport function fileCheckBeFreeOfCycles(\n locator: FileLocatorData,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n const targetedFilePaths = new Set<string>(\n locator.files.map((f) => f.fileName),\n );\n const graph = new Map<string, string[]>();\n\n for (const file of locator.files) {\n const filePath = file.fileName;\n const dependencies = getFileDependencies(file, locator.program).filter(\n (p) => targetedFilePaths.has(p),\n );\n\n graph.set(filePath, dependencies);\n }\n\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const cycles: string[][] = [];\n\n const isCyclicUtil = (node: string, path: string[]) => {\n if (recStack.has(node)) {\n const cycleStartIndex = path.indexOf(node);\n const cycleStr = [...path.slice(cycleStartIndex), node].join('->');\n if (!cycles.some((c) => c.join('->') === cycleStr)) {\n cycles.push([...path.slice(cycleStartIndex), node]);\n }\n return true;\n }\n\n if (visited.has(node)) return false;\n\n visited.add(node);\n recStack.add(node);\n path.push(node);\n\n const neighbors = graph.get(node) || [];\n for (const neighbor of neighbors) {\n isCyclicUtil(neighbor, path);\n }\n\n recStack.delete(node);\n path.pop();\n return false;\n };\n\n for (const node of graph.keys()) {\n if (!visited.has(node)) {\n isCyclicUtil(node, []);\n }\n }\n\n if (isNot && cycles.length === 0) {\n violations.push('Expected cyclic dependencies, but found none.');\n } else if (!isNot && cycles.length > 0) {\n for (const cycle of cycles) {\n violations.push(`Cycle detected: ${cycle.join(' -> ')}`);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import * as ts from 'typescript';\nimport { calculateCyclomaticComplexity } from '../metrics/calculateCyclomaticComplexity';\nimport { sharedCheckHaveMaxCyclomaticComplexity } from '../shared/sharedCheckHaveMaxCyclomaticComplexity';\nimport type { RuleResult } from '../types';\nimport type { FileLocatorData } from './types';\n\nexport function fileCheckHaveMaxCyclomaticComplexity(\n locator: FileLocatorData,\n max: number,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveMaxCyclomaticComplexity(\n locator.files,\n (f) => f.fileName,\n (file) => {\n let complexity = 0;\n const visit = (node: ts.Node) => {\n if (\n ts.isFunctionDeclaration(node) ||\n ts.isMethodDeclaration(node) ||\n ts.isArrowFunction(node) ||\n ts.isFunctionExpression(node)\n ) {\n complexity += calculateCyclomaticComplexity(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(file);\n return complexity;\n },\n 'File',\n max,\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport type { RuleResult } from '../types';\nimport type { FileLocatorData } from './types';\n\nexport function fileCheckHaveMaxExportedFunctions(\n locator: FileLocatorData,\n max: number,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n for (const file of locator.files) {\n let exportedFuncCount = 0;\n\n ts.forEachChild(file, (node) => {\n if (ts.isFunctionDeclaration(node)) {\n const modifiers = ts.canHaveModifiers(node)\n ? ts.getModifiers(node)\n : undefined;\n if (modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) {\n exportedFuncCount++;\n }\n }\n });\n\n const exceeds = exportedFuncCount > max;\n\n if (isNot && exceeds) {\n violations.push(\n `File ${file.fileName} has ${exportedFuncCount} exported functions, which exceeds the maximum of ${max}, but it shouldn't.`,\n );\n } else if (!isNot && exceeds) {\n violations.push(\n `File ${file.fileName} has ${exportedFuncCount} exported functions, which exceeds the maximum of ${max}.`,\n );\n }\n }\n return {\n pass: isNot ? violations.length > 0 : violations.length === 0,\n message: () =>\n violations.join('\\n') ||\n (isNot\n ? 'Expected some files to exceed maximum exported functions, but none did.'\n : ''),\n };\n}\n","import * as ts from 'typescript';\nimport { calculateCyclomaticComplexity } from './calculateCyclomaticComplexity';\n\nexport function calculateMaintainabilityIndex(node: ts.Node): number {\n let operators = 0;\n let operands = 0;\n const uniqueOperators = new Set<number>();\n const uniqueOperands = new Set<string>();\n let linesOfCode = 1;\n\n const sourceFile = node.getSourceFile();\n if (sourceFile) {\n const start = sourceFile.getLineAndCharacterOfPosition(node.getStart());\n const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());\n linesOfCode = end.line - start.line + 1;\n }\n\n const visit = (n: ts.Node) => {\n if (\n ts.isBinaryExpression(n) ||\n ts.isPrefixUnaryExpression(n) ||\n ts.isPostfixUnaryExpression(n)\n ) {\n operators++;\n uniqueOperators.add(n.kind);\n } else if (ts.isIdentifier(n) || ts.isLiteralExpression(n)) {\n operands++;\n uniqueOperands.add(n.getText(sourceFile));\n }\n ts.forEachChild(n, visit);\n };\n\n visit(node);\n\n const N = operators + operands;\n const n = uniqueOperators.size + uniqueOperands.size;\n const V = n === 0 ? 0 : N * Math.log2(n);\n const CC = calculateCyclomaticComplexity(node);\n\n const mi = Math.max(\n 0,\n ((171 - 5.2 * Math.log(V || 1) - 0.23 * CC - 16.2 * Math.log(linesOfCode)) *\n 100) /\n 171,\n );\n return mi;\n}\n","import { ruleBuilder } from '../utils/ruleBuilder';\n\nexport function sharedCheckHaveMinMaintainabilityIndex<T>(\n items: T[],\n getName: (item: T) => string | undefined,\n getMi: (item: T) => number,\n label: string,\n min: number,\n isNot: boolean,\n) {\n return ruleBuilder(items, isNot, (item) => {\n const name = getName(item);\n const mi = getMi(item);\n const fallsBelow = mi < min;\n const desc = `${label} ${name || 'Anonymous'}`;\n\n return {\n passes: !fallsBelow,\n failMessage: `${desc} has a maintainability index of ${mi.toFixed(2)}, which falls below the minimum of ${min}.`,\n failNotMessage: `${desc} has a maintainability index of ${mi.toFixed(2)}, which falls below the minimum of ${min}, but it shouldn't.`,\n };\n });\n}\n","import { calculateMaintainabilityIndex } from '../metrics/calculateMaintainabilityIndex';\nimport { sharedCheckHaveMinMaintainabilityIndex } from '../shared/sharedCheckHaveMinMaintainabilityIndex';\nimport type { RuleResult } from '../types';\nimport type { FileLocatorData } from './types';\n\nexport function fileCheckHaveMinMaintainabilityIndex(\n locator: FileLocatorData,\n min: number,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveMinMaintainabilityIndex(\n locator.files,\n (f) => f.fileName,\n calculateMaintainabilityIndex,\n 'File',\n min,\n isNot,\n );\n}\n","import { sharedCheckMatchNamePattern } from '../shared/sharedCheckMatchNamePattern';\nimport type { RuleResult } from '../types';\nimport type { FileLocatorData } from './types';\n\nexport function fileCheckMatchNamePattern(\n locator: FileLocatorData,\n pattern: string | RegExp,\n isNot: boolean,\n): RuleResult {\n return sharedCheckMatchNamePattern(\n locator.files,\n (f) => f.fileName,\n 'File',\n pattern,\n isNot,\n );\n}\n","import type * as ts from 'typescript';\nimport type { FileLocatorData, FileQueryOptions } from './types';\n\nexport function locateFiles(\n sourceFiles: ts.SourceFile[],\n program: ts.Program,\n options?: FileQueryOptions,\n): FileLocatorData {\n let filtered = sourceFiles;\n\n if (options?.inFolder) {\n filtered = filtered.filter(\n (file) =>\n file.fileName.includes(`/${options.inFolder}/`) ||\n file.fileName.includes(`\\\\${options.inFolder}\\\\`),\n );\n }\n if (options?.matchNamePattern) {\n const regex =\n typeof options.matchNamePattern === 'string'\n ? new RegExp(options.matchNamePattern)\n : options.matchNamePattern;\n filtered = filtered.filter((file) => regex.test(file.fileName));\n }\n\n return {\n type: 'FileLocator',\n files: filtered,\n program,\n };\n}\n","import * as ts from 'typescript';\nimport type { RuleResult } from '../types';\nimport type { FunctionLocatorData } from './types';\n\nexport function functionCheckHaveExplicitReturnType(\n locator: FunctionLocatorData,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n for (const f of locator.functions) {\n const name =\n f.name && ts.isIdentifier(f.name) ? f.name.text : 'Anonymous Function';\n const hasType = !!f.type;\n\n if (isNot && hasType) {\n violations.push(\n `Function ${name} has an explicit return type, but it shouldn't.`,\n );\n } else if (!isNot && !hasType) {\n violations.push(\n `Function ${name} does not have an explicit return type, but it should.`,\n );\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import * as ts from 'typescript';\nimport { calculateCyclomaticComplexity } from '../metrics/calculateCyclomaticComplexity';\nimport { sharedCheckHaveMaxCyclomaticComplexity } from '../shared/sharedCheckHaveMaxCyclomaticComplexity';\nimport type { RuleResult } from '../types';\nimport type { FunctionLocatorData } from './types';\n\nexport function functionCheckHaveMaxCyclomaticComplexity(\n locator: FunctionLocatorData,\n max: number,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveMaxCyclomaticComplexity(\n locator.functions,\n (f) => (f.name && ts.isIdentifier(f.name) ? f.name.text : undefined),\n calculateCyclomaticComplexity,\n 'Function',\n max,\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport { calculateMaintainabilityIndex } from '../metrics/calculateMaintainabilityIndex';\nimport { sharedCheckHaveMinMaintainabilityIndex } from '../shared/sharedCheckHaveMinMaintainabilityIndex';\nimport type { RuleResult } from '../types';\nimport type { FunctionLocatorData } from './types';\n\nexport function functionCheckHaveMinMaintainabilityIndex(\n locator: FunctionLocatorData,\n min: number,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveMinMaintainabilityIndex(\n locator.functions,\n (f) => (f.name && ts.isIdentifier(f.name) ? f.name.text : undefined),\n calculateMaintainabilityIndex,\n 'Function',\n min,\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport { sharedCheckHaveModifier } from '../shared/sharedCheckHaveModifier';\nimport type { RuleResult } from '../types';\nimport type { FunctionLocatorData } from './types';\n\nexport function functionCheckHaveModifier(\n locator: FunctionLocatorData,\n modifierStr: string,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveModifier(\n locator.functions,\n (f) => (f.name && ts.isIdentifier(f.name) ? f.name.text : undefined),\n 'Function',\n modifierStr,\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport { sharedCheckHaveNameMatchingFileName } from '../shared/sharedCheckHaveNameMatchingFileName';\nimport type { RuleResult } from '../types';\nimport type { FunctionLocatorData } from './types';\n\nexport function functionCheckHaveNameMatchingFileName(\n locator: FunctionLocatorData,\n isNot: boolean,\n): RuleResult {\n return sharedCheckHaveNameMatchingFileName(\n locator.functions,\n (f) => (f.name && ts.isIdentifier(f.name) ? f.name.text : undefined),\n 'Function',\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport { sharedCheckMatchNamePattern } from '../shared/sharedCheckMatchNamePattern';\nimport type { RuleResult } from '../types';\nimport type { FunctionLocatorData } from './types';\n\nexport function functionCheckMatchNamePattern(\n locator: FunctionLocatorData,\n pattern: string | RegExp,\n isNot: boolean,\n): RuleResult {\n return sharedCheckMatchNamePattern(\n locator.functions,\n (f) => (f.name && ts.isIdentifier(f.name) ? f.name.text : undefined),\n 'Function',\n pattern,\n isNot,\n );\n}\n","import * as ts from 'typescript';\nimport type { FunctionLocatorData, FunctionQueryOptions } from './types';\n\nexport function locateFunctions(\n functions: ts.FunctionLikeDeclaration[],\n program: ts.Program,\n options?: FunctionQueryOptions,\n): FunctionLocatorData {\n let filtered = functions;\n\n if (options?.inFolder) {\n filtered = filtered.filter((f) => {\n const sourceFile = f.getSourceFile\n ? f.getSourceFile()\n : f.parent\n ? ts.getSourceFileOfNode(f)\n : undefined;\n if (!sourceFile) return false;\n return (\n sourceFile.fileName.includes(`/${options.inFolder}/`) ||\n sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`)\n );\n });\n }\n\n if (options?.matchNamePattern) {\n const regex =\n typeof options.matchNamePattern === 'string'\n ? new RegExp(options.matchNamePattern)\n : options.matchNamePattern;\n filtered = filtered.filter((f) => {\n return f.name && ts.isIdentifier(f.name) && regex.test(f.name.text);\n });\n }\n\n if (options?.isTopLevel) {\n filtered = filtered.filter((f) => {\n return ts.isSourceFile(f.parent);\n });\n }\n\n return {\n type: 'FunctionLocator',\n functions: filtered,\n program,\n };\n}\n","import type { RuleResult } from '../types';\nimport type { LayeredArchitectureData } from './types';\n\nexport function checkLayeredArchitecture(\n data: LayeredArchitectureData,\n): RuleResult {\n const violations: string[] = [];\n for (const assertion of data.assertions) {\n violations.push(...assertion(data.files));\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import type * as ts from 'typescript';\nimport type { LayeredArchitectureData } from './types';\n\nexport function createLayeredArchitecture(\n files: ts.SourceFile[],\n program: ts.Program,\n): LayeredArchitectureData {\n return {\n type: 'LayeredArchitecture',\n files,\n layers: new Map<string, string>(),\n assertions: [],\n program,\n };\n}\n","import type { LayeredArchitectureData } from './types';\n\nexport function layer(\n data: LayeredArchitectureData,\n name: string,\n folderPattern: string,\n): LayeredArchitectureData {\n data.layers.set(name, folderPattern);\n return data;\n}\n","import * as ts from 'typescript';\n\nexport function getLayerDependencies(\n sourceFile: ts.SourceFile,\n program: ts.Program,\n): string[] {\n const dependencies: string[] = [];\n const compilerOptions = program.getCompilerOptions();\n\n const visit = (node: ts.Node) => {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys,\n );\n if (\n resolved.resolvedModule?.resolvedFileName &&\n !resolved.resolvedModule.isExternalLibraryImport\n ) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n } else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys,\n );\n if (\n resolved.resolvedModule?.resolvedFileName &&\n !resolved.resolvedModule.isExternalLibraryImport\n ) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return dependencies;\n}\n","import { getLayerDependencies } from './getLayerDependencies';\nimport type { LayeredArchitectureData } from './types';\n\nexport function layerShouldNotBeAccessedByAnyLayer(\n data: LayeredArchitectureData,\n targetLayer: string,\n): LayeredArchitectureData {\n if (!data.layers.has(targetLayer)) {\n throw new Error(`Layer ${targetLayer} is not defined`);\n }\n\n data.assertions.push((files) => {\n const violations: string[] = [];\n // biome-ignore lint/style/noNonNullAssertion: Safe map lookup\n const targetPattern = data.layers.get(targetLayer)!;\n\n for (const file of files) {\n const filePath = file.fileName;\n if (\n !filePath.includes(`/${targetPattern}/`) &&\n !filePath.includes(`\\\\${targetPattern}\\\\`)\n ) {\n const dependencies = getLayerDependencies(file, data.program);\n const importsTarget = dependencies.some(\n (dep) =>\n dep.includes(`/${targetPattern}/`) ||\n dep.includes(`\\\\${targetPattern}\\\\`),\n );\n if (importsTarget) {\n violations.push(\n `File ${filePath} accesses layer ${targetLayer} but it shouldn't.`,\n );\n }\n }\n }\n return violations;\n });\n\n return data;\n}\n","import { getLayerDependencies } from './getLayerDependencies';\nimport type { LayeredArchitectureData } from './types';\n\nexport function layerShouldOnlyBeAccessedBy(\n data: LayeredArchitectureData,\n targetLayer: string,\n allowedLayers: string[],\n): LayeredArchitectureData {\n if (!data.layers.has(targetLayer)) {\n throw new Error(`Layer ${targetLayer} is not defined`);\n }\n\n data.assertions.push((files) => {\n const violations: string[] = [];\n // biome-ignore lint/style/noNonNullAssertion: Safe map lookup\n const targetPattern = data.layers.get(targetLayer)!;\n // biome-ignore lint/style/noNonNullAssertion: Safe map lookup\n const allowedPatterns = allowedLayers.map((l) => data.layers.get(l)!);\n\n for (const file of files) {\n const filePath = file.fileName;\n const isInAllowedLayer = allowedPatterns.some(\n (p) => filePath.includes(`/${p}/`) || filePath.includes(`\\\\${p}\\\\`),\n );\n\n if (\n !filePath.includes(`/${targetPattern}/`) &&\n !filePath.includes(`\\\\${targetPattern}\\\\`) &&\n !isInAllowedLayer\n ) {\n const dependencies = getLayerDependencies(file, data.program);\n const importsTarget = dependencies.some(\n (dep) =>\n dep.includes(`/${targetPattern}/`) ||\n dep.includes(`\\\\${targetPattern}\\\\`),\n );\n if (importsTarget) {\n violations.push(\n `File ${filePath} accesses layer ${targetLayer} but only ${allowedLayers.join(', ')} are allowed.`,\n );\n }\n }\n }\n return violations;\n });\n\n return data;\n}\n","import * as ts from 'typescript';\nimport type { PropertyLocatorData, PropertyQueryOptions } from './types';\n\nexport function locateProperties(\n properties: ts.PropertyDeclaration[],\n program: ts.Program,\n options?: PropertyQueryOptions,\n): PropertyLocatorData {\n let filtered = properties;\n\n if (options?.inFolder) {\n filtered = filtered.filter((p) => {\n const sourceFile = p.getSourceFile\n ? p.getSourceFile()\n : p.parent\n ? ts.getSourceFileOfNode(p)\n : undefined;\n if (!sourceFile) return false;\n return (\n sourceFile.fileName.includes(`/${options.inFolder}/`) ||\n sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`)\n );\n });\n }\n\n if (options?.matchNamePattern) {\n const regex =\n typeof options.matchNamePattern === 'string'\n ? new RegExp(options.matchNamePattern)\n : options.matchNamePattern;\n filtered = filtered.filter((p) => {\n return ts.isIdentifier(p.name) && regex.test(p.name.text);\n });\n }\n\n return {\n type: 'PropertyLocator',\n properties: filtered,\n program,\n };\n}\n","import type * as ts from 'typescript';\nimport type { SliceLocatorData } from './types';\n\nexport function locateSlices(\n sourceFiles: ts.SourceFile[],\n program: ts.Program,\n pattern: string,\n): SliceLocatorData {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regexStr = escaped.replace(/\\*/g, '([^/\\\\\\\\]+)');\n const slicePattern = new RegExp(regexStr);\n\n const sliceIds = new Set<string>();\n const sliceFiles = new Map<string, ts.SourceFile[]>();\n\n for (const sf of sourceFiles) {\n const match = sf.fileName.match(slicePattern);\n if (match?.[1]) {\n const sliceId = match[1];\n sliceIds.add(sliceId);\n if (!sliceFiles.has(sliceId)) {\n sliceFiles.set(sliceId, []);\n }\n sliceFiles.get(sliceId)?.push(sf);\n }\n }\n\n return {\n type: 'SliceLocator',\n slicePattern,\n sliceIds,\n sliceFiles,\n program,\n };\n}\n","import { dirname } from 'node:path';\nimport * as ts from 'typescript';\nimport { locateClasses } from '../classes/locateClasses';\nimport type { ClassQueryOptions } from '../classes/types';\nimport { locateFiles } from '../files/locateFiles';\nimport type { FileQueryOptions } from '../files/types';\nimport { locateFunctions } from '../functions/locateFunctions';\nimport type { FunctionQueryOptions } from '../functions/types';\nimport { checkLayeredArchitecture } from '../layers/checkLayeredArchitecture';\nimport { createLayeredArchitecture } from '../layers/createLayeredArchitecture';\nimport { layer } from '../layers/layer';\nimport { layerShouldNotBeAccessedByAnyLayer } from '../layers/layerShouldNotBeAccessedByAnyLayer';\nimport { layerShouldOnlyBeAccessedBy } from '../layers/layerShouldOnlyBeAccessedBy';\nimport { locateProperties } from '../properties/locateProperties';\nimport type { PropertyQueryOptions } from '../properties/types';\nimport { locateSlices } from '../slices/locateSlices';\n\nexport function parseProject(options: { tsConfigFilePath?: string } = {}) {\n let compilerOptions: ts.CompilerOptions = {};\n const configPath =\n options.tsConfigFilePath ||\n ts.findConfigFile(process.cwd(), ts.sys.fileExists, 'tsconfig.json');\n\n let program: ts.Program;\n\n if (configPath) {\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n const parsedCommandLine = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n dirname(configPath),\n undefined,\n configPath,\n undefined,\n [\n {\n extension: '.vue',\n isMixedContent: true,\n scriptKind: ts.ScriptKind.TS,\n },\n {\n extension: '.svelte',\n isMixedContent: true,\n scriptKind: ts.ScriptKind.TS,\n },\n ],\n );\n compilerOptions = parsedCommandLine.options;\n\n const host = ts.createCompilerHost(compilerOptions);\n const originalGetSourceFile = host.getSourceFile;\n\n // biome-ignore lint/suspicious/noExplicitAny: Dynamic require\n let vueCompiler: any;\n try {\n vueCompiler = require('@vue/compiler-sfc');\n } catch (_e) {\n // Not a Vue project\n }\n\n host.getSourceFile = (\n fileName,\n languageVersion,\n onError,\n shouldCreateNewSourceFile,\n ) => {\n if (fileName.endsWith('.vue')) {\n const content = ts.sys.readFile(fileName);\n if (content) {\n let scriptContent = '';\n if (vueCompiler) {\n const parsed = vueCompiler.parse(content);\n const script = parsed.descriptor.script;\n const scriptSetup = parsed.descriptor.scriptSetup;\n if (script) scriptContent += `${script.content}\\n`;\n if (scriptSetup) scriptContent += `${scriptSetup.content}\\n`;\n } else {\n const match = content.match(/<script[^>]*>(.*?)<\\/script>/s);\n if (match) scriptContent = match[1];\n }\n return ts.createSourceFile(\n fileName,\n scriptContent,\n languageVersion,\n true,\n ts.ScriptKind.TS,\n );\n }\n }\n\n if (fileName.endsWith('.svelte')) {\n const content = ts.sys.readFile(fileName);\n if (content) {\n let scriptContent = '';\n const match = content.match(/<script[^>]*>(.*?)<\\/script>/s);\n if (match) scriptContent = match[1];\n return ts.createSourceFile(\n fileName,\n scriptContent,\n languageVersion,\n true,\n ts.ScriptKind.TS,\n );\n }\n }\n\n return originalGetSourceFile(\n fileName,\n languageVersion,\n onError,\n shouldCreateNewSourceFile,\n );\n };\n\n program = ts.createProgram({\n rootNames: parsedCommandLine.fileNames,\n options: compilerOptions,\n host: host,\n });\n\n // Force the TypeScript compiler to bind the AST and populate .parent pointers\n program.getTypeChecker();\n } else {\n throw new Error('Could not find tsconfig.json');\n }\n\n const getSourceFiles = () =>\n program\n .getSourceFiles()\n .filter(\n (sf) => !sf.isDeclarationFile && !sf.fileName.includes('node_modules'),\n );\n\n return {\n getFiles: (queryOptions?: FileQueryOptions) => {\n return locateFiles(getSourceFiles(), program, queryOptions);\n },\n\n getClasses: (queryOptions?: ClassQueryOptions) => {\n const allClasses: ts.ClassDeclaration[] = [];\n for (const sf of getSourceFiles()) {\n const visit = (node: ts.Node) => {\n if (ts.isClassDeclaration(node)) {\n allClasses.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return locateClasses(allClasses, program, queryOptions);\n },\n\n layeredArchitecture: () => {\n let data = createLayeredArchitecture(getSourceFiles(), program);\n const api = {\n layer: (name: string, folderPattern: string) => {\n data = layer(data, name, folderPattern);\n return api;\n },\n whereLayer: (name: string) => {\n return {\n shouldNotBeAccessedByAnyLayer: () => {\n data = layerShouldNotBeAccessedByAnyLayer(data, name);\n return api;\n },\n shouldOnlyBeAccessedBy: (...allowedLayers: string[]) => {\n data = layerShouldOnlyBeAccessedBy(data, name, allowedLayers);\n return api;\n },\n };\n },\n check: () => checkLayeredArchitecture(data),\n get data() {\n return data;\n },\n };\n return api;\n },\n\n getFunctions: (queryOptions?: FunctionQueryOptions) => {\n const allFunctions: ts.FunctionLikeDeclaration[] = [];\n for (const sf of getSourceFiles()) {\n const visit = (node: ts.Node) => {\n if (\n ts.isFunctionDeclaration(node) ||\n ts.isMethodDeclaration(node) ||\n ts.isArrowFunction(node)\n ) {\n allFunctions.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return locateFunctions(allFunctions, program, queryOptions);\n },\n\n getProperties: (queryOptions?: PropertyQueryOptions) => {\n const allProperties: ts.PropertyDeclaration[] = [];\n for (const sf of getSourceFiles()) {\n const visit = (node: ts.Node) => {\n if (ts.isPropertyDeclaration(node)) {\n allProperties.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return locateProperties(allProperties, program, queryOptions);\n },\n\n getSlices: (pattern: string) => {\n return locateSlices(getSourceFiles(), program, pattern);\n },\n };\n}\n","import * as ts from 'typescript';\nimport type { RuleResult } from '../types';\nimport type { PropertyLocatorData } from './types';\n\nexport function propertyCheckBeReadonly(\n locator: PropertyLocatorData,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n for (const p of locator.properties) {\n const name = ts.isIdentifier(p.name) ? p.name.text : 'Anonymous Property';\n const modifiers = ts.canHaveModifiers(p) ? ts.getModifiers(p) : undefined;\n const matches = modifiers?.some(\n (m: ts.Modifier) => m.kind === ts.SyntaxKind.ReadonlyKeyword,\n );\n\n if (isNot && matches) {\n violations.push(`Property ${name} is readonly, but it shouldn't be.`);\n } else if (!isNot && !matches) {\n violations.push(`Property ${name} is not readonly, but it should be.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n}\n","import * as ts from 'typescript';\nimport type { RuleResult } from '../types';\nimport type { SliceLocatorData } from './types';\n\nexport function sliceCheckBeFreeOfCycles(\n locator: SliceLocatorData,\n isNot: boolean,\n): RuleResult {\n const graph: Map<string, Set<string>> = new Map();\n for (const slice of locator.sliceIds) {\n graph.set(slice, new Set());\n }\n\n for (const [sliceId, files] of locator.sliceFiles.entries()) {\n for (const sf of files) {\n ts.forEachChild(sf, (node) => {\n if (\n ts.isImportDeclaration(node) &&\n node.moduleSpecifier &&\n ts.isStringLiteral(node.moduleSpecifier)\n ) {\n const importPath = node.moduleSpecifier.text;\n const resolved = ts.resolveModuleName(\n importPath,\n sf.fileName,\n locator.program.getCompilerOptions(),\n ts.sys,\n );\n if (resolved.resolvedModule?.resolvedFileName) {\n const targetMatch = resolved.resolvedModule.resolvedFileName.match(\n locator.slicePattern,\n );\n if (targetMatch?.[1]) {\n const targetSlice = targetMatch[1];\n if (\n targetSlice !== sliceId &&\n locator.sliceIds.has(targetSlice)\n ) {\n graph.get(sliceId)?.add(targetSlice);\n }\n }\n }\n }\n });\n }\n }\n\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n const violations: string[] = [];\n\n const dfs = (node: string, path: string[]): boolean => {\n visited.add(node);\n recursionStack.add(node);\n\n for (const neighbor of graph.get(node) || []) {\n if (!visited.has(neighbor)) {\n if (dfs(neighbor, [...path, neighbor])) return true;\n } else if (recursionStack.has(neighbor)) {\n violations.push(\n `Cycle detected between slices: ${path.join(' -> ')} -> ${neighbor}`,\n );\n return true;\n }\n }\n\n recursionStack.delete(node);\n return false;\n };\n\n for (const slice of locator.sliceIds) {\n if (!visited.has(slice)) {\n dfs(slice, [slice]);\n }\n }\n\n if (isNot) {\n return {\n pass: violations.length > 0,\n message: () =>\n violations.length > 0\n ? ''\n : 'Expected cycles between slices but found none.',\n };\n } else {\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport type { RuleResult } from '../types';\nimport type { SliceLocatorData } from './types';\n\nexport function sliceCheckHaveMaxDistanceFromMainSequence(\n locator: SliceLocatorData,\n max: number,\n isNot: boolean,\n): RuleResult {\n const violations: string[] = [];\n\n const ceMap = new Map<string, Set<string>>(); // Slices this slice depends on\n const caMap = new Map<string, Set<string>>(); // Slices depending on this slice\n\n for (const slice of locator.sliceIds) {\n ceMap.set(slice, new Set());\n caMap.set(slice, new Set());\n }\n\n for (const [sliceId, files] of locator.sliceFiles.entries()) {\n for (const sf of files) {\n ts.forEachChild(sf, (node) => {\n if (\n ts.isImportDeclaration(node) &&\n node.moduleSpecifier &&\n ts.isStringLiteral(node.moduleSpecifier)\n ) {\n const importPath = node.moduleSpecifier.text;\n const resolved = ts.resolveModuleName(\n importPath,\n sf.fileName,\n locator.program.getCompilerOptions(),\n ts.sys,\n );\n if (resolved.resolvedModule?.resolvedFileName) {\n const targetMatch = resolved.resolvedModule.resolvedFileName.match(\n locator.slicePattern,\n );\n if (targetMatch?.[1]) {\n const targetSlice = targetMatch[1];\n if (\n targetSlice !== sliceId &&\n locator.sliceIds.has(targetSlice)\n ) {\n ceMap.get(sliceId)?.add(targetSlice);\n caMap.get(targetSlice)?.add(sliceId);\n }\n }\n }\n }\n });\n }\n }\n\n for (const sliceId of locator.sliceIds) {\n const ce = ceMap.get(sliceId)?.size;\n const ca = caMap.get(sliceId)?.size;\n\n // biome-ignore lint/style/noNonNullAssertion: Safe map lookup\n const files = locator.sliceFiles.get(sliceId)!;\n let na = 0; // abstract classes + interfaces\n let nc = 0; // all classes + interfaces\n\n for (const sf of files) {\n const visit = (node: ts.Node) => {\n if (ts.isClassDeclaration(node)) {\n nc++;\n const modifiers = ts.canHaveModifiers(node)\n ? ts.getModifiers(node)\n : undefined;\n if (\n modifiers?.some((m) => m.kind === ts.SyntaxKind.AbstractKeyword)\n ) {\n na++;\n }\n } else if (ts.isInterfaceDeclaration(node)) {\n nc++;\n na++;\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n\n const I = ce + ca === 0 ? 0 : ce / (ca + ce);\n const A = nc === 0 ? 0 : na / nc;\n\n const D = Math.abs(A + I - 1);\n const exceeds = D > max;\n\n if (isNot && exceeds) {\n violations.push(\n `Slice ${sliceId} has a Distance from the Main Sequence of ${D.toFixed(2)}, which exceeds the maximum of ${max}, but it shouldn't.`,\n );\n } else if (!isNot && exceeds) {\n violations.push(\n `Slice ${sliceId} has a Distance from the Main Sequence of ${D.toFixed(2)}, which exceeds the maximum of ${max}.`,\n );\n }\n }\n\n return {\n pass: isNot ? violations.length > 0 : violations.length === 0,\n message: () =>\n violations.join('\\n') ||\n (isNot\n ? 'Expected some slices to exceed maximum distance from main sequence, but none did.'\n : ''),\n };\n}\n","import { expect } from 'vitest';\nimport { classCheckExtendClass } from '../core/classes/classCheckExtendClass';\nimport { classCheckHaveMaxCyclomaticComplexity } from '../core/classes/classCheckHaveMaxCyclomaticComplexity';\nimport { classCheckHaveModifier } from '../core/classes/classCheckHaveModifier';\nimport { classCheckHaveNameMatchingFileName } from '../core/classes/classCheckHaveNameMatchingFileName';\nimport { classCheckImplementInterface } from '../core/classes/classCheckImplementInterface';\nimport { classCheckMatchNamePattern } from '../core/classes/classCheckMatchNamePattern';\nimport { classCheckResideInFolder } from '../core/classes/classCheckResideInFolder';\nimport { checkDependOnFilesInFolder } from '../core/files/checkDependOnFilesInFolder';\nimport { fileCheckBeFreeOfCycles } from '../core/files/fileCheckBeFreeOfCycles';\nimport { fileCheckHaveMaxCyclomaticComplexity } from '../core/files/fileCheckHaveMaxCyclomaticComplexity';\nimport { fileCheckHaveMaxExportedFunctions } from '../core/files/fileCheckHaveMaxExportedFunctions';\nimport { fileCheckHaveMinMaintainabilityIndex } from '../core/files/fileCheckHaveMinMaintainabilityIndex';\nimport { fileCheckMatchNamePattern } from '../core/files/fileCheckMatchNamePattern';\nimport { functionCheckHaveExplicitReturnType } from '../core/functions/functionCheckHaveExplicitReturnType';\nimport { functionCheckHaveMaxCyclomaticComplexity } from '../core/functions/functionCheckHaveMaxCyclomaticComplexity';\nimport { functionCheckHaveMinMaintainabilityIndex } from '../core/functions/functionCheckHaveMinMaintainabilityIndex';\nimport { functionCheckHaveModifier } from '../core/functions/functionCheckHaveModifier';\nimport { functionCheckHaveNameMatchingFileName } from '../core/functions/functionCheckHaveNameMatchingFileName';\nimport { functionCheckMatchNamePattern } from '../core/functions/functionCheckMatchNamePattern';\nimport { checkLayeredArchitecture } from '../core/layers/checkLayeredArchitecture';\n\nimport { propertyCheckBeReadonly } from '../core/properties/propertyCheckBeReadonly';\n\nimport { sliceCheckBeFreeOfCycles } from '../core/slices/sliceCheckBeFreeOfCycles';\nimport { sliceCheckHaveMaxDistanceFromMainSequence } from '../core/slices/sliceCheckHaveMaxDistanceFromMainSequence';\nimport type { LocatorData, RuleResult } from '../core/types';\n\nexport function setupMatchers() {\n expect.extend({\n // biome-ignore lint/suspicious/noExplicitAny: Matcher signature\n toPass(received: any) {\n let result: RuleResult;\n\n if (received?.data && received.data.type === 'LayeredArchitecture') {\n result = checkLayeredArchitecture(received.data);\n } else {\n result = received as RuleResult;\n }\n\n const { pass, message } = result;\n return {\n pass: this.isNot ? !pass : pass,\n message: pass ? () => 'Expected rule not to pass' : () => message(),\n };\n },\n\n toResideInFolder(received: LocatorData, folder: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckResideInFolder(received, folder, this.isNot);\n } else {\n throw new Error(\n `toResideInFolder matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveModifier(received: LocatorData, modifier: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckHaveModifier(received, modifier, this.isNot);\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckHaveModifier(received, modifier, this.isNot);\n } else {\n throw new Error(\n `toHaveModifier matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toExtendClass(received: LocatorData, className: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckExtendClass(received, className, this.isNot);\n } else {\n throw new Error(\n `toExtendClass matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toImplementInterface(received: LocatorData, interfaceName: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckImplementInterface(\n received,\n interfaceName,\n this.isNot,\n );\n } else {\n throw new Error(\n `toImplementInterface matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveExplicitReturnType(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'FunctionLocator') {\n result = functionCheckHaveExplicitReturnType(received, this.isNot);\n } else {\n throw new Error(\n `toHaveExplicitReturnType matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toBeReadonly(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'PropertyLocator') {\n result = propertyCheckBeReadonly(received, this.isNot);\n } else {\n throw new Error(\n `toBeReadonly matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toDependOnFilesInFolder(received: LocatorData, folder: string) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = checkDependOnFilesInFolder(received, folder, this.isNot);\n } else {\n throw new Error(\n `toDependOnFilesInFolder matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toBeFreeOfCycles(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckBeFreeOfCycles(received, this.isNot);\n } else if (received.type === 'SliceLocator') {\n result = sliceCheckBeFreeOfCycles(received, this.isNot);\n } else {\n throw new Error(\n `toBeFreeOfCycles matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toMatchNamePattern(received: LocatorData, pattern: string | RegExp) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckMatchNamePattern(received, pattern, this.isNot);\n } else if (received.type === 'ClassLocator') {\n result = classCheckMatchNamePattern(received, pattern, this.isNot);\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckMatchNamePattern(received, pattern, this.isNot);\n } else {\n throw new Error(\n `toMatchNamePattern matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMaxCyclomaticComplexity(received: LocatorData, max: number) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckHaveMaxCyclomaticComplexity(\n received,\n max,\n this.isNot,\n );\n } else if (received.type === 'ClassLocator') {\n result = classCheckHaveMaxCyclomaticComplexity(\n received,\n max,\n this.isNot,\n );\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckHaveMaxCyclomaticComplexity(\n received,\n max,\n this.isNot,\n );\n } else {\n throw new Error(\n `toHaveMaxCyclomaticComplexity matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMinMaintainabilityIndex(received: LocatorData, min: number) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckHaveMinMaintainabilityIndex(\n received,\n min,\n this.isNot,\n );\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckHaveMinMaintainabilityIndex(\n received,\n min,\n this.isNot,\n );\n } else {\n throw new Error(\n `toHaveMinMaintainabilityIndex matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMaxDistanceFromMainSequence(received: LocatorData, max: number) {\n let result: RuleResult;\n if (received.type === 'SliceLocator') {\n result = sliceCheckHaveMaxDistanceFromMainSequence(\n received,\n max,\n this.isNot,\n );\n } else {\n throw new Error(\n `toHaveMaxDistanceFromMainSequence matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveNameMatchingFileName(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'FunctionLocator') {\n result = functionCheckHaveNameMatchingFileName(received, this.isNot);\n } else if (received.type === 'ClassLocator') {\n result = classCheckHaveNameMatchingFileName(received, this.isNot);\n } else {\n throw new Error(\n `toHaveNameMatchingFileName matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMaxExportedFunctions(received: LocatorData, max: number) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckHaveMaxExportedFunctions(received, max, this.isNot);\n } else {\n throw new Error(\n `toHaveMaxExportedFunctions matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n });\n}\n\ndeclare module 'vitest' {\n // biome-ignore lint/suspicious/noExplicitAny: Matcher signature\n interface Assertion<T = any> {\n toPass(): void;\n toResideInFolder(folder: string): void;\n toHaveModifier(\n modifier:\n | 'export'\n | 'default'\n | 'abstract'\n | 'async'\n | 'private'\n | 'public',\n ): void;\n toExtendClass(className: string): void;\n toImplementInterface(interfaceName: string): void;\n toHaveExplicitReturnType(): void;\n toBeReadonly(): void;\n toDependOnFilesInFolder(folder: string): void;\n toBeFreeOfCycles(): void;\n toMatchNamePattern(pattern: string | RegExp): void;\n toHaveMaxCyclomaticComplexity(max: number): void;\n toHaveMinMaintainabilityIndex(min: number): void;\n toHaveMaxDistanceFromMainSequence(max: number): void;\n toHaveNameMatchingFileName(): void;\n toHaveMaxExportedFunctions(max: number): void;\n }\n}\n"],"mappings":"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"}
|