@nielspeter/eess-ts 0.1.0
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/LICENSE +21 -0
- package/README.md +364 -0
- package/dist/builders/call-rule-builder.d.ts +199 -0
- package/dist/builders/call-rule-builder.d.ts.map +1 -0
- package/dist/builders/call-rule-builder.js +254 -0
- package/dist/builders/call-rule-builder.js.map +1 -0
- package/dist/builders/class-rule-builder.d.ts +136 -0
- package/dist/builders/class-rule-builder.d.ts.map +1 -0
- package/dist/builders/class-rule-builder.js +253 -0
- package/dist/builders/class-rule-builder.js.map +1 -0
- package/dist/builders/cross-layer-builder.d.ts +96 -0
- package/dist/builders/cross-layer-builder.d.ts.map +1 -0
- package/dist/builders/cross-layer-builder.js +172 -0
- package/dist/builders/cross-layer-builder.js.map +1 -0
- package/dist/builders/function-rule-builder.d.ts +198 -0
- package/dist/builders/function-rule-builder.d.ts.map +1 -0
- package/dist/builders/function-rule-builder.js +287 -0
- package/dist/builders/function-rule-builder.js.map +1 -0
- package/dist/builders/jsx-rule-builder.d.ts +113 -0
- package/dist/builders/jsx-rule-builder.d.ts.map +1 -0
- package/dist/builders/jsx-rule-builder.js +150 -0
- package/dist/builders/jsx-rule-builder.js.map +1 -0
- package/dist/builders/module-rule-builder.d.ts +159 -0
- package/dist/builders/module-rule-builder.d.ts.map +1 -0
- package/dist/builders/module-rule-builder.js +237 -0
- package/dist/builders/module-rule-builder.js.map +1 -0
- package/dist/builders/scoped-function-rule-builder.d.ts +21 -0
- package/dist/builders/scoped-function-rule-builder.d.ts.map +1 -0
- package/dist/builders/scoped-function-rule-builder.js +26 -0
- package/dist/builders/scoped-function-rule-builder.js.map +1 -0
- package/dist/builders/slice-rule-builder.d.ts +85 -0
- package/dist/builders/slice-rule-builder.d.ts.map +1 -0
- package/dist/builders/slice-rule-builder.js +134 -0
- package/dist/builders/slice-rule-builder.js.map +1 -0
- package/dist/builders/type-rule-builder.d.ts +103 -0
- package/dist/builders/type-rule-builder.d.ts.map +1 -0
- package/dist/builders/type-rule-builder.js +170 -0
- package/dist/builders/type-rule-builder.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/baseline.d.ts +11 -0
- package/dist/cli/commands/baseline.d.ts.map +1 -0
- package/dist/cli/commands/baseline.js +16 -0
- package/dist/cli/commands/baseline.js.map +1 -0
- package/dist/cli/commands/check.d.ts +21 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +94 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/explain.d.ts +9 -0
- package/dist/cli/commands/explain.d.ts.map +1 -0
- package/dist/cli/commands/explain.js +49 -0
- package/dist/cli/commands/explain.js.map +1 -0
- package/dist/cli/config.d.ts +31 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +20 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +21 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +168 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/load-rules.d.ts +20 -0
- package/dist/cli/load-rules.d.ts.map +1 -0
- package/dist/cli/load-rules.js +97 -0
- package/dist/cli/load-rules.js.map +1 -0
- package/dist/cli/resolve-config.d.ts +11 -0
- package/dist/cli/resolve-config.d.ts.map +1 -0
- package/dist/cli/resolve-config.js +61 -0
- package/dist/cli/resolve-config.js.map +1 -0
- package/dist/cli/watch.d.ts +49 -0
- package/dist/cli/watch.d.ts.map +1 -0
- package/dist/cli/watch.js +138 -0
- package/dist/cli/watch.js.map +1 -0
- package/dist/conditions/body-analysis-function.d.ts +23 -0
- package/dist/conditions/body-analysis-function.d.ts.map +1 -0
- package/dist/conditions/body-analysis-function.js +103 -0
- package/dist/conditions/body-analysis-function.js.map +1 -0
- package/dist/conditions/body-analysis-module.d.ts +27 -0
- package/dist/conditions/body-analysis-module.d.ts.map +1 -0
- package/dist/conditions/body-analysis-module.js +99 -0
- package/dist/conditions/body-analysis-module.js.map +1 -0
- package/dist/conditions/body-analysis.d.ts +34 -0
- package/dist/conditions/body-analysis.d.ts.map +1 -0
- package/dist/conditions/body-analysis.js +95 -0
- package/dist/conditions/body-analysis.js.map +1 -0
- package/dist/conditions/call.d.ts +62 -0
- package/dist/conditions/call.d.ts.map +1 -0
- package/dist/conditions/call.js +267 -0
- package/dist/conditions/call.js.map +1 -0
- package/dist/conditions/catch-analysis.d.ts +31 -0
- package/dist/conditions/catch-analysis.d.ts.map +1 -0
- package/dist/conditions/catch-analysis.js +78 -0
- package/dist/conditions/catch-analysis.js.map +1 -0
- package/dist/conditions/class.d.ts +33 -0
- package/dist/conditions/class.d.ts.map +1 -0
- package/dist/conditions/class.js +110 -0
- package/dist/conditions/class.js.map +1 -0
- package/dist/conditions/cross-layer.d.ts +28 -0
- package/dist/conditions/cross-layer.d.ts.map +1 -0
- package/dist/conditions/cross-layer.js +105 -0
- package/dist/conditions/cross-layer.js.map +1 -0
- package/dist/conditions/dependency.d.ts +73 -0
- package/dist/conditions/dependency.d.ts.map +1 -0
- package/dist/conditions/dependency.js +177 -0
- package/dist/conditions/dependency.js.map +1 -0
- package/dist/conditions/exports.d.ts +33 -0
- package/dist/conditions/exports.d.ts.map +1 -0
- package/dist/conditions/exports.js +101 -0
- package/dist/conditions/exports.js.map +1 -0
- package/dist/conditions/function.d.ts +79 -0
- package/dist/conditions/function.d.ts.map +1 -0
- package/dist/conditions/function.js +167 -0
- package/dist/conditions/function.js.map +1 -0
- package/dist/conditions/helpers.d.ts +14 -0
- package/dist/conditions/helpers.d.ts.map +1 -0
- package/dist/conditions/helpers.js +26 -0
- package/dist/conditions/helpers.js.map +1 -0
- package/dist/conditions/jsx.d.ts +40 -0
- package/dist/conditions/jsx.d.ts.map +1 -0
- package/dist/conditions/jsx.js +133 -0
- package/dist/conditions/jsx.js.map +1 -0
- package/dist/conditions/members.d.ts +74 -0
- package/dist/conditions/members.d.ts.map +1 -0
- package/dist/conditions/members.js +224 -0
- package/dist/conditions/members.js.map +1 -0
- package/dist/conditions/pattern.d.ts +20 -0
- package/dist/conditions/pattern.d.ts.map +1 -0
- package/dist/conditions/pattern.js +108 -0
- package/dist/conditions/pattern.js.map +1 -0
- package/dist/conditions/reverse-dependency.d.ts +28 -0
- package/dist/conditions/reverse-dependency.d.ts.map +1 -0
- package/dist/conditions/reverse-dependency.js +275 -0
- package/dist/conditions/reverse-dependency.js.map +1 -0
- package/dist/conditions/slice.d.ts +49 -0
- package/dist/conditions/slice.d.ts.map +1 -0
- package/dist/conditions/slice.js +153 -0
- package/dist/conditions/slice.js.map +1 -0
- package/dist/conditions/structural.d.ts +58 -0
- package/dist/conditions/structural.d.ts.map +1 -0
- package/dist/conditions/structural.js +102 -0
- package/dist/conditions/structural.js.map +1 -0
- package/dist/conditions/type-level.d.ts +29 -0
- package/dist/conditions/type-level.d.ts.map +1 -0
- package/dist/conditions/type-level.js +48 -0
- package/dist/conditions/type-level.js.map +1 -0
- package/dist/core/import-options.d.ts +32 -0
- package/dist/core/import-options.d.ts.map +1 -0
- package/dist/core/import-options.js +29 -0
- package/dist/core/import-options.js.map +1 -0
- package/dist/core/module-dependencies.d.ts +28 -0
- package/dist/core/module-dependencies.d.ts.map +1 -0
- package/dist/core/module-dependencies.js +35 -0
- package/dist/core/module-dependencies.js.map +1 -0
- package/dist/core/pair-condition.d.ts +10 -0
- package/dist/core/pair-condition.d.ts.map +1 -0
- package/dist/core/pair-condition.js +2 -0
- package/dist/core/pair-condition.js.map +1 -0
- package/dist/core/project.d.ts +68 -0
- package/dist/core/project.d.ts.map +1 -0
- package/dist/core/project.js +127 -0
- package/dist/core/project.js.map +1 -0
- package/dist/core/type-matcher.d.ts +10 -0
- package/dist/core/type-matcher.d.ts.map +1 -0
- package/dist/core/type-matcher.js +2 -0
- package/dist/core/type-matcher.js.map +1 -0
- package/dist/core/violation.d.ts +38 -0
- package/dist/core/violation.d.ts.map +1 -0
- package/dist/core/violation.js +130 -0
- package/dist/core/violation.js.map +1 -0
- package/dist/graphql/index.d.ts +76 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +108 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/graphql/resolver-rule-builder.d.ts +75 -0
- package/dist/graphql/resolver-rule-builder.d.ts.map +1 -0
- package/dist/graphql/resolver-rule-builder.js +146 -0
- package/dist/graphql/resolver-rule-builder.js.map +1 -0
- package/dist/graphql/schema-conditions.d.ts +31 -0
- package/dist/graphql/schema-conditions.d.ts.map +1 -0
- package/dist/graphql/schema-conditions.js +119 -0
- package/dist/graphql/schema-conditions.js.map +1 -0
- package/dist/graphql/schema-loader.d.ts +75 -0
- package/dist/graphql/schema-loader.d.ts.map +1 -0
- package/dist/graphql/schema-loader.js +113 -0
- package/dist/graphql/schema-loader.js.map +1 -0
- package/dist/graphql/schema-predicates.d.ts +42 -0
- package/dist/graphql/schema-predicates.d.ts.map +1 -0
- package/dist/graphql/schema-predicates.js +74 -0
- package/dist/graphql/schema-predicates.js.map +1 -0
- package/dist/graphql/schema-rule-builder.d.ts +74 -0
- package/dist/graphql/schema-rule-builder.d.ts.map +1 -0
- package/dist/graphql/schema-rule-builder.js +188 -0
- package/dist/graphql/schema-rule-builder.js.map +1 -0
- package/dist/helpers/body-traversal.d.ts +58 -0
- package/dist/helpers/body-traversal.d.ts.map +1 -0
- package/dist/helpers/body-traversal.js +180 -0
- package/dist/helpers/body-traversal.js.map +1 -0
- package/dist/helpers/callback-extractor.d.ts +28 -0
- package/dist/helpers/callback-extractor.d.ts.map +1 -0
- package/dist/helpers/callback-extractor.js +159 -0
- package/dist/helpers/callback-extractor.js.map +1 -0
- package/dist/helpers/complexity.d.ts +26 -0
- package/dist/helpers/complexity.d.ts.map +1 -0
- package/dist/helpers/complexity.js +64 -0
- package/dist/helpers/complexity.js.map +1 -0
- package/dist/helpers/matchers.d.ts +206 -0
- package/dist/helpers/matchers.d.ts.map +1 -0
- package/dist/helpers/matchers.js +470 -0
- package/dist/helpers/matchers.js.map +1 -0
- package/dist/helpers/pattern.d.ts +37 -0
- package/dist/helpers/pattern.d.ts.map +1 -0
- package/dist/helpers/pattern.js +22 -0
- package/dist/helpers/pattern.js.map +1 -0
- package/dist/helpers/slice-graph.d.ts +32 -0
- package/dist/helpers/slice-graph.d.ts.map +1 -0
- package/dist/helpers/slice-graph.js +89 -0
- package/dist/helpers/slice-graph.js.map +1 -0
- package/dist/helpers/tarjan.d.ts +21 -0
- package/dist/helpers/tarjan.d.ts.map +1 -0
- package/dist/helpers/tarjan.js +71 -0
- package/dist/helpers/tarjan.js.map +1 -0
- package/dist/helpers/type-matchers.d.ts +67 -0
- package/dist/helpers/type-matchers.d.ts.map +1 -0
- package/dist/helpers/type-matchers.js +108 -0
- package/dist/helpers/type-matchers.js.map +1 -0
- package/dist/helpers/within.d.ts +41 -0
- package/dist/helpers/within.d.ts.map +1 -0
- package/dist/helpers/within.js +32 -0
- package/dist/helpers/within.js.map +1 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +116 -0
- package/dist/index.js.map +1 -0
- package/dist/models/arch-call.d.ts +83 -0
- package/dist/models/arch-call.d.ts.map +1 -0
- package/dist/models/arch-call.js +90 -0
- package/dist/models/arch-call.js.map +1 -0
- package/dist/models/arch-function.d.ts +76 -0
- package/dist/models/arch-function.d.ts.map +1 -0
- package/dist/models/arch-function.js +122 -0
- package/dist/models/arch-function.js.map +1 -0
- package/dist/models/arch-jsx-element.d.ts +75 -0
- package/dist/models/arch-jsx-element.d.ts.map +1 -0
- package/dist/models/arch-jsx-element.js +231 -0
- package/dist/models/arch-jsx-element.js.map +1 -0
- package/dist/models/cross-layer.d.ts +15 -0
- package/dist/models/cross-layer.d.ts.map +1 -0
- package/dist/models/cross-layer.js +2 -0
- package/dist/models/cross-layer.js.map +1 -0
- package/dist/models/slice.d.ts +60 -0
- package/dist/models/slice.d.ts.map +1 -0
- package/dist/models/slice.js +89 -0
- package/dist/models/slice.js.map +1 -0
- package/dist/predicates/call.d.ts +49 -0
- package/dist/predicates/call.d.ts.map +1 -0
- package/dist/predicates/call.js +115 -0
- package/dist/predicates/call.js.map +1 -0
- package/dist/predicates/class.d.ts +42 -0
- package/dist/predicates/class.d.ts.map +1 -0
- package/dist/predicates/class.js +83 -0
- package/dist/predicates/class.js.map +1 -0
- package/dist/predicates/function.d.ts +81 -0
- package/dist/predicates/function.d.ts.map +1 -0
- package/dist/predicates/function.js +157 -0
- package/dist/predicates/function.js.map +1 -0
- package/dist/predicates/identity.d.ts +55 -0
- package/dist/predicates/identity.d.ts.map +1 -0
- package/dist/predicates/identity.js +96 -0
- package/dist/predicates/identity.js.map +1 -0
- package/dist/predicates/index.d.ts +4 -0
- package/dist/predicates/index.d.ts.map +1 -0
- package/dist/predicates/index.js +3 -0
- package/dist/predicates/index.js.map +1 -0
- package/dist/predicates/jsx.d.ts +41 -0
- package/dist/predicates/jsx.d.ts.map +1 -0
- package/dist/predicates/jsx.js +84 -0
- package/dist/predicates/jsx.js.map +1 -0
- package/dist/predicates/metrics.d.ts +30 -0
- package/dist/predicates/metrics.d.ts.map +1 -0
- package/dist/predicates/metrics.js +65 -0
- package/dist/predicates/metrics.js.map +1 -0
- package/dist/predicates/module.d.ts +44 -0
- package/dist/predicates/module.d.ts.map +1 -0
- package/dist/predicates/module.js +70 -0
- package/dist/predicates/module.js.map +1 -0
- package/dist/predicates/type.d.ts +48 -0
- package/dist/predicates/type.d.ts.map +1 -0
- package/dist/predicates/type.js +107 -0
- package/dist/predicates/type.js.map +1 -0
- package/dist/presets/boundaries.d.ts +19 -0
- package/dist/presets/boundaries.d.ts.map +1 -0
- package/dist/presets/boundaries.js +93 -0
- package/dist/presets/boundaries.js.map +1 -0
- package/dist/presets/data-layer.d.ts +20 -0
- package/dist/presets/data-layer.d.ts.map +1 -0
- package/dist/presets/data-layer.js +30 -0
- package/dist/presets/data-layer.js.map +1 -0
- package/dist/presets/index.d.ts +9 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +5 -0
- package/dist/presets/index.js.map +1 -0
- package/dist/presets/layered.d.ts +21 -0
- package/dist/presets/layered.d.ts.map +1 -0
- package/dist/presets/layered.js +103 -0
- package/dist/presets/layered.js.map +1 -0
- package/dist/presets/shared.d.ts +3 -0
- package/dist/presets/shared.d.ts.map +1 -0
- package/dist/presets/shared.js +5 -0
- package/dist/presets/shared.js.map +1 -0
- package/dist/rules/architecture.d.ts +10 -0
- package/dist/rules/architecture.d.ts.map +1 -0
- package/dist/rules/architecture.js +14 -0
- package/dist/rules/architecture.js.map +1 -0
- package/dist/rules/code-quality.d.ts +55 -0
- package/dist/rules/code-quality.d.ts.map +1 -0
- package/dist/rules/code-quality.js +116 -0
- package/dist/rules/code-quality.js.map +1 -0
- package/dist/rules/dependencies.d.ts +32 -0
- package/dist/rules/dependencies.d.ts.map +1 -0
- package/dist/rules/dependencies.js +37 -0
- package/dist/rules/dependencies.js.map +1 -0
- package/dist/rules/errors.d.ts +31 -0
- package/dist/rules/errors.d.ts.map +1 -0
- package/dist/rules/errors.js +97 -0
- package/dist/rules/errors.js.map +1 -0
- package/dist/rules/hygiene.d.ts +54 -0
- package/dist/rules/hygiene.d.ts.map +1 -0
- package/dist/rules/hygiene.js +62 -0
- package/dist/rules/hygiene.js.map +1 -0
- package/dist/rules/metrics-function.d.ts +45 -0
- package/dist/rules/metrics-function.d.ts.map +1 -0
- package/dist/rules/metrics-function.js +87 -0
- package/dist/rules/metrics-function.js.map +1 -0
- package/dist/rules/metrics.d.ts +64 -0
- package/dist/rules/metrics.d.ts.map +1 -0
- package/dist/rules/metrics.js +157 -0
- package/dist/rules/metrics.js.map +1 -0
- package/dist/rules/naming.d.ts +24 -0
- package/dist/rules/naming.d.ts.map +1 -0
- package/dist/rules/naming.js +51 -0
- package/dist/rules/naming.js.map +1 -0
- package/dist/rules/security.d.ts +59 -0
- package/dist/rules/security.d.ts.map +1 -0
- package/dist/rules/security.js +92 -0
- package/dist/rules/security.js.map +1 -0
- package/dist/rules/typescript.d.ts +73 -0
- package/dist/rules/typescript.d.ts.map +1 -0
- package/dist/rules/typescript.js +105 -0
- package/dist/rules/typescript.js.map +1 -0
- package/dist/smells/duplicate-bodies.d.ts +24 -0
- package/dist/smells/duplicate-bodies.d.ts.map +1 -0
- package/dist/smells/duplicate-bodies.js +131 -0
- package/dist/smells/duplicate-bodies.js.map +1 -0
- package/dist/smells/fingerprint.d.ts +27 -0
- package/dist/smells/fingerprint.d.ts.map +1 -0
- package/dist/smells/fingerprint.js +50 -0
- package/dist/smells/fingerprint.js.map +1 -0
- package/dist/smells/inconsistent-siblings.d.ts +21 -0
- package/dist/smells/inconsistent-siblings.d.ts.map +1 -0
- package/dist/smells/inconsistent-siblings.js +135 -0
- package/dist/smells/inconsistent-siblings.js.map +1 -0
- package/dist/smells/index.d.ts +12 -0
- package/dist/smells/index.d.ts.map +1 -0
- package/dist/smells/index.js +15 -0
- package/dist/smells/index.js.map +1 -0
- package/dist/smells/smell-builder.d.ts +37 -0
- package/dist/smells/smell-builder.d.ts.map +1 -0
- package/dist/smells/smell-builder.js +51 -0
- package/dist/smells/smell-builder.js.map +1 -0
- package/package.json +121 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complexity.d.ts","sourceRoot":"","sources":["../../src/helpers/complexity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,IAAI,EAAE,MAAM,UAAU,CAAA;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA;AAsBhD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,CAoBnE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAEzD"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { SyntaxKind, Node } from 'ts-morph';
|
|
2
|
+
/** Decision-point SyntaxKinds that increment cyclomatic complexity */
|
|
3
|
+
const DECISION_KINDS = new Set([
|
|
4
|
+
SyntaxKind.IfStatement,
|
|
5
|
+
SyntaxKind.ConditionalExpression,
|
|
6
|
+
SyntaxKind.ForStatement,
|
|
7
|
+
SyntaxKind.ForInStatement,
|
|
8
|
+
SyntaxKind.ForOfStatement,
|
|
9
|
+
SyntaxKind.WhileStatement,
|
|
10
|
+
SyntaxKind.DoStatement,
|
|
11
|
+
SyntaxKind.CatchClause,
|
|
12
|
+
SyntaxKind.CaseClause,
|
|
13
|
+
]);
|
|
14
|
+
/** Logical operator tokens that add branching */
|
|
15
|
+
const LOGICAL_OPERATORS = new Set([
|
|
16
|
+
SyntaxKind.AmpersandAmpersandToken, // &&
|
|
17
|
+
SyntaxKind.BarBarToken, // ||
|
|
18
|
+
SyntaxKind.QuestionQuestionToken, // ??
|
|
19
|
+
]);
|
|
20
|
+
/**
|
|
21
|
+
* Calculate cyclomatic complexity (McCabe) for a function body.
|
|
22
|
+
*
|
|
23
|
+
* Accepts the body Node directly (from ArchFunction.getBody(),
|
|
24
|
+
* MethodDeclaration.getBody(), etc.).
|
|
25
|
+
*
|
|
26
|
+
* Complexity = 1 + number of decision points.
|
|
27
|
+
* Returns 1 for an undefined/empty body (one path through).
|
|
28
|
+
*/
|
|
29
|
+
export function cyclomaticComplexity(body) {
|
|
30
|
+
if (!body)
|
|
31
|
+
return 1;
|
|
32
|
+
let complexity = 1;
|
|
33
|
+
for (const descendant of body.getDescendants()) {
|
|
34
|
+
if (DECISION_KINDS.has(descendant.getKind())) {
|
|
35
|
+
complexity++;
|
|
36
|
+
}
|
|
37
|
+
// Count logical operators in binary expressions
|
|
38
|
+
if (Node.isBinaryExpression(descendant)) {
|
|
39
|
+
const opKind = descendant.getOperatorToken().getKind();
|
|
40
|
+
if (LOGICAL_OPERATORS.has(opKind)) {
|
|
41
|
+
complexity++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return complexity;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Count lines spanned by a node (from first line to last line, inclusive).
|
|
49
|
+
*
|
|
50
|
+
* This is a "span lines" count — it includes blank lines and comments
|
|
51
|
+
* within the node's range. This is consistent with how editors report
|
|
52
|
+
* function/class length, and avoids the fragility of text-based
|
|
53
|
+
* comment stripping.
|
|
54
|
+
*/
|
|
55
|
+
export function linesOfCode(node) {
|
|
56
|
+
return node.getEndLineNumber() - node.getStartLineNumber() + 1;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Count the number of methods on a class.
|
|
60
|
+
*/
|
|
61
|
+
export function methodCount(cls) {
|
|
62
|
+
return cls.getMethods().length;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=complexity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complexity.js","sourceRoot":"","sources":["../../src/helpers/complexity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAG3C,sEAAsE;AACtE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,UAAU,CAAC,WAAW;IACtB,UAAU,CAAC,qBAAqB;IAChC,UAAU,CAAC,YAAY;IACvB,UAAU,CAAC,cAAc;IACzB,UAAU,CAAC,cAAc;IACzB,UAAU,CAAC,cAAc;IACzB,UAAU,CAAC,WAAW;IACtB,UAAU,CAAC,WAAW;IACtB,UAAU,CAAC,UAAU;CACtB,CAAC,CAAA;AAEF,iDAAiD;AACjD,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,UAAU,CAAC,uBAAuB,EAAE,KAAK;IACzC,UAAU,CAAC,WAAW,EAAE,KAAK;IAC7B,UAAU,CAAC,qBAAqB,EAAE,KAAK;CACxC,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAsB;IACzD,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAA;IAEnB,IAAI,UAAU,GAAG,CAAC,CAAA;IAElB,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QAC/C,IAAI,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;YAC7C,UAAU,EAAE,CAAA;QACd,CAAC;QAED,gDAAgD;QAChD,IAAI,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC,OAAO,EAAE,CAAA;YACtD,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClC,UAAU,EAAE,CAAA;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,IAAU;IACpC,OAAO,IAAI,CAAC,gBAAgB,EAAE,GAAG,IAAI,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAA;AAChE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAqB;IAC/C,OAAO,GAAG,CAAC,UAAU,EAAE,CAAC,MAAM,CAAA;AAChC,CAAC"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { Node, SyntaxKind } from 'ts-morph';
|
|
2
|
+
/**
|
|
3
|
+
* A matcher that tests whether a ts-morph AST node matches a specific pattern.
|
|
4
|
+
*
|
|
5
|
+
* Matchers are created by helper functions (call, access, newExpr, expression)
|
|
6
|
+
* and consumed by body analysis conditions (contain, notContain, useInsteadOf).
|
|
7
|
+
*/
|
|
8
|
+
export interface ExpressionMatcher {
|
|
9
|
+
/** Human-readable description for violation messages */
|
|
10
|
+
readonly description: string;
|
|
11
|
+
/**
|
|
12
|
+
* The SyntaxKind(s) this matcher targets.
|
|
13
|
+
* Used to narrow the AST traversal — only nodes of these kinds are tested.
|
|
14
|
+
* If undefined, all descendant nodes are tested (used by expression()).
|
|
15
|
+
*/
|
|
16
|
+
readonly syntaxKinds?: SyntaxKind[];
|
|
17
|
+
/**
|
|
18
|
+
* Test whether a single AST node matches this pattern.
|
|
19
|
+
*
|
|
20
|
+
* Precondition: the node's kind is one of `syntaxKinds` (if specified).
|
|
21
|
+
* The condition layer enforces this — matchers can assume the kind is correct.
|
|
22
|
+
*/
|
|
23
|
+
matches(node: Node): boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Match a CallExpression by function/method name.
|
|
27
|
+
*
|
|
28
|
+
* Matches against `CallExpression.getExpression().getText()` after
|
|
29
|
+
* normalizing optional chaining.
|
|
30
|
+
*
|
|
31
|
+
* @param nameOrRegex - Exact name (e.g. 'parseInt', 'this.normalizeCount')
|
|
32
|
+
* or regex for flexible matching.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* call('parseInt') // matches parseInt(x)
|
|
36
|
+
* call('this.normalizeCount') // matches this.normalizeCount(x) AND this?.normalizeCount(x)
|
|
37
|
+
* call(/^console\./) // matches console.log, console.warn, etc.
|
|
38
|
+
*/
|
|
39
|
+
export declare function call(nameOrRegex: string | RegExp): ExpressionMatcher;
|
|
40
|
+
/**
|
|
41
|
+
* Match a PropertyAccessExpression by the dotted chain.
|
|
42
|
+
*
|
|
43
|
+
* Matches against `PropertyAccessExpression.getText()` after normalizing
|
|
44
|
+
* optional chaining. Useful for detecting direct property access patterns
|
|
45
|
+
* like `process.env`, `this.db`, `window.location`.
|
|
46
|
+
*
|
|
47
|
+
* @param chain - Exact dotted chain (e.g. 'process.env') or regex.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* access('process.env') // matches process.env.FOO (the inner access)
|
|
51
|
+
* access(/^this\.db/) // matches this.db, this.db.query, etc.
|
|
52
|
+
*/
|
|
53
|
+
export declare function access(chain: string | RegExp): ExpressionMatcher;
|
|
54
|
+
/**
|
|
55
|
+
* Match a NewExpression by constructor name.
|
|
56
|
+
*
|
|
57
|
+
* Matches against `NewExpression.getExpression().getText()`.
|
|
58
|
+
* The PoC confirmed this correctly distinguishes 'Error' from 'DomainError'.
|
|
59
|
+
*
|
|
60
|
+
* @param nameOrRegex - Exact constructor name or regex.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* newExpr('Error') // matches new Error(...) but NOT new DomainError(...)
|
|
64
|
+
* newExpr('DomainError') // matches new DomainError(...)
|
|
65
|
+
* newExpr(/Error$/) // matches new Error, new DomainError, new TypeError, etc.
|
|
66
|
+
*/
|
|
67
|
+
export declare function newExpr(nameOrRegex: string | RegExp): ExpressionMatcher;
|
|
68
|
+
/**
|
|
69
|
+
* Escape hatch: match any node whose getText() contains or matches the given pattern.
|
|
70
|
+
*
|
|
71
|
+
* This is intentionally broad and should be used sparingly. It walks ALL
|
|
72
|
+
* descendant nodes and checks getText() against the pattern. A runtime
|
|
73
|
+
* console.warn is emitted the first time expression() is used, encouraging
|
|
74
|
+
* users to prefer call/access/newExpr where possible.
|
|
75
|
+
*
|
|
76
|
+
* @param textOrRegex - Substring to search for (string) or regex pattern.
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* expression('eval') // matches any node containing 'eval'
|
|
80
|
+
* expression(/document\.write/) // matches document.write calls
|
|
81
|
+
*/
|
|
82
|
+
export declare function expression(textOrRegex: string | RegExp): ExpressionMatcher;
|
|
83
|
+
export declare function property(name: string | RegExp, value?: boolean | number | string | RegExp): ExpressionMatcher;
|
|
84
|
+
/**
|
|
85
|
+
* Default stub/deferred-work patterns found in comments.
|
|
86
|
+
* Matches common markers (see regex) and phrases like
|
|
87
|
+
* "not implemented" or "coming soon".
|
|
88
|
+
*
|
|
89
|
+
* Exported as a constant for use with `comment()`. Users can pass
|
|
90
|
+
* their own RegExp to `comment()` for narrower matching.
|
|
91
|
+
*/
|
|
92
|
+
export declare const STUB_PATTERNS: RegExp;
|
|
93
|
+
/**
|
|
94
|
+
* Match comments attached to AST nodes.
|
|
95
|
+
*
|
|
96
|
+
* Unlike other matchers that test AST nodes, this matcher tests the
|
|
97
|
+
* leading and trailing comment ranges of each node. It uses
|
|
98
|
+
* `syntaxKinds: undefined` so the broad traversal path visits every node,
|
|
99
|
+
* and `matches(node)` checks that node's comment ranges.
|
|
100
|
+
*
|
|
101
|
+
* A Set tracks matched comment positions to avoid duplicates (the same
|
|
102
|
+
* comment may be visited as leading trivia of multiple nested nodes).
|
|
103
|
+
*
|
|
104
|
+
* @param pattern - String substring or RegExp to test against comment text.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* comment(/HACK/) // matches hack marker comments
|
|
108
|
+
* comment(STUB_PATTERNS) // matches all common stub markers
|
|
109
|
+
* comment('HACK') // matches hack comments
|
|
110
|
+
*/
|
|
111
|
+
export declare function comment(pattern: string | RegExp): ExpressionMatcher;
|
|
112
|
+
/**
|
|
113
|
+
* Match a JSX element by tag name.
|
|
114
|
+
*
|
|
115
|
+
* Targets `JsxElement` (has children) and `JsxSelfClosingElement` (no children).
|
|
116
|
+
* This is a **tag-only** matcher — it cannot check attributes. Use the
|
|
117
|
+
* `jsxElements()` entry point for attribute-level rules.
|
|
118
|
+
*
|
|
119
|
+
* @param tagOrRegex - Exact tag name (e.g. 'div', 'Button') or regex.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* jsxElement('div') // matches <div>...</div> and <div />
|
|
123
|
+
* jsxElement('Button') // matches <Button>...</Button>
|
|
124
|
+
* jsxElement(/^motion\./) // matches <motion.div>, <motion.span>, etc.
|
|
125
|
+
*/
|
|
126
|
+
export declare function jsxElement(tagOrRegex: string | RegExp): ExpressionMatcher;
|
|
127
|
+
/**
|
|
128
|
+
* Match hardcoded JSX text content — the children of JSX elements.
|
|
129
|
+
*
|
|
130
|
+
* Where {@link jsxElement} matches elements by tag and the `jsxElements()`
|
|
131
|
+
* entry point handles attribute values, this matcher covers the remaining
|
|
132
|
+
* gap: literal text rendered as element children. Composes with
|
|
133
|
+
* `notContain()` for i18n-style rules ("no hardcoded user-facing text").
|
|
134
|
+
*
|
|
135
|
+
* Matches:
|
|
136
|
+
* - `JsxText` nodes with non-whitespace content (`<button>Save</button>`).
|
|
137
|
+
* - `JsxExpression` wrapping a bare string literal (`<div>{"Save"}</div>`)
|
|
138
|
+
* or a no-substitution template (`` <div>{`Save`}</div> ``) — these render
|
|
139
|
+
* identically to plain text and would otherwise be a trivial bypass.
|
|
140
|
+
*
|
|
141
|
+
* Does NOT match: inter-element whitespace, `{expr}` wrapping an identifier
|
|
142
|
+
* or call (`<div>{t("save")}</div>`), templates with substitution
|
|
143
|
+
* (`` <div>{`Hi ${name}`}</div> ``), or attribute values whether braced or
|
|
144
|
+
* quoted (`title={"Save"}`, `title="Save"`) — those belong to the
|
|
145
|
+
* `jsxElements()` entry point. No letter-presence filter is baked in —
|
|
146
|
+
* `<div>123</div>` matches; the matcher takes no options, so to narrow which
|
|
147
|
+
* text is flagged, scope the rule with folder/file predicates or
|
|
148
|
+
* `.excluding(...)`. Note: text inside translation wrappers like `<Trans>`
|
|
149
|
+
* also matches — scope those out the same way if your i18n setup uses them.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* modules(p)
|
|
153
|
+
* .that()
|
|
154
|
+
* .resideInFolder('src/components/**')
|
|
155
|
+
* .should()
|
|
156
|
+
* .notContain(jsxText())
|
|
157
|
+
* .because('User-facing text must go through t()')
|
|
158
|
+
* .check()
|
|
159
|
+
*/
|
|
160
|
+
export declare function jsxText(): ExpressionMatcher;
|
|
161
|
+
/**
|
|
162
|
+
* Options for the `typeAssertion()` matcher.
|
|
163
|
+
*/
|
|
164
|
+
export interface TypeAssertionOptions {
|
|
165
|
+
/**
|
|
166
|
+
* Whether to allow `as const` in user code (default: true).
|
|
167
|
+
*
|
|
168
|
+
* | Option | Matcher matches `as const`? | With `notContain()` — is `as const` allowed in code? |
|
|
169
|
+
* | ---------------------- | --------------------------- | ---------------------------------------------------- |
|
|
170
|
+
* | default (`true`) | no | yes — idiomatic literal preservation |
|
|
171
|
+
* | `{ allowConst: false }` | yes | no — bans ALL `as` expressions |
|
|
172
|
+
*
|
|
173
|
+
* Does NOT affect angle-bracket assertions (`<Type>value`) — those can't
|
|
174
|
+
* express `as const` and are always matched.
|
|
175
|
+
*/
|
|
176
|
+
readonly allowConst?: boolean;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Match type assertion expressions — both `as Type` and the legacy
|
|
180
|
+
* angle-bracket `<Type>value` form.
|
|
181
|
+
*
|
|
182
|
+
* By default, `as const` is excluded from matches (it narrows types rather
|
|
183
|
+
* than widening them, so it's idiomatic for literal preservation). The
|
|
184
|
+
* `allowConst` option does not affect angle-bracket assertions — those
|
|
185
|
+
* can't express `as const` and are always matched.
|
|
186
|
+
*
|
|
187
|
+
* Does NOT match `satisfies` expressions — those are validation, not
|
|
188
|
+
* assertions, and should not be banned.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* // Allow `as const` in user code (default)
|
|
192
|
+
* classes(p).should().notContain(typeAssertion()).check()
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* // Ban `as const` too — no `as` expressions of any kind
|
|
196
|
+
* modules(p).should().notContain(typeAssertion({ allowConst: false })).check()
|
|
197
|
+
*/
|
|
198
|
+
export declare function typeAssertion(options?: TypeAssertionOptions): ExpressionMatcher;
|
|
199
|
+
/**
|
|
200
|
+
* Match `!` non-null assertion expressions.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* functions(p).should().notContain(nonNullAssertion()).check()
|
|
204
|
+
*/
|
|
205
|
+
export declare function nonNullAssertion(): ExpressionMatcher;
|
|
206
|
+
//# sourceMappingURL=matchers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../../src/helpers/matchers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAqB,MAAM,UAAU,CAAA;AAE9D;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,UAAU,EAAE,CAAA;IAEnC;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAA;CAC7B;AAaD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAqBpE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAqBhE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAqBvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAgC1E;AAsDD,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GACzC,iBAAiB,CAgBnB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,QACsE,CAAA;AAEhG;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAoCnE;AAeD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,iBAAiB,CAoBzE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,OAAO,IAAI,iBAAiB,CAwB3C;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,iBAAiB,CAoB/E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CAQpD"}
|