yukigo 0.2.3 → 0.3.2

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 +105 -40
  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 +22 -14
  13. package/dist/analyzer/inspections/generic/generic.js +82 -60
  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 +13 -5
  115. package/dist/utils/helpers.js +38 -85
  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 -577
  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 +113 -169
  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 +156 -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,577 +1,610 @@
1
- import {
2
- Application,
3
- ArithmeticBinaryOperation,
4
- ArithmeticUnaryOperation,
5
- Assignment,
6
- ASTNode,
7
- Attribute,
8
- Call,
9
- Catch,
10
- Class,
11
- EntryPoint,
12
- Equation,
13
- Fact,
14
- Function,
15
- If,
16
- isUnguardedBody,
17
- LogicalBinaryOperation,
18
- LogicalUnaryOperation,
19
- Method,
20
- Object,
21
- ParameterizedType,
22
- Print,
23
- Procedure,
24
- Raise,
25
- Record as RecordNode,
26
- Rule,
27
- SimpleType,
28
- StopTraversalException,
29
- SymbolPrimitive,
30
- TraverseVisitor,
31
- Try,
32
- TypeAlias,
33
- TypeSignature,
34
- TypeVar,
35
- Variable,
36
- VariablePattern,
37
- } from "yukigo-ast";
38
- import { VisitorConstructor, ScopedVisitor, AutoScoped } from "../../utils.js";
39
-
40
- @AutoScoped
41
- export class Assigns extends ScopedVisitor {
42
- private readonly targetIdentifier: string;
43
- constructor(targetIdentifier: string, scope?: string) {
44
- super(scope);
45
- this.targetIdentifier = targetIdentifier;
46
- }
47
- visitVariable(node: Variable): void {
48
- if (node.identifier.value === this.targetIdentifier)
49
- throw new StopTraversalException();
50
- }
51
- visitAttribute(node: Attribute): void {
52
- if (node.identifier.value === this.targetIdentifier)
53
- throw new StopTraversalException();
54
- }
55
- visitAssignment(node: Assignment): void {
56
- if (node.identifier.value === this.targetIdentifier)
57
- throw new StopTraversalException();
58
- }
59
- }
60
- @AutoScoped
61
- export class Calls extends ScopedVisitor {
62
- private readonly targetCallee: string;
63
- constructor(targetCallee: string, scope?: string) {
64
- super(scope);
65
- this.targetCallee = targetCallee;
66
- }
67
- visitCall(node: Call): void {
68
- if (node.callee.value === this.targetCallee)
69
- throw new StopTraversalException();
70
- }
71
- }
72
- @AutoScoped
73
- export class Declares extends ScopedVisitor {
74
- private readonly targetIdentifier: string;
75
-
76
- constructor(targetIdentifier: string, scopeName?: string) {
77
- super(scopeName);
78
- this.targetIdentifier = targetIdentifier;
79
- }
80
-
81
- private check(node: { identifier: SymbolPrimitive }): void {
82
- if (node.identifier.value === this.targetIdentifier)
83
- throw new StopTraversalException();
84
- }
85
-
86
- visitFunction(node: Function): void {
87
- if (this.inScope) this.check(node);
88
- super.visitFunction(node);
89
- }
90
-
91
- visitMethod(node: Method): void {
92
- if (this.inScope) this.check(node);
93
- super.visitMethod(node);
94
- }
95
-
96
- visitProcedure(node: Procedure): void {
97
- if (this.inScope) this.check(node);
98
- super.visitProcedure(node);
99
- }
100
-
101
- visitRule(node: Rule): void {
102
- if (this.inScope) this.check(node);
103
- super.visitRule(node);
104
- }
105
-
106
- visitFact(node: Fact): void {
107
- if (this.inScope) this.check(node);
108
- super.visitFact(node);
109
- }
110
-
111
- visitVariable(node: Variable): void {
112
- this.check(node);
113
- }
114
-
115
- visitAttribute(node: Attribute): void {
116
- this.check(node);
117
- }
118
-
119
- visitTypeAlias(node: TypeAlias): void {
120
- this.check(node);
121
- }
122
- }
123
- @AutoScoped
124
- export class DeclaresComputation extends ScopedVisitor {
125
- private readonly callName: string;
126
- constructor(callName: string, scope?: string) {
127
- super(scope);
128
- this.callName = callName;
129
- }
130
- visitFunction(node: Function): void {
131
- if (node.identifier.value === this.callName)
132
- throw new StopTraversalException();
133
- }
134
- visitMethod(node: Method): void {
135
- if (node.identifier.value === this.callName)
136
- throw new StopTraversalException();
137
- }
138
- visitProcedure(node: Procedure): void {
139
- if (node.identifier.value === this.callName)
140
- throw new StopTraversalException();
141
- }
142
- visitFact(node: Fact): void {
143
- if (node.identifier.value === this.callName)
144
- throw new StopTraversalException();
145
- }
146
- visitRule(node: Rule): void {
147
- if (node.identifier.value === this.callName)
148
- throw new StopTraversalException();
149
- }
150
- }
151
- @AutoScoped
152
- export class DeclaresComputationWithArity extends ScopedVisitor {
153
- private readonly targetArity: number;
154
- constructor(targetArity: string, scope?: string) {
155
- super(scope);
156
- this.targetArity = Number(targetArity);
157
- }
158
- visitFunction(node: Function): void {
159
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
160
- throw new StopTraversalException();
161
- }
162
- visitMethod(node: Method): void {
163
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
164
- throw new StopTraversalException();
165
- }
166
- visitProcedure(node: Procedure): void {
167
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
168
- throw new StopTraversalException();
169
- }
170
- visitFact(node: Fact): void {
171
- if (node.patterns.length === this.targetArity)
172
- throw new StopTraversalException();
173
- }
174
- visitRule(node: Rule): void {
175
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
176
- throw new StopTraversalException();
177
- }
178
- }
179
- export class DeclaresEntryPoint extends TraverseVisitor {
180
- visitEntryPoint(node: EntryPoint): void {
181
- throw new StopTraversalException();
182
- }
183
- }
184
- @AutoScoped
185
- export class DeclaresFunction extends ScopedVisitor {
186
- private readonly targetBinding: string;
187
- constructor(targetBinding: string, scope?: string) {
188
- super(scope);
189
- this.targetBinding = targetBinding;
190
- }
191
- visitFunction(node: Function): void {
192
- if (node.identifier.value === this.targetBinding)
193
- throw new StopTraversalException();
194
- }
195
- }
196
-
197
- @AutoScoped
198
- export class DeclaresRecursively extends ScopedVisitor {
199
- private readonly targetBinding: string;
200
- constructor(targetBinding: string, scope?: string) {
201
- super(scope);
202
- this.targetBinding = targetBinding;
203
- }
204
- visitFunction(node: Function): void {
205
- super.visitFunction(node);
206
- this.visitNested(node);
207
- }
208
- visitMethod(node: Method): void {
209
- super.visitMethod(node);
210
- this.visitNested(node);
211
- }
212
- visitProcedure(node: Procedure): void {
213
- super.visitProcedure(node);
214
- this.visitNested(node);
215
- }
216
- visitFact(node: Fact): void {
217
- super.visitFact(node);
218
- this.visitNested(node);
219
- }
220
- visitRule(node: Rule): void {
221
- super.visitRule(node);
222
- this.visitNested(node);
223
- }
224
- visitNested(node: ASTNode): void {
225
- if (
226
- "identifier" in node &&
227
- node.identifier instanceof SymbolPrimitive &&
228
- node.identifier.value === this.targetBinding
229
- )
230
- throw new StopTraversalException();
231
- }
232
- }
233
- export class UsesDirectRecursion extends TraverseVisitor {
234
- private isInsideBody: boolean = false;
235
- constructor(private readonly binding: string) {
236
- super();
237
- }
238
-
239
- override visitFunction(node: Function): void {
240
- if (node.identifier.value !== this.binding) return;
241
- this.traverseCollection(node.equations);
242
- }
243
- override visitRule(node: Rule): void {
244
- if (node.identifier.value !== this.binding) return;
245
- this.traverseCollection(node.equations);
246
- }
247
- override visitProcedure(node: Procedure): void {
248
- if (node.identifier.value !== this.binding) return;
249
- this.traverseCollection(node.equations);
250
- }
251
- override visitMethod(node: Method): void {
252
- if (node.identifier.value !== this.binding) return;
253
- this.traverseCollection(node.equations);
254
- }
255
- override visitEquation(node: Equation): void {
256
- this.isInsideBody = true;
257
- try {
258
- if (isUnguardedBody(node.body)) {
259
- node.body.accept(this);
260
- } else {
261
- this.traverseCollection(node.body);
262
- }
263
- } finally {
264
- this.isInsideBody = false;
265
- }
266
- }
267
-
268
- visitSymbolPrimitive(node: SymbolPrimitive): void {
269
- if (this.isInsideBody && node.value === this.binding)
270
- throw new StopTraversalException();
271
- }
272
- }
273
-
274
- export class DeclaresTypeAlias extends TraverseVisitor {
275
- private readonly typeAliasName: string;
276
- constructor(typeAliasName: string) {
277
- super();
278
- this.typeAliasName = typeAliasName;
279
- }
280
- visitTypeAlias(node: TypeAlias): void {
281
- if (node.identifier.value === this.typeAliasName)
282
- throw new StopTraversalException();
283
- }
284
- }
285
- export class DeclaresTypeSignature extends TraverseVisitor {
286
- private readonly targetBinding: string;
287
- constructor(targetBinding: string) {
288
- super();
289
- this.targetBinding = targetBinding;
290
- }
291
- visitTypeSignature(node: TypeSignature): void {
292
- if (node.identifier.value === this.targetBinding)
293
- throw new StopTraversalException();
294
- }
295
- }
296
- @AutoScoped
297
- export class DeclaresVariable extends ScopedVisitor {
298
- private readonly targetBinding: string;
299
- constructor(targetBinding: string, scope?: string) {
300
- super(scope);
301
- this.targetBinding = targetBinding;
302
- }
303
- visitVariable(node: Variable): void {
304
- if (node.identifier.value === this.targetBinding)
305
- throw new StopTraversalException();
306
- }
307
- }
308
- @AutoScoped
309
- export class Raises extends ScopedVisitor {
310
- constructor(scope: string) {
311
- super(scope);
312
- }
313
- visitRaise(node: Raise): void {
314
- throw new StopTraversalException();
315
- }
316
- }
317
- @AutoScoped
318
- export class Uses extends ScopedVisitor {
319
- private readonly targetBinding: string;
320
- constructor(targetBinding: string, scope?: string) {
321
- super(scope);
322
- this.targetBinding = targetBinding;
323
- }
324
- visitSymbolPrimitive(node: SymbolPrimitive): void {
325
- if (node.value === this.targetBinding) throw new StopTraversalException();
326
- }
327
- }
328
- @AutoScoped
329
- export class UsesArithmetic extends ScopedVisitor {
330
- constructor(scope?: string) {
331
- super(scope);
332
- }
333
- visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation): void {
334
- throw new StopTraversalException();
335
- }
336
- visitArithmeticUnaryOperation(node: ArithmeticUnaryOperation): void {
337
- throw new StopTraversalException();
338
- }
339
- }
340
- @AutoScoped
341
- export class UsesConditional extends ScopedVisitor {
342
- visitIf(node: If): void {
343
- throw new StopTraversalException();
344
- }
345
- }
346
- @AutoScoped
347
- export class UsesLogic extends ScopedVisitor {
348
- constructor(scope?: string) {
349
- super(scope);
350
- }
351
- visitLogicalBinaryOperation(node: LogicalBinaryOperation): void {
352
- throw new StopTraversalException();
353
- }
354
- visitLogicalUnaryOperation(node: LogicalUnaryOperation): void {
355
- throw new StopTraversalException();
356
- }
357
- }
358
- @AutoScoped
359
- export class UsesPrint extends ScopedVisitor {
360
- constructor(scope?: string) {
361
- super(scope);
362
- }
363
- visitPrint(node: Print): void {
364
- throw new StopTraversalException();
365
- }
366
- }
367
- @AutoScoped
368
- export class UsesType extends ScopedVisitor {
369
- private readonly targetBinding: string;
370
- constructor(targetBinding: string, scope?: string) {
371
- super(scope);
372
- this.targetBinding = targetBinding;
373
- }
374
- visitTypeSignature(node: TypeSignature): void {
375
- node.body.accept(this);
376
- }
377
- visitSimpleType(node: SimpleType): void {
378
- if (node.value === this.targetBinding) throw new StopTraversalException();
379
- }
380
- visitTypeVar(node: TypeVar): void {
381
- if (node.value === this.targetBinding) throw new StopTraversalException();
382
- }
383
- }
384
- @AutoScoped
385
- export class HasBinding extends ScopedVisitor {
386
- visitFunction(node: Function): void {
387
- throw new StopTraversalException();
388
- }
389
- visitObject(node: Object): void {
390
- throw new StopTraversalException();
391
- }
392
- visitClass(node: Class): void {
393
- throw new StopTraversalException();
394
- }
395
- visitRule(node: Rule): void {
396
- throw new StopTraversalException();
397
- }
398
- visitFact(node: Fact): void {
399
- throw new StopTraversalException();
400
- }
401
- visitTypeAlias(node: TypeAlias): void {
402
- throw new StopTraversalException();
403
- }
404
- visitTypeSignature(node: TypeSignature): void {
405
- throw new StopTraversalException();
406
- }
407
- visitRecord(node: RecordNode): void {
408
- throw new StopTraversalException();
409
- }
410
- }
411
-
412
- export class SubordinatesDeclarationsTo extends TraverseVisitor {
413
- constructor(private childName: string, private parentName: string) {
414
- super();
415
- }
416
-
417
- visitFunction(node: Function): void {
418
- if (node.identifier.value === this.parentName) {
419
- const childFinder = new Declares(this.childName);
420
- node.equations.forEach((eq) => eq.accept(childFinder)); // we expect that this will throw if find the subordinated decl
421
- } else {
422
- super.visitFunction(node);
423
- }
424
- }
425
- }
426
-
427
- export class SubordinatesDeclarationsToEntryPoint extends TraverseVisitor {
428
- constructor(private childName: string) {
429
- super();
430
- }
431
-
432
- visitEntryPoint(node: EntryPoint): void {
433
- const childFinder = new Declares(this.childName);
434
- node.expression.statements.forEach((stmt) => stmt.accept(childFinder));
435
- }
436
- }
437
-
438
- export class TypesAs extends TraverseVisitor {
439
- constructor(private typeName: string, private bindingName: string) {
440
- super();
441
- }
442
-
443
- visitTypeSignature(node: TypeSignature): void {
444
- if (node.identifier.value === this.bindingName) {
445
- const actualType = node.body.toString();
446
- if (
447
- actualType.replace(/\s+/g, " ").trim() ===
448
- this.typeName.replace(/\s+/g, " ").trim()
449
- ) {
450
- throw new StopTraversalException();
451
- }
452
- }
453
- }
454
- }
455
-
456
- export class TypesParameterAs extends TraverseVisitor {
457
- constructor(
458
- private paramIndex: number,
459
- private typeName: string,
460
- private bindingName: string
461
- ) {
462
- super();
463
- }
464
-
465
- visitTypeSignature(node: TypeSignature): void {
466
- if (node.identifier.value === this.bindingName) {
467
- if (node.body instanceof ParameterizedType) {
468
- const paramType = node.body.inputs[this.paramIndex];
469
- if (paramType) {
470
- const actualType = paramType.toString();
471
- if (
472
- actualType.replace(/\s+/g, " ").trim() ===
473
- this.typeName.replace(/\s+/g, " ").trim()
474
- ) {
475
- throw new StopTraversalException();
476
- }
477
- }
478
- }
479
- }
480
- }
481
- }
482
-
483
- export class TypesReturnAs extends TraverseVisitor {
484
- constructor(private typeName: string, private bindingName: string) {
485
- super();
486
- }
487
-
488
- visitTypeSignature(node: TypeSignature): void {
489
- if (node.identifier.value === this.bindingName) {
490
- if (node.body instanceof ParameterizedType) {
491
- const actualType = node.body.returnType.toString();
492
- if (
493
- actualType.replace(/\s+/g, " ").trim() ===
494
- this.typeName.replace(/\s+/g, " ").trim()
495
- ) {
496
- throw new StopTraversalException();
497
- }
498
- }
499
- }
500
- }
501
- }
502
-
503
- @AutoScoped
504
- export class Rescues extends ScopedVisitor {
505
- constructor(private exceptionName: string, scope?: string) {
506
- super(scope);
507
- }
508
- visitCatch(node: Catch): void {
509
- for (const pattern of node.patterns) {
510
- if (
511
- pattern instanceof VariablePattern &&
512
- pattern.name.value === this.exceptionName
513
- ) {
514
- throw new StopTraversalException();
515
- }
516
- }
517
- }
518
- }
519
-
520
- @AutoScoped
521
- export class UsesExceptionHandling extends ScopedVisitor {
522
- constructor(scope?: string) {
523
- super(scope);
524
- }
525
- visitTry(node: Try): void {
526
- throw new StopTraversalException();
527
- }
528
- }
529
- @AutoScoped
530
- export class UsesExceptions extends ScopedVisitor {
531
- constructor(scope?: string) {
532
- super(scope);
533
- }
534
- visitTry(node: Try): void {
535
- return new UsesExceptionHandling(this.binding).visitTry(node);
536
- }
537
- visitRaise(node: Raise): void {
538
- throw new StopTraversalException();
539
- }
540
- }
541
-
542
- export const genericInspections: Record<string, VisitorConstructor> = {
543
- Assigns: Assigns,
544
- Calls: Calls,
545
- Declares: Declares,
546
- DeclaresComputation: DeclaresComputation,
547
- DeclaresComputationWithArity: DeclaresComputationWithArity,
548
- HasArity: DeclaresComputationWithArity,
549
- DeclaresEntryPoint: DeclaresEntryPoint,
550
- DeclaresFunction: DeclaresFunction,
551
- DeclaresRecursively: DeclaresRecursively,
552
- UsesDirectRecursion: UsesDirectRecursion,
553
- DeclaresTypeAlias: DeclaresTypeAlias,
554
- DeclaresTypeSignature: DeclaresTypeSignature,
555
- HasTypeSignature: DeclaresTypeSignature,
556
- DeclaresVariable: DeclaresVariable,
557
- Raises: Raises,
558
- Uses: Uses,
559
- HasUsage: Uses,
560
- UsesArithmetic: UsesArithmetic,
561
- SubordinatesDeclarationsTo: SubordinatesDeclarationsTo,
562
- SubordinatesDeclarationsToEntryPoint: SubordinatesDeclarationsToEntryPoint,
563
- TypesAs: TypesAs,
564
- TypesParameterAs: TypesParameterAs,
565
- TypesReturnAs: TypesReturnAs,
566
- UsesConditional: UsesConditional,
567
- HasConditional: UsesConditional,
568
- Rescues: Rescues,
569
- UsesExceptionHandling: UsesExceptionHandling,
570
- UsesExceptions: UsesExceptions,
571
- UsesIf: UsesConditional,
572
- UsesLogic: UsesLogic,
573
- UsesMath: UsesArithmetic,
574
- UsesPrint: UsesPrint,
575
- UsesType: UsesType,
576
- HasBinding: HasBinding,
577
- };
1
+ import {
2
+ Application,
3
+ ArithmeticBinaryOperation,
4
+ ArithmeticUnaryOperation,
5
+ Assignment,
6
+ ASTNode,
7
+ Attribute,
8
+ Call,
9
+ Catch,
10
+ Class,
11
+ EntryPoint,
12
+ Equation,
13
+ Fact,
14
+ Function,
15
+ If,
16
+ LogicalBinaryOperation,
17
+ LogicalUnaryOperation,
18
+ Method,
19
+ NativeBody,
20
+ Object,
21
+ ParameterizedType,
22
+ Print,
23
+ Procedure,
24
+ Raise,
25
+ Record as RecordNode,
26
+ Rule,
27
+ SimpleType,
28
+ StopTraversalException,
29
+ SymbolPrimitive,
30
+ Try,
31
+ TypeAlias,
32
+ TypeSignature,
33
+ TypeVar,
34
+ Variable,
35
+ VariablePattern,
36
+ } from "yukigo-ast";
37
+ import {
38
+ VisitorConstructor,
39
+ ScopedVisitor,
40
+ InspectionVisitor,
41
+ AutoScoped,
42
+ } from "../../utils.js";
43
+
44
+ @AutoScoped
45
+ export class Assigns extends ScopedVisitor {
46
+ private readonly targetIdentifier: string;
47
+ constructor(targetIdentifier: string, scope?: string) {
48
+ super(scope);
49
+ this.targetIdentifier = targetIdentifier;
50
+ }
51
+ visitVariable(node: Variable): void {
52
+ if (node.identifier.value === this.targetIdentifier)
53
+ throw new StopTraversalException();
54
+ }
55
+ visitAttribute(node: Attribute): void {
56
+ if (node.identifier.value === this.targetIdentifier)
57
+ throw new StopTraversalException();
58
+ }
59
+ visitAssignment(node: Assignment): void {
60
+ if (node.identifier.value === this.targetIdentifier)
61
+ throw new StopTraversalException();
62
+ }
63
+ }
64
+ @AutoScoped
65
+ export class Calls extends ScopedVisitor {
66
+ private readonly targetCallee: string;
67
+ constructor(targetCallee: string, scope?: string) {
68
+ super(scope);
69
+ this.targetCallee = targetCallee;
70
+ }
71
+ visitCall(node: Call): void {
72
+ if (node.callee.value === this.targetCallee)
73
+ throw new StopTraversalException();
74
+ }
75
+ }
76
+ @AutoScoped
77
+ export class Declares extends ScopedVisitor {
78
+ private readonly targetIdentifier: string;
79
+
80
+ constructor(targetIdentifier: string, scopeName?: string) {
81
+ super(scopeName);
82
+ this.targetIdentifier = targetIdentifier;
83
+ }
84
+
85
+ private check(node: { identifier: SymbolPrimitive }): void {
86
+ if (node.identifier.value === this.targetIdentifier)
87
+ throw new StopTraversalException();
88
+ }
89
+
90
+ visitFunction(node: Function): void {
91
+ if (this.inScope) this.check(node);
92
+ super.visitFunction(node);
93
+ }
94
+
95
+ visitMethod(node: Method): void {
96
+ if (this.inScope) this.check(node);
97
+ super.visitMethod(node);
98
+ }
99
+
100
+ visitProcedure(node: Procedure): void {
101
+ if (this.inScope) this.check(node);
102
+ super.visitProcedure(node);
103
+ }
104
+
105
+ visitRule(node: Rule): void {
106
+ if (this.inScope) this.check(node);
107
+ super.visitRule(node);
108
+ }
109
+
110
+ visitFact(node: Fact): void {
111
+ if (this.inScope) this.check(node);
112
+ super.visitFact(node);
113
+ }
114
+
115
+ visitVariable(node: Variable): void {
116
+ this.check(node);
117
+ }
118
+
119
+ visitAttribute(node: Attribute): void {
120
+ this.check(node);
121
+ }
122
+
123
+ visitTypeAlias(node: TypeAlias): void {
124
+ this.check(node);
125
+ }
126
+
127
+ visitTypeSignature(node: TypeSignature): void {
128
+ this.check(node);
129
+ }
130
+ }
131
+ @AutoScoped
132
+ export class DeclaresComputation extends ScopedVisitor {
133
+ private readonly callName: string;
134
+ constructor(callName: string, scope?: string) {
135
+ super(scope);
136
+ this.callName = callName;
137
+ }
138
+ visitFunction(node: Function): void {
139
+ if (node.identifier.value === this.callName)
140
+ throw new StopTraversalException();
141
+ }
142
+ visitMethod(node: Method): void {
143
+ if (node.identifier.value === this.callName)
144
+ throw new StopTraversalException();
145
+ }
146
+ visitProcedure(node: Procedure): void {
147
+ if (node.identifier.value === this.callName)
148
+ throw new StopTraversalException();
149
+ }
150
+ visitFact(node: Fact): void {
151
+ if (node.identifier.value === this.callName)
152
+ throw new StopTraversalException();
153
+ }
154
+ visitRule(node: Rule): void {
155
+ if (node.identifier.value === this.callName)
156
+ throw new StopTraversalException();
157
+ }
158
+ }
159
+ @AutoScoped
160
+ export class DeclaresComputationWithArity extends ScopedVisitor {
161
+ private readonly targetArity: number;
162
+ constructor(targetArity: string, scope?: string) {
163
+ super(scope);
164
+ this.targetArity = Number(targetArity);
165
+ }
166
+ visitFunction(node: Function): void {
167
+ if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
168
+ throw new StopTraversalException();
169
+ }
170
+ visitMethod(node: Method): void {
171
+ if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
172
+ throw new StopTraversalException();
173
+ }
174
+ visitProcedure(node: Procedure): void {
175
+ if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
176
+ throw new StopTraversalException();
177
+ }
178
+ visitFact(node: Fact): void {
179
+ if (node.patterns.length === this.targetArity)
180
+ throw new StopTraversalException();
181
+ }
182
+ visitRule(node: Rule): void {
183
+ if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
184
+ throw new StopTraversalException();
185
+ }
186
+ }
187
+ export class DeclaresEntryPoint extends InspectionVisitor {
188
+ visitEntryPoint(node: EntryPoint): void {
189
+ throw new StopTraversalException();
190
+ }
191
+ }
192
+ @AutoScoped
193
+ export class DeclaresFunction extends ScopedVisitor {
194
+ private readonly targetBinding: string;
195
+ constructor(targetBinding: string, scope?: string) {
196
+ super(scope);
197
+ this.targetBinding = targetBinding;
198
+ }
199
+ visitFunction(node: Function): void {
200
+ if (node.identifier.value === this.targetBinding)
201
+ throw new StopTraversalException();
202
+ }
203
+ }
204
+
205
+ type CallableDeclaration = Function | Method | Procedure | Fact | Rule;
206
+ @AutoScoped
207
+ export class DeclaresRecursively extends ScopedVisitor {
208
+ private readonly targetBinding: SymbolPrimitive;
209
+ constructor(targetBinding: string, scope?: string) {
210
+ super(scope);
211
+ this.targetBinding = new SymbolPrimitive(targetBinding);
212
+ }
213
+ visitFunction(node: Function): void {
214
+ super.visitFunction(node);
215
+ this.visitNested(node);
216
+ }
217
+ visitMethod(node: Method): void {
218
+ super.visitMethod(node);
219
+ this.visitNested(node);
220
+ }
221
+ visitProcedure(node: Procedure): void {
222
+ super.visitProcedure(node);
223
+ this.visitNested(node);
224
+ }
225
+ visitFact(node: Fact): void {
226
+ super.visitFact(node);
227
+ this.visitNested(node);
228
+ }
229
+ visitRule(node: Rule): void {
230
+ super.visitRule(node);
231
+ this.visitNested(node);
232
+ }
233
+ visitNested(node: CallableDeclaration): void {
234
+ const hasOwnIdentifier = node.identifier.equals(this.targetBinding);
235
+ if (hasOwnIdentifier) throw new StopTraversalException();
236
+ }
237
+ }
238
+ export class HasDirectRecursion extends InspectionVisitor {
239
+ private isInsideBody: boolean = false;
240
+ constructor(private readonly binding: string) {
241
+ super();
242
+ }
243
+
244
+ override visitFunction(node: Function): void {
245
+ if (node.identifier.value !== this.binding) return;
246
+ this.traverseCollection(node.equations);
247
+ }
248
+ override visitRule(node: Rule): void {
249
+ if (node.identifier.value !== this.binding) return;
250
+ this.traverseCollection(node.equations);
251
+ }
252
+ override visitProcedure(node: Procedure): void {
253
+ if (node.identifier.value !== this.binding) return;
254
+ this.traverseCollection(node.equations);
255
+ }
256
+ override visitMethod(node: Method): void {
257
+ if (node.identifier.value !== this.binding) return;
258
+ this.traverseCollection(node.equations);
259
+ }
260
+ override visitEquation(node: Equation): void {
261
+ this.isInsideBody = true;
262
+ try {
263
+ if (node.body instanceof NativeBody) return;
264
+ node.body.accept(this);
265
+ } finally {
266
+ this.isInsideBody = false;
267
+ }
268
+ }
269
+
270
+ visitSymbolPrimitive(node: SymbolPrimitive): void {
271
+ if (this.isInsideBody && node.value === this.binding)
272
+ throw new StopTraversalException();
273
+ }
274
+ }
275
+
276
+ export class DeclaresTypeAlias extends InspectionVisitor {
277
+ private readonly typeAliasName: string;
278
+ constructor(typeAliasName: string) {
279
+ super();
280
+ this.typeAliasName = typeAliasName;
281
+ }
282
+ visitTypeAlias(node: TypeAlias): void {
283
+ if (node.identifier.value === this.typeAliasName)
284
+ throw new StopTraversalException();
285
+ }
286
+ }
287
+ export class DeclaresTypeSignature extends InspectionVisitor {
288
+ private readonly targetBinding: string;
289
+ constructor(targetBinding: string) {
290
+ super();
291
+ this.targetBinding = targetBinding;
292
+ }
293
+ visitTypeSignature(node: TypeSignature): void {
294
+ if (node.identifier.value === this.targetBinding)
295
+ throw new StopTraversalException();
296
+ }
297
+ }
298
+ @AutoScoped
299
+ export class DeclaresVariable extends ScopedVisitor {
300
+ private readonly targetBinding: string;
301
+ constructor(targetBinding: string, scope?: string) {
302
+ super(scope);
303
+ this.targetBinding = targetBinding;
304
+ }
305
+ visitVariable(node: Variable): void {
306
+ if (node.identifier.value === this.targetBinding)
307
+ throw new StopTraversalException();
308
+ }
309
+ }
310
+ @AutoScoped
311
+ export class Raises extends ScopedVisitor {
312
+ constructor(scope: string) {
313
+ super(scope);
314
+ }
315
+ visitRaise(node: Raise): void {
316
+ throw new StopTraversalException();
317
+ }
318
+ }
319
+ @AutoScoped
320
+ export class Uses extends ScopedVisitor {
321
+ private readonly targetBinding: string;
322
+ constructor(targetBinding: string, scope?: string) {
323
+ super(scope);
324
+ this.targetBinding = targetBinding;
325
+ }
326
+ visitSymbolPrimitive(node: SymbolPrimitive): void {
327
+ if (node.value === this.targetBinding) throw new StopTraversalException();
328
+ }
329
+ }
330
+ @AutoScoped
331
+ export class UsesArithmetic extends ScopedVisitor {
332
+ constructor(scope?: string) {
333
+ super(scope);
334
+ }
335
+ visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation): void {
336
+ throw new StopTraversalException();
337
+ }
338
+ visitArithmeticUnaryOperation(node: ArithmeticUnaryOperation): void {
339
+ throw new StopTraversalException();
340
+ }
341
+ }
342
+ @AutoScoped
343
+ export class UsesConditional extends ScopedVisitor {
344
+ visitIf(node: If): void {
345
+ throw new StopTraversalException();
346
+ }
347
+ }
348
+ @AutoScoped
349
+ export class UsesLogic extends ScopedVisitor {
350
+ constructor(scope?: string) {
351
+ super(scope);
352
+ }
353
+ visitLogicalBinaryOperation(node: LogicalBinaryOperation): void {
354
+ throw new StopTraversalException();
355
+ }
356
+ visitLogicalUnaryOperation(node: LogicalUnaryOperation): void {
357
+ throw new StopTraversalException();
358
+ }
359
+ }
360
+ @AutoScoped
361
+ export class UsesPrint extends ScopedVisitor {
362
+ constructor(scope?: string) {
363
+ super(scope);
364
+ }
365
+ visitPrint(node: Print): void {
366
+ throw new StopTraversalException();
367
+ }
368
+ }
369
+ @AutoScoped
370
+ export class UsesType extends ScopedVisitor {
371
+ private readonly targetBinding: string;
372
+ constructor(targetBinding: string, scope?: string) {
373
+ super(scope);
374
+ this.targetBinding = targetBinding;
375
+ }
376
+ visitTypeSignature(node: TypeSignature): void {
377
+ node.body.accept(this);
378
+ }
379
+ visitSimpleType(node: SimpleType): void {
380
+ if (node.value === this.targetBinding) throw new StopTraversalException();
381
+ }
382
+ visitTypeVar(node: TypeVar): void {
383
+ if (node.value === this.targetBinding) throw new StopTraversalException();
384
+ }
385
+ }
386
+ export class HasBinding extends InspectionVisitor {
387
+ private readonly targetBinding: string;
388
+
389
+ constructor(targetBinding: string) {
390
+ super();
391
+ this.targetBinding = targetBinding;
392
+ }
393
+
394
+ private check(identifier: SymbolPrimitive): void {
395
+ if (identifier && identifier.value === this.targetBinding) {
396
+ throw new StopTraversalException();
397
+ }
398
+ }
399
+
400
+ visitFunction(node: Function): void {
401
+ this.check(node.identifier);
402
+ super.visitFunction(node);
403
+ }
404
+ visitObject(node: Object): void {
405
+ this.check(node.identifier);
406
+ super.visitObject(node);
407
+ }
408
+ visitClass(node: Class): void {
409
+ this.check(node.identifier);
410
+ super.visitClass(node);
411
+ }
412
+ visitRule(node: Rule): void {
413
+ this.check(node.identifier);
414
+ super.visitRule(node);
415
+ }
416
+ visitFact(node: Fact): void {
417
+ this.check(node.identifier);
418
+ super.visitFact(node);
419
+ }
420
+ visitTypeAlias(node: TypeAlias): void {
421
+ this.check(node.identifier);
422
+ super.visitTypeAlias(node);
423
+ }
424
+ visitRecord(node: RecordNode): void {
425
+ this.check(node.name);
426
+ super.visitRecord(node);
427
+ }
428
+ visitVariable(node: Variable): void {
429
+ this.check(node.identifier);
430
+ super.visitVariable(node);
431
+ }
432
+ visitMethod(node: Method): void {
433
+ this.check(node.identifier);
434
+ super.visitMethod(node);
435
+ }
436
+ visitProcedure(node: Procedure): void {
437
+ this.check(node.identifier);
438
+ super.visitProcedure(node);
439
+ }
440
+ }
441
+
442
+ export class SubordinatesDeclarationsTo extends InspectionVisitor {
443
+ constructor(
444
+ private childName: string,
445
+ private parentName: string,
446
+ ) {
447
+ super();
448
+ }
449
+
450
+ visitFunction(node: Function): void {
451
+ if (node.identifier.value === this.parentName) {
452
+ const childFinder = new Declares(this.childName);
453
+ node.equations.forEach((eq) => eq.accept(childFinder)); // we expect that this will throw if find the subordinated decl
454
+ } else {
455
+ super.visitFunction(node);
456
+ }
457
+ }
458
+ }
459
+
460
+ export class SubordinatesDeclarationsToEntryPoint extends InspectionVisitor {
461
+ constructor(private childName: string) {
462
+ super();
463
+ }
464
+
465
+ visitEntryPoint(node: EntryPoint): void {
466
+ const childFinder = new Declares(this.childName);
467
+ node.expression.statements.forEach((stmt) => stmt.accept(childFinder));
468
+ }
469
+ }
470
+
471
+ export class TypesAs extends InspectionVisitor {
472
+ constructor(
473
+ private typeName: string,
474
+ private bindingName: string,
475
+ ) {
476
+ super();
477
+ }
478
+
479
+ visitTypeSignature(node: TypeSignature): void {
480
+ if (node.identifier.value === this.bindingName) {
481
+ const actualType = node.body.toString();
482
+ if (
483
+ actualType.replace(/\s+/g, " ").trim() ===
484
+ this.typeName.replace(/\s+/g, " ").trim()
485
+ ) {
486
+ throw new StopTraversalException();
487
+ }
488
+ }
489
+ }
490
+ }
491
+ function isFormatAgnosticMatch(actual: string, expected: string): boolean {
492
+ const normalize = (str: string) => str.replace(/\s+/g, " ").trim();
493
+ return normalize(actual) === normalize(expected);
494
+ }
495
+ export class TypesParameterAs extends InspectionVisitor {
496
+ constructor(
497
+ private paramIndex: number,
498
+ private typeName: string,
499
+ private bindingName: string,
500
+ ) {
501
+ super();
502
+ }
503
+
504
+ visitTypeSignature(node: TypeSignature): void {
505
+ if (node.identifier.value !== this.bindingName) return;
506
+ if (!node.body.is(ParameterizedType)) return;
507
+ const paramType = node.body.inputs[this.paramIndex];
508
+ if (!paramType) return;
509
+ const actualType = paramType.toString();
510
+ if (isFormatAgnosticMatch(actualType, this.typeName))
511
+ throw new StopTraversalException();
512
+ }
513
+ }
514
+
515
+ export class TypesReturnAs extends InspectionVisitor {
516
+ constructor(
517
+ private typeName: string,
518
+ private bindingName: string,
519
+ ) {
520
+ super();
521
+ }
522
+
523
+ visitTypeSignature(node: TypeSignature): void {
524
+ if (node.identifier.value !== this.bindingName) return;
525
+ if (node.body.is(ParameterizedType)) {
526
+ const actualType = node.body.returnType.toString();
527
+ if (isFormatAgnosticMatch(actualType, this.typeName))
528
+ throw new StopTraversalException();
529
+ }
530
+ }
531
+ }
532
+
533
+ @AutoScoped
534
+ export class Rescues extends ScopedVisitor {
535
+ constructor(
536
+ private exceptionName: string,
537
+ scope?: string,
538
+ ) {
539
+ super(scope);
540
+ }
541
+ visitCatch(node: Catch): void {
542
+ for (const pattern of node.patterns) {
543
+ const capturesExceptionAs =
544
+ pattern.is(VariablePattern) &&
545
+ pattern.name.value === this.exceptionName;
546
+ if (capturesExceptionAs) {
547
+ throw new StopTraversalException();
548
+ }
549
+ }
550
+ }
551
+ }
552
+
553
+ @AutoScoped
554
+ export class UsesExceptionHandling extends ScopedVisitor {
555
+ constructor(scope?: string) {
556
+ super(scope);
557
+ }
558
+ visitTry(node: Try): void {
559
+ throw new StopTraversalException();
560
+ }
561
+ }
562
+ @AutoScoped
563
+ export class UsesExceptions extends ScopedVisitor {
564
+ constructor(scope?: string) {
565
+ super(scope);
566
+ }
567
+ visitTry(node: Try): void {
568
+ return new UsesExceptionHandling(this.binding).visitTry(node);
569
+ }
570
+ visitRaise(node: Raise): void {
571
+ throw new StopTraversalException();
572
+ }
573
+ }
574
+
575
+ export const genericInspections: Record<string, VisitorConstructor> = {
576
+ Assigns: Assigns,
577
+ Calls: Calls,
578
+ Declares: Declares,
579
+ DeclaresComputation: DeclaresComputation,
580
+ DeclaresComputationWithArity: DeclaresComputationWithArity,
581
+ HasArity: DeclaresComputationWithArity,
582
+ DeclaresEntryPoint: DeclaresEntryPoint,
583
+ DeclaresFunction: DeclaresFunction,
584
+ DeclaresRecursively: DeclaresRecursively,
585
+ HasDirectRecursion: HasDirectRecursion,
586
+ DeclaresTypeAlias: DeclaresTypeAlias,
587
+ DeclaresTypeSignature: DeclaresTypeSignature,
588
+ HasTypeSignature: DeclaresTypeSignature,
589
+ DeclaresVariable: DeclaresVariable,
590
+ Raises: Raises,
591
+ Uses: Uses,
592
+ HasUsage: Uses,
593
+ UsesArithmetic: UsesArithmetic,
594
+ SubordinatesDeclarationsTo: SubordinatesDeclarationsTo,
595
+ SubordinatesDeclarationsToEntryPoint: SubordinatesDeclarationsToEntryPoint,
596
+ TypesAs: TypesAs,
597
+ TypesParameterAs: TypesParameterAs,
598
+ TypesReturnAs: TypesReturnAs,
599
+ UsesConditional: UsesConditional,
600
+ HasConditional: UsesConditional,
601
+ Rescues: Rescues,
602
+ UsesExceptionHandling: UsesExceptionHandling,
603
+ UsesExceptions: UsesExceptions,
604
+ UsesIf: UsesConditional,
605
+ UsesLogic: UsesLogic,
606
+ UsesMath: UsesArithmetic,
607
+ UsesPrint: UsesPrint,
608
+ UsesType: UsesType,
609
+ HasBinding: HasBinding,
610
+ };