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,581 +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
- visitTypeSignature(node: TypeSignature): void {
124
- this.check(node);
125
- }
126
- }
127
- @AutoScoped
128
- export class DeclaresComputation extends ScopedVisitor {
129
- private readonly callName: string;
130
- constructor(callName: string, scope?: string) {
131
- super(scope);
132
- this.callName = callName;
133
- }
134
- visitFunction(node: Function): void {
135
- if (node.identifier.value === this.callName)
136
- throw new StopTraversalException();
137
- }
138
- visitMethod(node: Method): void {
139
- if (node.identifier.value === this.callName)
140
- throw new StopTraversalException();
141
- }
142
- visitProcedure(node: Procedure): void {
143
- if (node.identifier.value === this.callName)
144
- throw new StopTraversalException();
145
- }
146
- visitFact(node: Fact): void {
147
- if (node.identifier.value === this.callName)
148
- throw new StopTraversalException();
149
- }
150
- visitRule(node: Rule): void {
151
- if (node.identifier.value === this.callName)
152
- throw new StopTraversalException();
153
- }
154
- }
155
- @AutoScoped
156
- export class DeclaresComputationWithArity extends ScopedVisitor {
157
- private readonly targetArity: number;
158
- constructor(targetArity: string, scope?: string) {
159
- super(scope);
160
- this.targetArity = Number(targetArity);
161
- }
162
- visitFunction(node: Function): void {
163
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
164
- throw new StopTraversalException();
165
- }
166
- visitMethod(node: Method): void {
167
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
168
- throw new StopTraversalException();
169
- }
170
- visitProcedure(node: Procedure): void {
171
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
172
- throw new StopTraversalException();
173
- }
174
- visitFact(node: Fact): void {
175
- if (node.patterns.length === this.targetArity)
176
- throw new StopTraversalException();
177
- }
178
- visitRule(node: Rule): void {
179
- if (node.equations.some((eq) => eq.patterns.length === this.targetArity))
180
- throw new StopTraversalException();
181
- }
182
- }
183
- export class DeclaresEntryPoint extends TraverseVisitor {
184
- visitEntryPoint(node: EntryPoint): void {
185
- throw new StopTraversalException();
186
- }
187
- }
188
- @AutoScoped
189
- export class DeclaresFunction extends ScopedVisitor {
190
- private readonly targetBinding: string;
191
- constructor(targetBinding: string, scope?: string) {
192
- super(scope);
193
- this.targetBinding = targetBinding;
194
- }
195
- visitFunction(node: Function): void {
196
- if (node.identifier.value === this.targetBinding)
197
- throw new StopTraversalException();
198
- }
199
- }
200
-
201
- @AutoScoped
202
- export class DeclaresRecursively extends ScopedVisitor {
203
- private readonly targetBinding: string;
204
- constructor(targetBinding: string, scope?: string) {
205
- super(scope);
206
- this.targetBinding = targetBinding;
207
- }
208
- visitFunction(node: Function): void {
209
- super.visitFunction(node);
210
- this.visitNested(node);
211
- }
212
- visitMethod(node: Method): void {
213
- super.visitMethod(node);
214
- this.visitNested(node);
215
- }
216
- visitProcedure(node: Procedure): void {
217
- super.visitProcedure(node);
218
- this.visitNested(node);
219
- }
220
- visitFact(node: Fact): void {
221
- super.visitFact(node);
222
- this.visitNested(node);
223
- }
224
- visitRule(node: Rule): void {
225
- super.visitRule(node);
226
- this.visitNested(node);
227
- }
228
- visitNested(node: ASTNode): void {
229
- if (
230
- "identifier" in node &&
231
- node.identifier instanceof SymbolPrimitive &&
232
- node.identifier.value === this.targetBinding
233
- )
234
- throw new StopTraversalException();
235
- }
236
- }
237
- export class HasDirectRecursion extends TraverseVisitor {
238
- private isInsideBody: boolean = false;
239
- constructor(private readonly binding: string) {
240
- super();
241
- }
242
-
243
- override visitFunction(node: Function): void {
244
- if (node.identifier.value !== this.binding) return;
245
- this.traverseCollection(node.equations);
246
- }
247
- override visitRule(node: Rule): void {
248
- if (node.identifier.value !== this.binding) return;
249
- this.traverseCollection(node.equations);
250
- }
251
- override visitProcedure(node: Procedure): void {
252
- if (node.identifier.value !== this.binding) return;
253
- this.traverseCollection(node.equations);
254
- }
255
- override visitMethod(node: Method): void {
256
- if (node.identifier.value !== this.binding) return;
257
- this.traverseCollection(node.equations);
258
- }
259
- override visitEquation(node: Equation): void {
260
- this.isInsideBody = true;
261
- try {
262
- if (isUnguardedBody(node.body)) {
263
- node.body.accept(this);
264
- } else {
265
- this.traverseCollection(node.body);
266
- }
267
- } finally {
268
- this.isInsideBody = false;
269
- }
270
- }
271
-
272
- visitSymbolPrimitive(node: SymbolPrimitive): void {
273
- if (this.isInsideBody && node.value === this.binding)
274
- throw new StopTraversalException();
275
- }
276
- }
277
-
278
- export class DeclaresTypeAlias extends TraverseVisitor {
279
- private readonly typeAliasName: string;
280
- constructor(typeAliasName: string) {
281
- super();
282
- this.typeAliasName = typeAliasName;
283
- }
284
- visitTypeAlias(node: TypeAlias): void {
285
- if (node.identifier.value === this.typeAliasName)
286
- throw new StopTraversalException();
287
- }
288
- }
289
- export class DeclaresTypeSignature extends TraverseVisitor {
290
- private readonly targetBinding: string;
291
- constructor(targetBinding: string) {
292
- super();
293
- this.targetBinding = targetBinding;
294
- }
295
- visitTypeSignature(node: TypeSignature): void {
296
- if (node.identifier.value === this.targetBinding)
297
- throw new StopTraversalException();
298
- }
299
- }
300
- @AutoScoped
301
- export class DeclaresVariable extends ScopedVisitor {
302
- private readonly targetBinding: string;
303
- constructor(targetBinding: string, scope?: string) {
304
- super(scope);
305
- this.targetBinding = targetBinding;
306
- }
307
- visitVariable(node: Variable): void {
308
- if (node.identifier.value === this.targetBinding)
309
- throw new StopTraversalException();
310
- }
311
- }
312
- @AutoScoped
313
- export class Raises extends ScopedVisitor {
314
- constructor(scope: string) {
315
- super(scope);
316
- }
317
- visitRaise(node: Raise): void {
318
- throw new StopTraversalException();
319
- }
320
- }
321
- @AutoScoped
322
- export class Uses extends ScopedVisitor {
323
- private readonly targetBinding: string;
324
- constructor(targetBinding: string, scope?: string) {
325
- super(scope);
326
- this.targetBinding = targetBinding;
327
- }
328
- visitSymbolPrimitive(node: SymbolPrimitive): void {
329
- if (node.value === this.targetBinding) throw new StopTraversalException();
330
- }
331
- }
332
- @AutoScoped
333
- export class UsesArithmetic extends ScopedVisitor {
334
- constructor(scope?: string) {
335
- super(scope);
336
- }
337
- visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation): void {
338
- throw new StopTraversalException();
339
- }
340
- visitArithmeticUnaryOperation(node: ArithmeticUnaryOperation): void {
341
- throw new StopTraversalException();
342
- }
343
- }
344
- @AutoScoped
345
- export class UsesConditional extends ScopedVisitor {
346
- visitIf(node: If): void {
347
- throw new StopTraversalException();
348
- }
349
- }
350
- @AutoScoped
351
- export class UsesLogic extends ScopedVisitor {
352
- constructor(scope?: string) {
353
- super(scope);
354
- }
355
- visitLogicalBinaryOperation(node: LogicalBinaryOperation): void {
356
- throw new StopTraversalException();
357
- }
358
- visitLogicalUnaryOperation(node: LogicalUnaryOperation): void {
359
- throw new StopTraversalException();
360
- }
361
- }
362
- @AutoScoped
363
- export class UsesPrint extends ScopedVisitor {
364
- constructor(scope?: string) {
365
- super(scope);
366
- }
367
- visitPrint(node: Print): void {
368
- throw new StopTraversalException();
369
- }
370
- }
371
- @AutoScoped
372
- export class UsesType extends ScopedVisitor {
373
- private readonly targetBinding: string;
374
- constructor(targetBinding: string, scope?: string) {
375
- super(scope);
376
- this.targetBinding = targetBinding;
377
- }
378
- visitTypeSignature(node: TypeSignature): void {
379
- node.body.accept(this);
380
- }
381
- visitSimpleType(node: SimpleType): void {
382
- if (node.value === this.targetBinding) throw new StopTraversalException();
383
- }
384
- visitTypeVar(node: TypeVar): void {
385
- if (node.value === this.targetBinding) throw new StopTraversalException();
386
- }
387
- }
388
- @AutoScoped
389
- export class HasBinding extends ScopedVisitor {
390
- visitFunction(node: Function): void {
391
- throw new StopTraversalException();
392
- }
393
- visitObject(node: Object): void {
394
- throw new StopTraversalException();
395
- }
396
- visitClass(node: Class): void {
397
- throw new StopTraversalException();
398
- }
399
- visitRule(node: Rule): void {
400
- throw new StopTraversalException();
401
- }
402
- visitFact(node: Fact): void {
403
- throw new StopTraversalException();
404
- }
405
- visitTypeAlias(node: TypeAlias): void {
406
- throw new StopTraversalException();
407
- }
408
- visitTypeSignature(node: TypeSignature): void {
409
- throw new StopTraversalException();
410
- }
411
- visitRecord(node: RecordNode): void {
412
- throw new StopTraversalException();
413
- }
414
- }
415
-
416
- export class SubordinatesDeclarationsTo extends TraverseVisitor {
417
- constructor(private childName: string, private parentName: string) {
418
- super();
419
- }
420
-
421
- visitFunction(node: Function): void {
422
- if (node.identifier.value === this.parentName) {
423
- const childFinder = new Declares(this.childName);
424
- node.equations.forEach((eq) => eq.accept(childFinder)); // we expect that this will throw if find the subordinated decl
425
- } else {
426
- super.visitFunction(node);
427
- }
428
- }
429
- }
430
-
431
- export class SubordinatesDeclarationsToEntryPoint extends TraverseVisitor {
432
- constructor(private childName: string) {
433
- super();
434
- }
435
-
436
- visitEntryPoint(node: EntryPoint): void {
437
- const childFinder = new Declares(this.childName);
438
- node.expression.statements.forEach((stmt) => stmt.accept(childFinder));
439
- }
440
- }
441
-
442
- export class TypesAs extends TraverseVisitor {
443
- constructor(private typeName: string, private bindingName: string) {
444
- super();
445
- }
446
-
447
- visitTypeSignature(node: TypeSignature): void {
448
- if (node.identifier.value === this.bindingName) {
449
- const actualType = node.body.toString();
450
- if (
451
- actualType.replace(/\s+/g, " ").trim() ===
452
- this.typeName.replace(/\s+/g, " ").trim()
453
- ) {
454
- throw new StopTraversalException();
455
- }
456
- }
457
- }
458
- }
459
-
460
- export class TypesParameterAs extends TraverseVisitor {
461
- constructor(
462
- private paramIndex: number,
463
- private typeName: string,
464
- private bindingName: string
465
- ) {
466
- super();
467
- }
468
-
469
- visitTypeSignature(node: TypeSignature): void {
470
- if (node.identifier.value === this.bindingName) {
471
- if (node.body instanceof ParameterizedType) {
472
- const paramType = node.body.inputs[this.paramIndex];
473
- if (paramType) {
474
- const actualType = paramType.toString();
475
- if (
476
- actualType.replace(/\s+/g, " ").trim() ===
477
- this.typeName.replace(/\s+/g, " ").trim()
478
- ) {
479
- throw new StopTraversalException();
480
- }
481
- }
482
- }
483
- }
484
- }
485
- }
486
-
487
- export class TypesReturnAs extends TraverseVisitor {
488
- constructor(private typeName: string, private bindingName: string) {
489
- super();
490
- }
491
-
492
- visitTypeSignature(node: TypeSignature): void {
493
- if (node.identifier.value === this.bindingName) {
494
- if (node.body instanceof ParameterizedType) {
495
- const actualType = node.body.returnType.toString();
496
- if (
497
- actualType.replace(/\s+/g, " ").trim() ===
498
- this.typeName.replace(/\s+/g, " ").trim()
499
- ) {
500
- throw new StopTraversalException();
501
- }
502
- }
503
- }
504
- }
505
- }
506
-
507
- @AutoScoped
508
- export class Rescues extends ScopedVisitor {
509
- constructor(private exceptionName: string, scope?: string) {
510
- super(scope);
511
- }
512
- visitCatch(node: Catch): void {
513
- for (const pattern of node.patterns) {
514
- if (
515
- pattern instanceof VariablePattern &&
516
- pattern.name.value === this.exceptionName
517
- ) {
518
- throw new StopTraversalException();
519
- }
520
- }
521
- }
522
- }
523
-
524
- @AutoScoped
525
- export class UsesExceptionHandling extends ScopedVisitor {
526
- constructor(scope?: string) {
527
- super(scope);
528
- }
529
- visitTry(node: Try): void {
530
- throw new StopTraversalException();
531
- }
532
- }
533
- @AutoScoped
534
- export class UsesExceptions extends ScopedVisitor {
535
- constructor(scope?: string) {
536
- super(scope);
537
- }
538
- visitTry(node: Try): void {
539
- return new UsesExceptionHandling(this.binding).visitTry(node);
540
- }
541
- visitRaise(node: Raise): void {
542
- throw new StopTraversalException();
543
- }
544
- }
545
-
546
- export const genericInspections: Record<string, VisitorConstructor> = {
547
- Assigns: Assigns,
548
- Calls: Calls,
549
- Declares: Declares,
550
- DeclaresComputation: DeclaresComputation,
551
- DeclaresComputationWithArity: DeclaresComputationWithArity,
552
- HasArity: DeclaresComputationWithArity,
553
- DeclaresEntryPoint: DeclaresEntryPoint,
554
- DeclaresFunction: DeclaresFunction,
555
- DeclaresRecursively: DeclaresRecursively,
556
- HasDirectRecursion: HasDirectRecursion,
557
- DeclaresTypeAlias: DeclaresTypeAlias,
558
- DeclaresTypeSignature: DeclaresTypeSignature,
559
- HasTypeSignature: DeclaresTypeSignature,
560
- DeclaresVariable: DeclaresVariable,
561
- Raises: Raises,
562
- Uses: Uses,
563
- HasUsage: Uses,
564
- UsesArithmetic: UsesArithmetic,
565
- SubordinatesDeclarationsTo: SubordinatesDeclarationsTo,
566
- SubordinatesDeclarationsToEntryPoint: SubordinatesDeclarationsToEntryPoint,
567
- TypesAs: TypesAs,
568
- TypesParameterAs: TypesParameterAs,
569
- TypesReturnAs: TypesReturnAs,
570
- UsesConditional: UsesConditional,
571
- HasConditional: UsesConditional,
572
- Rescues: Rescues,
573
- UsesExceptionHandling: UsesExceptionHandling,
574
- UsesExceptions: UsesExceptions,
575
- UsesIf: UsesConditional,
576
- UsesLogic: UsesLogic,
577
- UsesMath: UsesArithmetic,
578
- UsesPrint: UsesPrint,
579
- UsesType: UsesType,
580
- HasBinding: HasBinding,
581
- };
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
+ };