yukigo 0.2.2 → 0.3.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.
Files changed (266) hide show
  1. package/.mocharc.json +3 -3
  2. package/CHANGELOG.md +102 -41
  3. package/README.md +193 -193
  4. package/dist/analyzer/GraphBuilder.d.ts +1 -0
  5. package/dist/analyzer/GraphBuilder.js +2 -1
  6. package/dist/analyzer/index.d.ts +0 -7
  7. package/dist/analyzer/index.js +3 -3
  8. package/dist/analyzer/inspections/functional/functional.d.ts +1 -1
  9. package/dist/analyzer/inspections/functional/functional.js +1 -1
  10. package/dist/analyzer/inspections/functional/smells.d.ts +3 -3
  11. package/dist/analyzer/inspections/functional/smells.js +27 -35
  12. package/dist/analyzer/inspections/generic/generic.d.ts +21 -14
  13. package/dist/analyzer/inspections/generic/generic.js +78 -59
  14. package/dist/analyzer/inspections/generic/smells.d.ts +2 -0
  15. package/dist/analyzer/inspections/generic/smells.js +55 -64
  16. package/dist/analyzer/inspections/imperative/imperative.d.ts +3 -3
  17. package/dist/analyzer/inspections/imperative/imperative.js +3 -3
  18. package/dist/analyzer/inspections/imperative/smells.d.ts +1 -0
  19. package/dist/analyzer/inspections/imperative/smells.js +8 -5
  20. package/dist/analyzer/inspections/logic/logic.d.ts +8 -8
  21. package/dist/analyzer/inspections/logic/logic.js +5 -5
  22. package/dist/analyzer/inspections/logic/smells.js +2 -2
  23. package/dist/analyzer/inspections/object/object.d.ts +5 -5
  24. package/dist/analyzer/inspections/object/object.js +22 -21
  25. package/dist/analyzer/inspections/object/smells.js +11 -23
  26. package/dist/analyzer/utils.d.ts +6 -2
  27. package/dist/analyzer/utils.js +6 -2
  28. package/dist/interpreter/components/EnvBuilder.d.ts +20 -1
  29. package/dist/interpreter/components/EnvBuilder.js +211 -66
  30. package/dist/interpreter/components/EqualityComparer.d.ts +15 -0
  31. package/dist/interpreter/components/EqualityComparer.js +69 -0
  32. package/dist/interpreter/components/Operations.d.ts +17 -14
  33. package/dist/interpreter/components/Operations.js +61 -62
  34. package/dist/interpreter/components/PatternMatcher.d.ts +19 -58
  35. package/dist/interpreter/components/PatternMatcher.js +185 -286
  36. package/dist/interpreter/components/RuntimeContext.d.ts +24 -15
  37. package/dist/interpreter/components/RuntimeContext.js +43 -4
  38. package/dist/interpreter/components/TestRunner.d.ts +15 -13
  39. package/dist/interpreter/components/TestRunner.js +86 -53
  40. package/dist/interpreter/components/evaluators/BaseEvaluator.d.ts +19 -0
  41. package/dist/interpreter/components/evaluators/BaseEvaluator.js +20 -0
  42. package/dist/interpreter/components/evaluators/ExpressionEvaluator.d.ts +34 -0
  43. package/dist/interpreter/components/evaluators/ExpressionEvaluator.js +298 -0
  44. package/dist/interpreter/components/evaluators/OperationEvaluator.d.ts +25 -0
  45. package/dist/interpreter/components/evaluators/OperationEvaluator.js +226 -0
  46. package/dist/interpreter/components/evaluators/PrimitiveEvaluator.d.ts +19 -0
  47. package/dist/interpreter/components/evaluators/PrimitiveEvaluator.js +50 -0
  48. package/dist/interpreter/components/evaluators/StatementEvaluator.d.ts +28 -0
  49. package/dist/interpreter/components/evaluators/StatementEvaluator.js +240 -0
  50. package/dist/interpreter/components/evaluators/TestingEvaluator.d.ts +15 -0
  51. package/dist/interpreter/components/evaluators/TestingEvaluator.js +14 -0
  52. package/dist/interpreter/components/evaluators/index.d.ts +110 -0
  53. package/dist/interpreter/components/evaluators/index.js +21 -0
  54. package/dist/interpreter/components/evaluators/utils.d.ts +7 -0
  55. package/dist/interpreter/components/evaluators/utils.js +50 -0
  56. package/dist/interpreter/components/hooks/YukigoHook.d.ts +27 -0
  57. package/dist/interpreter/components/hooks/YukigoHook.js +1 -0
  58. package/dist/interpreter/components/kernel/commands.d.ts +122 -0
  59. package/dist/interpreter/components/kernel/commands.js +203 -0
  60. package/dist/interpreter/components/kernel/index.d.ts +51 -0
  61. package/dist/interpreter/components/kernel/index.js +176 -0
  62. package/dist/interpreter/components/logic/LogicEngine.d.ts +26 -23
  63. package/dist/interpreter/components/logic/LogicEngine.js +234 -221
  64. package/dist/interpreter/components/logic/LogicResolver.d.ts +22 -51
  65. package/dist/interpreter/components/logic/LogicResolver.js +73 -440
  66. package/dist/interpreter/components/logic/LogicTerm.d.ts +104 -0
  67. package/dist/interpreter/components/logic/LogicTerm.js +423 -0
  68. package/dist/interpreter/components/logic/LogicTranslator.d.ts +25 -9
  69. package/dist/interpreter/components/logic/LogicTranslator.js +211 -74
  70. package/dist/interpreter/components/runtimes/FunctionRuntime.d.ts +6 -4
  71. package/dist/interpreter/components/runtimes/FunctionRuntime.js +82 -84
  72. package/dist/interpreter/components/runtimes/LazyRuntime.d.ts +13 -14
  73. package/dist/interpreter/components/runtimes/LazyRuntime.js +112 -239
  74. package/dist/interpreter/components/runtimes/ObjectRuntime.d.ts +17 -14
  75. package/dist/interpreter/components/runtimes/ObjectRuntime.js +105 -74
  76. package/dist/interpreter/errors.d.ts +10 -0
  77. package/dist/interpreter/errors.js +17 -0
  78. package/dist/interpreter/index.d.ts +9 -5
  79. package/dist/interpreter/index.js +11 -13
  80. package/dist/interpreter/primitives/YuValue.d.ts +21 -0
  81. package/dist/interpreter/primitives/YuValue.js +40 -0
  82. package/dist/interpreter/primitives/capabilities.d.ts +90 -0
  83. package/dist/interpreter/primitives/capabilities.js +1 -0
  84. package/dist/interpreter/primitives/entities/LazyList.d.ts +48 -0
  85. package/dist/interpreter/primitives/entities/LazyList.js +164 -0
  86. package/dist/interpreter/primitives/entities/LogicResult.d.ts +51 -0
  87. package/dist/interpreter/primitives/entities/LogicResult.js +101 -0
  88. package/dist/interpreter/primitives/entities/RuntimeClass.d.ts +24 -0
  89. package/dist/interpreter/primitives/entities/RuntimeClass.js +57 -0
  90. package/dist/interpreter/primitives/entities/RuntimeFunction.d.ts +40 -0
  91. package/dist/interpreter/primitives/entities/RuntimeFunction.js +73 -0
  92. package/dist/interpreter/primitives/entities/RuntimeObject.d.ts +27 -0
  93. package/dist/interpreter/primitives/entities/RuntimeObject.js +82 -0
  94. package/dist/interpreter/primitives/entities/RuntimePredicate.d.ts +19 -0
  95. package/dist/interpreter/primitives/entities/RuntimePredicate.js +59 -0
  96. package/dist/interpreter/primitives/index.d.ts +14 -0
  97. package/dist/interpreter/primitives/index.js +14 -0
  98. package/dist/interpreter/primitives/scalars/YuBoolean.d.ts +24 -0
  99. package/dist/interpreter/primitives/scalars/YuBoolean.js +69 -0
  100. package/dist/interpreter/primitives/scalars/YuChar.d.ts +28 -0
  101. package/dist/interpreter/primitives/scalars/YuChar.js +78 -0
  102. package/dist/interpreter/primitives/scalars/YuNil.d.ts +25 -0
  103. package/dist/interpreter/primitives/scalars/YuNil.js +73 -0
  104. package/dist/interpreter/primitives/scalars/YuNumber.d.ts +49 -0
  105. package/dist/interpreter/primitives/scalars/YuNumber.js +165 -0
  106. package/dist/interpreter/primitives/sequences/YuArray.d.ts +33 -0
  107. package/dist/interpreter/primitives/sequences/YuArray.js +150 -0
  108. package/dist/interpreter/primitives/sequences/YuString.d.ts +40 -0
  109. package/dist/interpreter/primitives/sequences/YuString.js +130 -0
  110. package/dist/interpreter/utils.d.ts +23 -10
  111. package/dist/interpreter/utils.js +25 -30
  112. package/dist/tester/index.d.ts +3 -3
  113. package/dist/tester/index.js +39 -28
  114. package/dist/utils/helpers.d.ts +12 -5
  115. package/dist/utils/helpers.js +6 -79
  116. package/package.json +3 -16
  117. package/src/analyzer/GraphBuilder.ts +143 -142
  118. package/src/analyzer/index.ts +185 -194
  119. package/src/analyzer/inspections/functional/functional.ts +121 -121
  120. package/src/analyzer/inspections/functional/smells.ts +88 -102
  121. package/src/analyzer/inspections/generic/generic.ts +610 -581
  122. package/src/analyzer/inspections/generic/smells.ts +355 -365
  123. package/src/analyzer/inspections/imperative/imperative.ts +104 -101
  124. package/src/analyzer/inspections/imperative/smells.ts +58 -54
  125. package/src/analyzer/inspections/logic/logic.ts +84 -90
  126. package/src/analyzer/inspections/logic/smells.ts +54 -54
  127. package/src/analyzer/inspections/object/object.ts +295 -264
  128. package/src/analyzer/inspections/object/smells.ts +130 -144
  129. package/src/analyzer/utils.ts +115 -109
  130. package/src/index.ts +3 -3
  131. package/src/interpreter/components/EnvBuilder.ts +405 -202
  132. package/src/interpreter/components/EqualityComparer.ts +107 -0
  133. package/src/interpreter/components/Operations.ts +126 -99
  134. package/src/interpreter/components/PatternMatcher.ts +375 -475
  135. package/src/interpreter/components/RuntimeContext.ts +181 -119
  136. package/src/interpreter/components/TestRunner.ts +223 -151
  137. package/src/interpreter/components/evaluators/BaseEvaluator.ts +36 -0
  138. package/src/interpreter/components/evaluators/ExpressionEvaluator.ts +475 -0
  139. package/src/interpreter/components/evaluators/OperationEvaluator.ts +477 -0
  140. package/src/interpreter/components/evaluators/PrimitiveEvaluator.ts +80 -0
  141. package/src/interpreter/components/evaluators/StatementEvaluator.ts +372 -0
  142. package/src/interpreter/components/evaluators/TestingEvaluator.ts +26 -0
  143. package/src/interpreter/components/evaluators/index.ts +34 -0
  144. package/src/interpreter/components/evaluators/utils.ts +64 -0
  145. package/src/interpreter/components/hooks/YukigoHook.ts +45 -0
  146. package/src/interpreter/components/kernel/commands.ts +255 -0
  147. package/src/interpreter/components/kernel/index.ts +222 -0
  148. package/src/interpreter/components/logic/LogicEngine.ts +509 -519
  149. package/src/interpreter/components/logic/LogicResolver.ts +209 -858
  150. package/src/interpreter/components/logic/LogicTerm.ts +477 -0
  151. package/src/interpreter/components/logic/LogicTranslator.ts +362 -149
  152. package/src/interpreter/components/runtimes/FunctionRuntime.ts +249 -227
  153. package/src/interpreter/components/runtimes/LazyRuntime.ts +226 -334
  154. package/src/interpreter/components/runtimes/ObjectRuntime.ts +262 -224
  155. package/src/interpreter/errors.ts +68 -47
  156. package/src/interpreter/index.ts +50 -52
  157. package/src/interpreter/primitives/YuValue.ts +64 -0
  158. package/src/interpreter/primitives/capabilities.ts +111 -0
  159. package/src/interpreter/primitives/entities/LazyList.ts +225 -0
  160. package/src/interpreter/primitives/entities/LogicResult.ts +133 -0
  161. package/src/interpreter/primitives/entities/RuntimeClass.ts +70 -0
  162. package/src/interpreter/primitives/entities/RuntimeFunction.ts +108 -0
  163. package/src/interpreter/primitives/entities/RuntimeObject.ts +110 -0
  164. package/src/interpreter/primitives/entities/RuntimePredicate.ts +77 -0
  165. package/src/interpreter/primitives/index.ts +17 -0
  166. package/src/interpreter/primitives/scalars/YuBoolean.ts +79 -0
  167. package/src/interpreter/primitives/scalars/YuChar.ts +94 -0
  168. package/src/interpreter/primitives/scalars/YuNil.ts +84 -0
  169. package/src/interpreter/primitives/scalars/YuNumber.ts +187 -0
  170. package/src/interpreter/primitives/sequences/YuArray.ts +178 -0
  171. package/src/interpreter/primitives/sequences/YuString.ts +165 -0
  172. package/src/interpreter/utils.ts +105 -84
  173. package/src/tester/index.ts +157 -128
  174. package/src/utils/helpers.ts +81 -168
  175. package/tests/analyzer/functional.spec.ts +221 -207
  176. package/tests/analyzer/generic.spec.ts +178 -178
  177. package/tests/analyzer/helpers.spec.ts +83 -89
  178. package/tests/analyzer/logic.spec.ts +237 -237
  179. package/tests/analyzer/oop.spec.ts +320 -323
  180. package/tests/analyzer/transitive.spec.ts +166 -166
  181. package/tests/interpreter/EnvBuilder.spec.ts +181 -183
  182. package/tests/interpreter/FunctionRuntime.spec.ts +224 -223
  183. package/tests/interpreter/LazyRuntime.spec.ts +227 -225
  184. package/tests/interpreter/LogicEngine.spec.ts +371 -327
  185. package/tests/interpreter/LogicSubstitution.spec.ts +90 -80
  186. package/tests/interpreter/ObjectRuntime.spec.ts +431 -606
  187. package/tests/interpreter/Operations.spec.ts +312 -220
  188. package/tests/interpreter/PatternSystem.spec.ts +254 -213
  189. package/tests/interpreter/Tests.spec.ts +122 -122
  190. package/tests/interpreter/interpreter.spec.ts +1143 -991
  191. package/tests/kernel/YukigoKernel.spec.ts +112 -0
  192. package/tests/tester/Tester.spec.ts +188 -152
  193. package/tsconfig.build.json +16 -15
  194. package/tsconfig.json +27 -25
  195. package/dist/interpreter/components/Visitor.d.ts +0 -70
  196. package/dist/interpreter/components/Visitor.js +0 -634
  197. package/dist/interpreter/entities.d.ts +0 -105
  198. package/dist/interpreter/entities.js +0 -96
  199. package/dist/interpreter/trampoline.d.ts +0 -17
  200. package/dist/interpreter/trampoline.js +0 -38
  201. package/dist/src/analyzer/GraphBuilder.d.ts +0 -30
  202. package/dist/src/analyzer/GraphBuilder.js +0 -100
  203. package/dist/src/analyzer/index.d.ts +0 -59
  204. package/dist/src/analyzer/index.js +0 -152
  205. package/dist/src/analyzer/inspections/functional/functional.d.ts +0 -44
  206. package/dist/src/analyzer/inspections/functional/functional.js +0 -149
  207. package/dist/src/analyzer/inspections/functional/smells.d.ts +0 -16
  208. package/dist/src/analyzer/inspections/functional/smells.js +0 -98
  209. package/dist/src/analyzer/inspections/generic/generic.d.ts +0 -178
  210. package/dist/src/analyzer/inspections/generic/generic.js +0 -604
  211. package/dist/src/analyzer/inspections/generic/smells.d.ts +0 -61
  212. package/dist/src/analyzer/inspections/generic/smells.js +0 -349
  213. package/dist/src/analyzer/inspections/imperative/imperative.d.ts +0 -35
  214. package/dist/src/analyzer/inspections/imperative/imperative.js +0 -109
  215. package/dist/src/analyzer/inspections/imperative/smells.d.ts +0 -16
  216. package/dist/src/analyzer/inspections/imperative/smells.js +0 -58
  217. package/dist/src/analyzer/inspections/logic/logic.d.ts +0 -32
  218. package/dist/src/analyzer/inspections/logic/logic.js +0 -96
  219. package/dist/src/analyzer/inspections/logic/smells.d.ts +0 -15
  220. package/dist/src/analyzer/inspections/logic/smells.js +0 -60
  221. package/dist/src/analyzer/inspections/object/object.d.ts +0 -90
  222. package/dist/src/analyzer/inspections/object/object.js +0 -321
  223. package/dist/src/analyzer/inspections/object/smells.d.ts +0 -30
  224. package/dist/src/analyzer/inspections/object/smells.js +0 -135
  225. package/dist/src/analyzer/utils.d.ts +0 -30
  226. package/dist/src/analyzer/utils.js +0 -78
  227. package/dist/src/index.d.ts +0 -4
  228. package/dist/src/index.js +0 -4
  229. package/dist/src/interpreter/components/EnvBuilder.d.ts +0 -21
  230. package/dist/src/interpreter/components/EnvBuilder.js +0 -155
  231. package/dist/src/interpreter/components/Operations.d.ts +0 -14
  232. package/dist/src/interpreter/components/Operations.js +0 -84
  233. package/dist/src/interpreter/components/PatternMatcher.d.ts +0 -73
  234. package/dist/src/interpreter/components/PatternMatcher.js +0 -358
  235. package/dist/src/interpreter/components/RuntimeContext.d.ts +0 -35
  236. package/dist/src/interpreter/components/RuntimeContext.js +0 -93
  237. package/dist/src/interpreter/components/TestRunner.d.ts +0 -19
  238. package/dist/src/interpreter/components/TestRunner.js +0 -110
  239. package/dist/src/interpreter/components/Visitor.d.ts +0 -71
  240. package/dist/src/interpreter/components/Visitor.js +0 -638
  241. package/dist/src/interpreter/components/logic/LogicEngine.d.ts +0 -29
  242. package/dist/src/interpreter/components/logic/LogicEngine.js +0 -259
  243. package/dist/src/interpreter/components/logic/LogicResolver.d.ts +0 -53
  244. package/dist/src/interpreter/components/logic/LogicResolver.js +0 -484
  245. package/dist/src/interpreter/components/logic/LogicTranslator.d.ts +0 -14
  246. package/dist/src/interpreter/components/logic/LogicTranslator.js +0 -99
  247. package/dist/src/interpreter/components/runtimes/FunctionRuntime.d.ts +0 -12
  248. package/dist/src/interpreter/components/runtimes/FunctionRuntime.js +0 -149
  249. package/dist/src/interpreter/components/runtimes/LazyRuntime.d.ts +0 -19
  250. package/dist/src/interpreter/components/runtimes/LazyRuntime.js +0 -269
  251. package/dist/src/interpreter/components/runtimes/ObjectRuntime.d.ts +0 -35
  252. package/dist/src/interpreter/components/runtimes/ObjectRuntime.js +0 -126
  253. package/dist/src/interpreter/errors.d.ts +0 -19
  254. package/dist/src/interpreter/errors.js +0 -36
  255. package/dist/src/interpreter/index.d.ts +0 -24
  256. package/dist/src/interpreter/index.js +0 -41
  257. package/dist/src/interpreter/trampoline.d.ts +0 -17
  258. package/dist/src/interpreter/trampoline.js +0 -38
  259. package/dist/src/interpreter/utils.d.ts +0 -11
  260. package/dist/src/interpreter/utils.js +0 -65
  261. package/dist/src/tester/index.d.ts +0 -25
  262. package/dist/src/tester/index.js +0 -113
  263. package/dist/src/utils/helpers.d.ts +0 -13
  264. package/dist/src/utils/helpers.js +0 -52
  265. package/src/interpreter/components/Visitor.ts +0 -1065
  266. package/src/interpreter/trampoline.ts +0 -71
@@ -1,194 +1,185 @@
1
- import { AST, TraverseVisitor, StopTraversalException } from "yukigo-ast";
2
- import { genericInspections } from "./inspections/generic/generic.js";
3
- import { functionalInspections } from "./inspections/functional/functional.js";
4
- import { logicInspections } from "./inspections/logic/logic.js";
5
- import { objectInspections } from "./inspections/object/object.js";
6
- import { imperativeInspections } from "./inspections/imperative/imperative.js";
7
- import { InspectionMap, VisitorConstructor } from "./utils.js";
8
- import { functionalSmells } from "./inspections/functional/smells.js";
9
- import { logicSmells } from "./inspections/logic/smells.js";
10
- import { objectSmells } from "./inspections/object/smells.js";
11
- import { imperativeSmells } from "./inspections/imperative/smells.js";
12
- import { genericSmells } from "./inspections/generic/smells.js";
13
- import { GraphBuilder } from "./GraphBuilder.js";
14
-
15
- export type AnalysisResult = {
16
- rule: InspectionRule;
17
- passed: boolean;
18
- actual: boolean;
19
- error?: string;
20
- };
21
-
22
- export type TargetSuffix = "named" | "like" | "except";
23
-
24
- export type InspectionMatcher = {
25
- type: string;
26
- value?: string;
27
- };
28
-
29
- export type InspectionRule = {
30
- inspection: string;
31
- binding?: string;
32
- args?: string[];
33
- expected: boolean;
34
- targetSuffix?: TargetSuffix;
35
- matcher?: InspectionMatcher;
36
- };
37
-
38
- export const DefaultInspectionSet: InspectionMap = {
39
- ...genericInspections,
40
- ...functionalInspections,
41
- ...logicInspections,
42
- ...objectInspections,
43
- ...imperativeInspections,
44
- };
45
- export const DefaultSmellsSet: InspectionMap = {
46
- ...genericSmells,
47
- ...functionalSmells,
48
- ...logicSmells,
49
- ...objectSmells,
50
- ...imperativeSmells,
51
- };
52
-
53
- /**
54
- * The Analyzer class.
55
- * @remarks
56
- * The Analyzer is the part of Yukigo which runs the inspections on the AST.s
57
- */
58
- export class Analyzer {
59
- /**
60
- * The set of inspections that are available for the Analyzer.
61
- * You can load your set of inspections or leave the default one.
62
- * @defaultValue a default set of inspections for each supported paradigm
63
- */
64
- private inspectionConstructors: InspectionMap = {};
65
- private smellsConstructors: InspectionMap = {};
66
- constructor(inspectionSet?: InspectionMap, smellsSet?: InspectionMap) {
67
- this.inspectionConstructors = inspectionSet ?? DefaultInspectionSet;
68
- this.smellsConstructors = smellsSet ?? DefaultSmellsSet;
69
- }
70
-
71
- /**
72
- * Registers a new custom inspection handler after Analyzer was instantiated.
73
- * @param name The name of the inspection (e.g., "HasArithmetic").
74
- * @param visitorConstructor The constructor for the TraverseVisitor class.
75
- */
76
- public registerInspection(
77
- name: string,
78
- visitorConstructor: VisitorConstructor
79
- ) {
80
- this.inspectionConstructors[name] = visitorConstructor;
81
- }
82
-
83
- /**
84
- * Runs a list of inspection rules against the AST.
85
- * @param ast The parsed AST.
86
- * @param rules The array of inspection rules to run.
87
- * @returns An array of analysis results.
88
- * @example
89
- * const rules: InspectionRule[] = [
90
- * {
91
- * inspection: "HasBinding",
92
- * args: { name: "minimoEntre" },
93
- * expected: false,
94
- * },
95
- * {
96
- * inspection: "HasBinding",
97
- * args: { name: "squareList" },
98
- * expected: true,
99
- * }
100
- * ]
101
- * const analyzer = new ASTAnalyzer(ast);
102
- * const analysisResults = analyzer.analyze(expectations);
103
- */
104
- public analyze(ast: AST, rules: InspectionRule[]): AnalysisResult[] {
105
- const ruleResults: Map<InspectionRule, AnalysisResult> = new Map();
106
- const graphBuilder = new GraphBuilder();
107
- const { defs, calls } = graphBuilder.build(ast);
108
-
109
- for (const rule of rules) {
110
- let inspectionName = rule.inspection;
111
- let isTransitive = true;
112
-
113
- if (inspectionName.startsWith("Intransitive:")) {
114
- isTransitive = false;
115
- inspectionName = inspectionName.replace("Intransitive:", "");
116
- }
117
-
118
- const InspectionClass = this.inspectionConstructors[inspectionName];
119
- if (!InspectionClass) {
120
- ruleResults.set(rule, {
121
- rule,
122
- passed: false,
123
- actual: false,
124
- error: "Unknown inspection: " + inspectionName,
125
- });
126
- continue;
127
- }
128
-
129
- if (InspectionClass.IS_INTRANSITIVE) isTransitive = false;
130
-
131
- let targets: { node: any; binding?: string }[] = [];
132
-
133
- // Case 1: Global Inspection (No binding or wildcard)
134
- if (!rule.binding || rule.binding === "*") {
135
- targets = ast.map((n) => ({ node: n, binding: undefined }));
136
- }
137
- // Case 2: Directed Inspection (Specific binding)
138
- else {
139
- const workList = [rule.binding];
140
- const visited = new Set<string>();
141
-
142
- while (workList.length > 0) {
143
- const currentBinding = workList.shift();
144
- if (visited.has(currentBinding)) continue;
145
- visited.add(currentBinding);
146
-
147
- const node = defs.get(currentBinding);
148
- if (node)
149
- node.forEach((n) =>
150
- targets.push({ node: n, binding: currentBinding })
151
- );
152
-
153
- if (isTransitive) {
154
- const deps = calls.get(currentBinding) || [];
155
- workList.push(...deps);
156
- }
157
- }
158
- }
159
-
160
- let actual = false;
161
- let error: string;
162
-
163
- // Execution Loop
164
- const isGlobalVisitor = !rule.binding || rule.binding === "*";
165
- const normalizedBinding = isGlobalVisitor ? undefined : rule.binding;
166
- const args = rule.args ?? []
167
- const visitor = new InspectionClass(...args, normalizedBinding);
168
-
169
- for (const { node, binding } of targets) {
170
- try {
171
- if (!isGlobalVisitor && visitor.setBinding) {
172
- visitor.setBinding(binding);
173
- }
174
- node.accept(visitor);
175
- } catch (e) {
176
- if (e instanceof StopTraversalException) {
177
- actual = true;
178
- break; // Short-circuit: Rule passed
179
- } else {
180
- error = (e as Error).message;
181
- }
182
- }
183
- }
184
-
185
- ruleResults.set(rule, {
186
- rule,
187
- passed: actual === rule.expected,
188
- actual,
189
- error,
190
- });
191
- }
192
- return [...ruleResults.values()];
193
- }
194
- }
1
+ import { AST, TraverseVisitor, StopTraversalException } from "yukigo-ast";
2
+ import { genericInspections } from "./inspections/generic/generic.js";
3
+ import { functionalInspections } from "./inspections/functional/functional.js";
4
+ import { logicInspections } from "./inspections/logic/logic.js";
5
+ import { objectInspections } from "./inspections/object/object.js";
6
+ import { imperativeInspections } from "./inspections/imperative/imperative.js";
7
+ import { InspectionMap, VisitorConstructor } from "./utils.js";
8
+ import { functionalSmells } from "./inspections/functional/smells.js";
9
+ import { logicSmells } from "./inspections/logic/smells.js";
10
+ import { objectSmells } from "./inspections/object/smells.js";
11
+ import { imperativeSmells } from "./inspections/imperative/smells.js";
12
+ import { genericSmells } from "./inspections/generic/smells.js";
13
+ import { GraphBuilder } from "./GraphBuilder.js";
14
+
15
+ export type AnalysisResult = {
16
+ rule: InspectionRule;
17
+ passed: boolean;
18
+ actual: boolean;
19
+ error?: string;
20
+ };
21
+
22
+ export type InspectionRule = {
23
+ inspection: string;
24
+ binding?: string;
25
+ args?: string[];
26
+ expected: boolean;
27
+ };
28
+
29
+ export const DefaultInspectionSet: InspectionMap = {
30
+ ...genericInspections,
31
+ ...functionalInspections,
32
+ ...logicInspections,
33
+ ...objectInspections,
34
+ ...imperativeInspections,
35
+ };
36
+ export const DefaultSmellsSet: InspectionMap = {
37
+ ...genericSmells,
38
+ ...functionalSmells,
39
+ ...logicSmells,
40
+ ...objectSmells,
41
+ ...imperativeSmells,
42
+ };
43
+
44
+ /**
45
+ * The Analyzer class.
46
+ * @remarks
47
+ * The Analyzer is the part of Yukigo which runs the inspections on the AST.s
48
+ */
49
+ export class Analyzer {
50
+ /**
51
+ * The set of inspections that are available for the Analyzer.
52
+ * You can load your set of inspections or leave the default one.
53
+ * @defaultValue a default set of inspections for each supported paradigm
54
+ */
55
+ private inspectionConstructors: InspectionMap = {};
56
+ private smellsConstructors: InspectionMap = {};
57
+ constructor(inspectionSet?: InspectionMap, smellsSet?: InspectionMap) {
58
+ this.inspectionConstructors = inspectionSet ?? DefaultInspectionSet;
59
+ this.smellsConstructors = smellsSet ?? DefaultSmellsSet;
60
+ }
61
+
62
+ /**
63
+ * Registers a new custom inspection handler after Analyzer was instantiated.
64
+ * @param name The name of the inspection (e.g., "HasArithmetic").
65
+ * @param visitorConstructor The constructor for the TraverseVisitor class.
66
+ */
67
+ public registerInspection(
68
+ name: string,
69
+ visitorConstructor: VisitorConstructor,
70
+ ) {
71
+ this.inspectionConstructors[name] = visitorConstructor;
72
+ }
73
+
74
+ /**
75
+ * Runs a list of inspection rules against the AST.
76
+ * @param ast The parsed AST.
77
+ * @param rules The array of inspection rules to run.
78
+ * @returns An array of analysis results.
79
+ * @example
80
+ * const rules: InspectionRule[] = [
81
+ * {
82
+ * inspection: "HasBinding",
83
+ * args: { name: "minimoEntre" },
84
+ * expected: false,
85
+ * },
86
+ * {
87
+ * inspection: "HasBinding",
88
+ * args: { name: "squareList" },
89
+ * expected: true,
90
+ * }
91
+ * ]
92
+ * const analyzer = new ASTAnalyzer(ast);
93
+ * const analysisResults = analyzer.analyze(expectations);
94
+ */
95
+ public analyze(ast: AST, rules: InspectionRule[]): AnalysisResult[] {
96
+ const ruleResults: Map<InspectionRule, AnalysisResult> = new Map();
97
+ const graphBuilder = new GraphBuilder();
98
+ const { defs, calls } = graphBuilder.build(ast);
99
+
100
+ for (const rule of rules) {
101
+ let inspectionName = rule.inspection;
102
+ let isTransitive = true;
103
+
104
+ if (inspectionName.startsWith("Intransitive:")) {
105
+ isTransitive = false;
106
+ inspectionName = inspectionName.replace("Intransitive:", "");
107
+ }
108
+
109
+ const InspectionClass = this.inspectionConstructors[inspectionName];
110
+ if (!InspectionClass) {
111
+ ruleResults.set(rule, {
112
+ rule,
113
+ passed: false,
114
+ actual: false,
115
+ error: "Unknown inspection: " + inspectionName,
116
+ });
117
+ continue;
118
+ }
119
+
120
+ if (InspectionClass.IS_INTRANSITIVE) isTransitive = false;
121
+
122
+ let targets: { node: any; binding?: string }[] = [];
123
+
124
+ // Case 1: Global Inspection (No binding or wildcard)
125
+ if (!rule.binding || rule.binding === "*") {
126
+ targets = ast.map((n) => ({ node: n, binding: undefined }));
127
+ }
128
+ // Case 2: Directed Inspection (Specific binding)
129
+ else {
130
+ const workList = [rule.binding];
131
+ const visited = new Set<string>();
132
+
133
+ while (workList.length > 0) {
134
+ const currentBinding = workList.shift();
135
+ if (!currentBinding || visited.has(currentBinding)) continue;
136
+ visited.add(currentBinding);
137
+
138
+ const node = defs.get(currentBinding);
139
+ if (node)
140
+ node.forEach((n) =>
141
+ targets.push({ node: n, binding: currentBinding }),
142
+ );
143
+
144
+ if (isTransitive) {
145
+ const deps = calls.get(currentBinding) || [];
146
+ workList.push(...deps);
147
+ }
148
+ }
149
+ }
150
+
151
+ let actual = false;
152
+ let error: string | undefined = undefined;
153
+
154
+ // Execution Loop
155
+ const isGlobalVisitor = !rule.binding || rule.binding === "*";
156
+ const normalizedBinding = isGlobalVisitor ? undefined : rule.binding;
157
+ const args = rule.args ?? [];
158
+ const visitor = new InspectionClass(...args, normalizedBinding);
159
+
160
+ for (const { node, binding } of targets) {
161
+ try {
162
+ if (!isGlobalVisitor && visitor.setBinding && binding) {
163
+ visitor.setBinding(binding);
164
+ }
165
+ node.accept(visitor);
166
+ } catch (e) {
167
+ if (e instanceof StopTraversalException) {
168
+ actual = true;
169
+ break; // Short-circuit: Rule passed
170
+ } else {
171
+ error = (e as Error).message;
172
+ }
173
+ }
174
+ }
175
+
176
+ ruleResults.set(rule, {
177
+ rule,
178
+ passed: actual === rule.expected,
179
+ actual,
180
+ error,
181
+ });
182
+ }
183
+ return [...ruleResults.values()];
184
+ }
185
+ }
@@ -1,121 +1,121 @@
1
- import * as Yu from "yukigo-ast";
2
- import { VisitorConstructor, ScopedVisitor, AutoScoped } from "../../utils.js";
3
-
4
- @AutoScoped
5
- export class UsesComposition extends ScopedVisitor {
6
- constructor(scope?: string) {
7
- super(scope);
8
- }
9
- visitCompositionExpression(node: Yu.CompositionExpression): void {
10
- throw new Yu.StopTraversalException();
11
- }
12
- }
13
- @AutoScoped
14
- export class UsesAnonymousVariable extends ScopedVisitor {
15
- constructor(scope?: string) {
16
- super(scope);
17
- }
18
- visitWildcardPattern(node: Yu.WildcardPattern): void {
19
- throw new Yu.StopTraversalException();
20
- }
21
- }
22
- @AutoScoped
23
- export class UsesComprehension extends ScopedVisitor {
24
- constructor(scope?: string) {
25
- super(scope);
26
- }
27
- visitListComprehension(node: Yu.ListComprehension): void {
28
- throw new Yu.StopTraversalException();
29
- }
30
- }
31
- @AutoScoped
32
- export class UsesGuards extends ScopedVisitor {
33
- constructor(scope?: string) {
34
- super(scope);
35
- }
36
- visitGuardedBody(node: Yu.GuardedBody): void {
37
- throw new Yu.StopTraversalException();
38
- }
39
- }
40
- @AutoScoped
41
- export class UsesOtherwise extends ScopedVisitor {
42
- constructor(scope?: string) {
43
- super(scope);
44
- }
45
- visitOtherwise(node: Yu.Otherwise): void {
46
- throw new Yu.StopTraversalException();
47
- }
48
- }
49
- @AutoScoped
50
- export class UsesLambda extends ScopedVisitor {
51
- constructor(scope?: string) {
52
- super(scope);
53
- }
54
- visitLambda(node: Yu.Lambda): void {
55
- throw new Yu.StopTraversalException();
56
- }
57
- }
58
- @AutoScoped
59
- export class UsesYield extends ScopedVisitor {
60
- constructor(scope?: string) {
61
- super(scope);
62
- }
63
- visitYield(node: Yu.Yield): void {
64
- throw new Yu.StopTraversalException();
65
- }
66
- }
67
- @AutoScoped
68
- export class UsesPatternMatching extends ScopedVisitor {
69
- constructor(scope?: string) {
70
- super(scope);
71
- }
72
- visitConsPattern(node: Yu.ConsPattern): void {
73
- throw new Yu.StopTraversalException();
74
- }
75
- visitAsPattern(node: Yu.AsPattern): void {
76
- throw new Yu.StopTraversalException();
77
- }
78
- visitListPattern(node: Yu.ListPattern): void {
79
- throw new Yu.StopTraversalException();
80
- }
81
- visitTuplePattern(node: Yu.TuplePattern): void {
82
- throw new Yu.StopTraversalException();
83
- }
84
- visitLiteralPattern(node: Yu.LiteralPattern): void {
85
- throw new Yu.StopTraversalException();
86
- }
87
- visitApplicationPattern(node: Yu.ApplicationPattern): void {
88
- throw new Yu.StopTraversalException();
89
- }
90
- visitConstructorPattern(node: Yu.ConstructorPattern): void {
91
- throw new Yu.StopTraversalException();
92
- }
93
- visitUnionPattern(node: Yu.UnionPattern): void {
94
- throw new Yu.StopTraversalException();
95
- }
96
- visitFunctorPattern(node: Yu.FunctorPattern): void {
97
- throw new Yu.StopTraversalException();
98
- }
99
- visitWildcardPattern(node: Yu.WildcardPattern): void {
100
- throw new Yu.StopTraversalException();
101
- }
102
- }
103
-
104
- export const functionalInspections: Record<string, VisitorConstructor> = {
105
- UsesComposition: UsesComposition,
106
- HasComposition: UsesComposition,
107
- UsesAnonymousVariable: UsesAnonymousVariable,
108
- HasAnonymousVariable: UsesAnonymousVariable,
109
- UsesComprehension: UsesComprehension,
110
- HasComprehension: UsesComprehension,
111
- UsesGuards: UsesGuards,
112
- HasGuards: UsesGuards,
113
- UsesOtherwise: UsesOtherwise,
114
- HasOtherwise: UsesOtherwise,
115
- UsesLambda: UsesLambda,
116
- HasLambda: UsesLambda,
117
- UsesYield: UsesYield,
118
- HasYield: UsesYield,
119
- UsesPatternMatching: UsesPatternMatching,
120
- HasPatternMatching: UsesPatternMatching,
121
- };
1
+ import * as Yu from "yukigo-ast";
2
+ import { VisitorConstructor, ScopedVisitor, AutoScoped } from "../../utils.js";
3
+
4
+ @AutoScoped
5
+ export class UsesComposition extends ScopedVisitor {
6
+ constructor(scope?: string) {
7
+ super(scope);
8
+ }
9
+ visitCompositionExpression(node: Yu.CompositionExpression): void {
10
+ throw new Yu.StopTraversalException();
11
+ }
12
+ }
13
+ @AutoScoped
14
+ export class UsesAnonymousVariable extends ScopedVisitor {
15
+ constructor(scope?: string) {
16
+ super(scope);
17
+ }
18
+ visitWildcardPattern(node: Yu.WildcardPattern): void {
19
+ throw new Yu.StopTraversalException();
20
+ }
21
+ }
22
+ @AutoScoped
23
+ export class UsesComprehension extends ScopedVisitor {
24
+ constructor(scope?: string) {
25
+ super(scope);
26
+ }
27
+ visitListComprehension(node: Yu.ListComprehension): void {
28
+ throw new Yu.StopTraversalException();
29
+ }
30
+ }
31
+ @AutoScoped
32
+ export class UsesGuards extends ScopedVisitor {
33
+ constructor(scope?: string) {
34
+ super(scope);
35
+ }
36
+ visitGuardedExpression(node: Yu.GuardedExpression): void {
37
+ throw new Yu.StopTraversalException();
38
+ }
39
+ }
40
+ @AutoScoped
41
+ export class UsesOtherwise extends ScopedVisitor {
42
+ constructor(scope?: string) {
43
+ super(scope);
44
+ }
45
+ visitOtherwise(node: Yu.Otherwise): void {
46
+ throw new Yu.StopTraversalException();
47
+ }
48
+ }
49
+ @AutoScoped
50
+ export class UsesLambda extends ScopedVisitor {
51
+ constructor(scope?: string) {
52
+ super(scope);
53
+ }
54
+ visitLambda(node: Yu.Lambda): void {
55
+ throw new Yu.StopTraversalException();
56
+ }
57
+ }
58
+ @AutoScoped
59
+ export class UsesYield extends ScopedVisitor {
60
+ constructor(scope?: string) {
61
+ super(scope);
62
+ }
63
+ visitYield(node: Yu.Yield): void {
64
+ throw new Yu.StopTraversalException();
65
+ }
66
+ }
67
+ @AutoScoped
68
+ export class UsesPatternMatching extends ScopedVisitor {
69
+ constructor(scope?: string) {
70
+ super(scope);
71
+ }
72
+ visitConsPattern(node: Yu.ConsPattern): void {
73
+ throw new Yu.StopTraversalException();
74
+ }
75
+ visitAsPattern(node: Yu.AsPattern): void {
76
+ throw new Yu.StopTraversalException();
77
+ }
78
+ visitListPattern(node: Yu.ListPattern): void {
79
+ throw new Yu.StopTraversalException();
80
+ }
81
+ visitTuplePattern(node: Yu.TuplePattern): void {
82
+ throw new Yu.StopTraversalException();
83
+ }
84
+ visitLiteralPattern(node: Yu.LiteralPattern): void {
85
+ throw new Yu.StopTraversalException();
86
+ }
87
+ visitApplicationPattern(node: Yu.ApplicationPattern): void {
88
+ throw new Yu.StopTraversalException();
89
+ }
90
+ visitConstructorPattern(node: Yu.ConstructorPattern): void {
91
+ throw new Yu.StopTraversalException();
92
+ }
93
+ visitUnionPattern(node: Yu.UnionPattern): void {
94
+ throw new Yu.StopTraversalException();
95
+ }
96
+ visitFunctorPattern(node: Yu.FunctorPattern): void {
97
+ throw new Yu.StopTraversalException();
98
+ }
99
+ visitWildcardPattern(node: Yu.WildcardPattern): void {
100
+ throw new Yu.StopTraversalException();
101
+ }
102
+ }
103
+
104
+ export const functionalInspections: Record<string, VisitorConstructor> = {
105
+ UsesComposition: UsesComposition,
106
+ HasComposition: UsesComposition,
107
+ UsesAnonymousVariable: UsesAnonymousVariable,
108
+ HasAnonymousVariable: UsesAnonymousVariable,
109
+ UsesComprehension: UsesComprehension,
110
+ HasComprehension: UsesComprehension,
111
+ UsesGuards: UsesGuards,
112
+ HasGuards: UsesGuards,
113
+ UsesOtherwise: UsesOtherwise,
114
+ HasOtherwise: UsesOtherwise,
115
+ UsesLambda: UsesLambda,
116
+ HasLambda: UsesLambda,
117
+ UsesYield: UsesYield,
118
+ HasYield: UsesYield,
119
+ UsesPatternMatching: UsesPatternMatching,
120
+ HasPatternMatching: UsesPatternMatching,
121
+ };