yukigo 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.json +3 -3
- package/CHANGELOG.md +26 -0
- package/README.md +193 -199
- package/dist/analyzer/GraphBuilder.d.ts +29 -0
- package/dist/analyzer/GraphBuilder.js +99 -0
- package/dist/analyzer/index.d.ts +11 -23
- package/dist/analyzer/index.js +100 -58
- package/dist/analyzer/inspections/functional/functional.d.ts +44 -0
- package/dist/analyzer/inspections/functional/functional.js +149 -0
- package/dist/analyzer/inspections/functional/smells.d.ts +16 -0
- package/dist/analyzer/inspections/functional/smells.js +98 -0
- package/dist/analyzer/inspections/{generic.d.ts → generic/generic.d.ts} +70 -43
- package/dist/analyzer/inspections/generic/generic.js +604 -0
- package/dist/analyzer/inspections/generic/smells.d.ts +61 -0
- package/dist/analyzer/inspections/generic/smells.js +349 -0
- package/dist/analyzer/inspections/imperative/imperative.d.ts +35 -0
- package/dist/analyzer/inspections/imperative/imperative.js +109 -0
- package/dist/analyzer/inspections/imperative/smells.d.ts +16 -0
- package/dist/analyzer/inspections/imperative/smells.js +58 -0
- package/dist/analyzer/inspections/logic/logic.d.ts +32 -0
- package/dist/analyzer/inspections/logic/logic.js +96 -0
- package/dist/analyzer/inspections/logic/smells.d.ts +15 -0
- package/dist/analyzer/inspections/logic/smells.js +60 -0
- package/dist/analyzer/inspections/object/object.d.ts +88 -0
- package/dist/analyzer/inspections/object/object.js +319 -0
- package/dist/analyzer/inspections/object/smells.d.ts +30 -0
- package/dist/analyzer/inspections/object/smells.js +135 -0
- package/dist/analyzer/utils.d.ts +26 -4
- package/dist/analyzer/utils.js +71 -13
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/interpreter/components/EnvBuilder.d.ts +9 -5
- package/dist/interpreter/components/EnvBuilder.js +100 -30
- package/dist/interpreter/components/Operations.d.ts +4 -4
- package/dist/interpreter/components/Operations.js +17 -2
- package/dist/interpreter/components/PatternMatcher.d.ts +47 -17
- package/dist/interpreter/components/PatternMatcher.js +264 -119
- package/dist/interpreter/components/RuntimeContext.d.ts +35 -0
- package/dist/interpreter/components/RuntimeContext.js +93 -0
- package/dist/interpreter/components/TestRunner.d.ts +18 -0
- package/dist/interpreter/components/TestRunner.js +103 -0
- package/dist/interpreter/components/Visitor.d.ts +63 -57
- package/dist/interpreter/components/Visitor.js +508 -173
- package/dist/interpreter/components/logic/LogicEngine.d.ts +29 -0
- package/dist/interpreter/components/logic/LogicEngine.js +259 -0
- package/dist/interpreter/components/logic/LogicResolver.d.ts +53 -0
- package/dist/interpreter/components/logic/LogicResolver.js +471 -0
- package/dist/interpreter/components/logic/LogicTranslator.d.ts +14 -0
- package/dist/interpreter/components/logic/LogicTranslator.js +99 -0
- package/dist/interpreter/components/runtimes/FunctionRuntime.d.ts +12 -0
- package/dist/interpreter/components/runtimes/FunctionRuntime.js +147 -0
- package/dist/interpreter/components/runtimes/LazyRuntime.d.ts +19 -0
- package/dist/interpreter/components/runtimes/LazyRuntime.js +269 -0
- package/dist/interpreter/components/runtimes/ObjectRuntime.d.ts +35 -0
- package/dist/interpreter/components/runtimes/ObjectRuntime.js +126 -0
- package/dist/interpreter/entities.d.ts +105 -0
- package/dist/interpreter/entities.js +96 -0
- package/dist/interpreter/errors.d.ts +1 -1
- package/dist/interpreter/index.d.ts +4 -12
- package/dist/interpreter/index.js +10 -13
- package/dist/interpreter/trampoline.d.ts +17 -0
- package/dist/interpreter/trampoline.js +38 -0
- package/dist/interpreter/utils.d.ts +4 -7
- package/dist/interpreter/utils.js +25 -17
- package/dist/tester/index.d.ts +25 -0
- package/dist/tester/index.js +108 -0
- package/dist/utils/helpers.d.ts +0 -4
- package/dist/utils/helpers.js +20 -24
- package/package.json +2 -2
- package/src/analyzer/GraphBuilder.ts +142 -0
- package/src/analyzer/index.ts +185 -132
- package/src/analyzer/inspections/functional/functional.ts +121 -0
- package/src/analyzer/inspections/functional/smells.ts +102 -0
- package/src/analyzer/inspections/{generic.ts → generic/generic.ts} +581 -499
- package/src/analyzer/inspections/generic/smells.ts +365 -0
- package/src/analyzer/inspections/imperative/imperative.ts +101 -0
- package/src/analyzer/inspections/imperative/smells.ts +54 -0
- package/src/analyzer/inspections/logic/logic.ts +90 -0
- package/src/analyzer/inspections/logic/smells.ts +54 -0
- package/src/analyzer/inspections/{object.ts → object/object.ts} +264 -282
- package/src/analyzer/inspections/object/smells.ts +144 -0
- package/src/analyzer/utils.ts +109 -26
- package/src/index.ts +3 -2
- package/src/interpreter/components/EnvBuilder.ts +202 -97
- package/src/interpreter/components/Operations.ts +99 -81
- package/src/interpreter/components/PatternMatcher.ts +475 -254
- package/src/interpreter/components/RuntimeContext.ts +119 -0
- package/src/interpreter/components/TestRunner.ts +151 -0
- package/src/interpreter/components/Visitor.ts +1065 -493
- package/src/interpreter/components/logic/LogicEngine.ts +519 -0
- package/src/interpreter/components/logic/LogicResolver.ts +858 -0
- package/src/interpreter/components/logic/LogicTranslator.ts +149 -0
- package/src/interpreter/components/runtimes/FunctionRuntime.ts +227 -0
- package/src/interpreter/components/runtimes/LazyRuntime.ts +334 -0
- package/src/interpreter/components/runtimes/ObjectRuntime.ts +224 -0
- package/src/interpreter/errors.ts +47 -47
- package/src/interpreter/index.ts +52 -59
- package/src/interpreter/trampoline.ts +71 -0
- package/src/interpreter/utils.ts +84 -79
- package/src/tester/index.ts +128 -0
- package/src/utils/helpers.ts +67 -73
- package/tests/analyzer/functional.spec.ts +207 -221
- package/tests/analyzer/generic.spec.ts +178 -100
- package/tests/analyzer/helpers.spec.ts +83 -83
- package/tests/analyzer/logic.spec.ts +237 -292
- package/tests/analyzer/oop.spec.ts +323 -338
- package/tests/analyzer/transitive.spec.ts +166 -0
- package/tests/interpreter/EnvBuilder.spec.ts +183 -178
- package/tests/interpreter/FunctionRuntime.spec.ts +223 -234
- package/tests/interpreter/LazyRuntime.spec.ts +225 -190
- package/tests/interpreter/LogicEngine.spec.ts +327 -194
- package/tests/interpreter/LogicSubstitution.spec.ts +80 -0
- package/tests/interpreter/ObjectRuntime.spec.ts +606 -0
- package/tests/interpreter/Operations.spec.ts +220 -220
- package/tests/interpreter/PatternSystem.spec.ts +213 -189
- package/tests/interpreter/Tests.spec.ts +122 -0
- package/tests/interpreter/interpreter.spec.ts +991 -937
- package/tests/tester/Tester.spec.ts +153 -0
- package/tsconfig.build.json +15 -7
- package/tsconfig.json +25 -17
- package/dist/analyzer/inspections/functional.d.ts +0 -46
- package/dist/analyzer/inspections/functional.js +0 -123
- package/dist/analyzer/inspections/generic.js +0 -427
- package/dist/analyzer/inspections/imperative.d.ts +0 -37
- package/dist/analyzer/inspections/imperative.js +0 -105
- package/dist/analyzer/inspections/logic.d.ts +0 -49
- package/dist/analyzer/inspections/logic.js +0 -140
- package/dist/analyzer/inspections/object.d.ts +0 -83
- package/dist/analyzer/inspections/object.js +0 -235
- package/dist/interpreter/components/FunctionRuntime.d.ts +0 -8
- package/dist/interpreter/components/FunctionRuntime.js +0 -52
- package/dist/interpreter/components/LazyRuntime.d.ts +0 -7
- package/dist/interpreter/components/LazyRuntime.js +0 -75
- package/dist/interpreter/components/LogicEngine.d.ts +0 -21
- package/dist/interpreter/components/LogicEngine.js +0 -152
- package/dist/interpreter/components/LogicResolver.d.ts +0 -11
- package/dist/interpreter/components/LogicResolver.js +0 -87
- package/src/analyzer/inspections/functional.ts +0 -159
- package/src/analyzer/inspections/imperative.ts +0 -129
- package/src/analyzer/inspections/logic.ts +0 -166
- package/src/interpreter/components/FunctionRuntime.ts +0 -79
- package/src/interpreter/components/LazyRuntime.ts +0 -97
- package/src/interpreter/components/LogicEngine.ts +0 -227
- package/src/interpreter/components/LogicResolver.ts +0 -130
|
@@ -1,338 +1,323 @@
|
|
|
1
|
-
import { expect } from "chai";
|
|
2
|
-
import {
|
|
3
|
-
Class,
|
|
4
|
-
Method,
|
|
5
|
-
Send,
|
|
6
|
-
Self,
|
|
7
|
-
SymbolPrimitive,
|
|
8
|
-
Attribute,
|
|
9
|
-
New,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} from "yukigo-ast";
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
) => {
|
|
67
|
-
return new
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
describe("
|
|
190
|
-
it("should detect
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
1,
|
|
325
|
-
false,
|
|
326
|
-
new Print(new StringPrimitive("This method is Declared"))
|
|
327
|
-
);
|
|
328
|
-
const sendToSelf = new Send(new Self(), createSymbol("declared"), []);
|
|
329
|
-
|
|
330
|
-
const method = createMethod("process", 1, false, sendToSelf);
|
|
331
|
-
|
|
332
|
-
const classNode = createClass("MyClass", [declaredMethod, method]);
|
|
333
|
-
|
|
334
|
-
const visitor = new UsesTemplateMethod();
|
|
335
|
-
expect(executeVisitor(classNode, visitor)).to.eq(false);
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
});
|
|
1
|
+
import { expect } from "chai";
|
|
2
|
+
import {
|
|
3
|
+
Class,
|
|
4
|
+
Method,
|
|
5
|
+
Send,
|
|
6
|
+
Self,
|
|
7
|
+
SymbolPrimitive,
|
|
8
|
+
Attribute,
|
|
9
|
+
New,
|
|
10
|
+
Interface,
|
|
11
|
+
Object as AstObject,
|
|
12
|
+
PrimitiveMethod,
|
|
13
|
+
Implement,
|
|
14
|
+
ASTNode,
|
|
15
|
+
Equation,
|
|
16
|
+
UnguardedBody,
|
|
17
|
+
Sequence,
|
|
18
|
+
NilPrimitive,
|
|
19
|
+
Statement,
|
|
20
|
+
Print,
|
|
21
|
+
StringPrimitive,
|
|
22
|
+
Variable,
|
|
23
|
+
} from "yukigo-ast";
|
|
24
|
+
import { Analyzer, InspectionRule } from "../../src/analyzer/index.js";
|
|
25
|
+
|
|
26
|
+
describe("OOP Inspections", () => {
|
|
27
|
+
const createSymbol = (name: string) => new SymbolPrimitive(name);
|
|
28
|
+
const analyzer = new Analyzer();
|
|
29
|
+
|
|
30
|
+
const runSingleRule = (
|
|
31
|
+
ast: any[],
|
|
32
|
+
inspection: string,
|
|
33
|
+
expected: boolean,
|
|
34
|
+
binding?: string,
|
|
35
|
+
args: string[] = []
|
|
36
|
+
) => {
|
|
37
|
+
const rule: InspectionRule = { inspection, binding, args, expected };
|
|
38
|
+
const results = analyzer.analyze(ast, [rule]);
|
|
39
|
+
const result = results[0];
|
|
40
|
+
return result.passed;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const createMethod = (
|
|
44
|
+
name: string,
|
|
45
|
+
equationsCount: number = 1,
|
|
46
|
+
isAbstract: boolean = false,
|
|
47
|
+
bodyNode?: Statement
|
|
48
|
+
): Method => {
|
|
49
|
+
const identifier = createSymbol(name);
|
|
50
|
+
const stmts = bodyNode ? [bodyNode] : [];
|
|
51
|
+
const equations = new Array(equationsCount).fill(
|
|
52
|
+
new Equation([], new UnguardedBody(new Sequence(stmts)))
|
|
53
|
+
);
|
|
54
|
+
const method = new Method(identifier, equations);
|
|
55
|
+
method.setMetadata("isAbstract", isAbstract);
|
|
56
|
+
return method;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const createAttribute = (
|
|
60
|
+
name: string,
|
|
61
|
+
expression: any = new NilPrimitive(null)
|
|
62
|
+
) => {
|
|
63
|
+
return new Attribute(createSymbol(name), expression);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const createNew = (className: string) => {
|
|
67
|
+
return new New(createSymbol(className), []);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const createClass = (
|
|
71
|
+
name: string,
|
|
72
|
+
stmts: Statement[] = [],
|
|
73
|
+
extendsName?: string,
|
|
74
|
+
implementsName?: string,
|
|
75
|
+
includes?: string[]
|
|
76
|
+
): Class => {
|
|
77
|
+
const identifier = createSymbol(name);
|
|
78
|
+
const extendsSymbol = extendsName ? createSymbol(extendsName) : undefined;
|
|
79
|
+
const implementsNode = implementsName
|
|
80
|
+
? new Implement(createSymbol(implementsName))
|
|
81
|
+
: undefined;
|
|
82
|
+
const includesMixin =
|
|
83
|
+
includes && includes.length > 0
|
|
84
|
+
? includes.map((sym) => createSymbol(sym))
|
|
85
|
+
: undefined;
|
|
86
|
+
|
|
87
|
+
const expression = new Sequence(stmts);
|
|
88
|
+
|
|
89
|
+
return new Class(
|
|
90
|
+
identifier,
|
|
91
|
+
extendsSymbol,
|
|
92
|
+
implementsNode,
|
|
93
|
+
includesMixin,
|
|
94
|
+
expression
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const createObject = (name: string, children: Statement[] = []) => {
|
|
99
|
+
const identifier = createSymbol(name);
|
|
100
|
+
const expression = new Sequence(children);
|
|
101
|
+
return new AstObject(identifier, expression);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
describe("DeclaresAttribute", () => {
|
|
105
|
+
it("should detect if an attribute with the specific name is declared", () => {
|
|
106
|
+
const attr = createAttribute("energy");
|
|
107
|
+
const ast = [createClass("A", [attr])];
|
|
108
|
+
expect(
|
|
109
|
+
runSingleRule(ast, "DeclaresAttribute", true, undefined, ["energy"])
|
|
110
|
+
).to.be.true;
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should ignore attributes with different names", () => {
|
|
114
|
+
const attr = createAttribute("life");
|
|
115
|
+
const ast = [createClass("A", [attr])];
|
|
116
|
+
expect(
|
|
117
|
+
runSingleRule(ast, "DeclaresAttribute", false, undefined, ["energy"])
|
|
118
|
+
).to.be.true;
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
describe("DeclaresClass", () => {
|
|
123
|
+
it("should detect specific class declaration", () => {
|
|
124
|
+
const ast = [createClass("Bird")];
|
|
125
|
+
expect(runSingleRule(ast, "DeclaresClass", true, "Bird")).to.be.true;
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
describe("DeclaresInterface", () => {
|
|
130
|
+
it("should detect specific interface declaration", () => {
|
|
131
|
+
const ast = [
|
|
132
|
+
new Interface(createSymbol("Flyable"), [], new Sequence([])),
|
|
133
|
+
];
|
|
134
|
+
expect(runSingleRule(ast, "DeclaresInterface", true, "Flyable")).to.be
|
|
135
|
+
.true;
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe("DeclaresMethod", () => {
|
|
140
|
+
it("should detect specific method declaration", () => {
|
|
141
|
+
const ast = [createMethod("fly")];
|
|
142
|
+
expect(runSingleRule(ast, "DeclaresMethod", true, "fly")).to.be.true;
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
describe("DeclaresObject", () => {
|
|
147
|
+
it("should detect specific object declaration", () => {
|
|
148
|
+
const ast = [createObject("pepita")];
|
|
149
|
+
expect(runSingleRule(ast, "DeclaresObject", true, "pepita")).to.be.true;
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("DeclaresPrimitive", () => {
|
|
154
|
+
it("should detect primitive operator override", () => {
|
|
155
|
+
const op: any = "==";
|
|
156
|
+
const ast = [new PrimitiveMethod(op, [], undefined)];
|
|
157
|
+
expect(runSingleRule(ast, "DeclaresPrimitive", true, undefined, ["=="]))
|
|
158
|
+
.to.be.true;
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
describe("DeclaresSuperclass", () => {
|
|
163
|
+
it("should detect if a class extends a specific superclass", () => {
|
|
164
|
+
const ast = [createClass("Sparrow", [], "Bird")];
|
|
165
|
+
expect(
|
|
166
|
+
runSingleRule(ast, "DeclaresSuperclass", true, undefined, ["Bird"])
|
|
167
|
+
).to.be.true;
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe("Implements", () => {
|
|
172
|
+
it("should detect if a class implements a specific interface", () => {
|
|
173
|
+
const ast = [createClass("Pigeon", [], undefined, "Messenger")];
|
|
174
|
+
expect(runSingleRule(ast, "Implements", true, undefined, ["Messenger"]))
|
|
175
|
+
.to.be.true;
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe("IncludeMixin", () => {
|
|
180
|
+
it("should detect usage of a specific mixin", () => {
|
|
181
|
+
const ast = [
|
|
182
|
+
createClass("ClassWithMixin", [], undefined, undefined, ["Walking"]),
|
|
183
|
+
];
|
|
184
|
+
expect(runSingleRule(ast, "IncludeMixin", true, undefined, ["Walking"]))
|
|
185
|
+
.to.be.true;
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe("Instantiates", () => {
|
|
190
|
+
it("should detect instantiation of a specific class", () => {
|
|
191
|
+
const ast = [new Variable(new SymbolPrimitive("a"), createNew("Engine"))];
|
|
192
|
+
expect(runSingleRule(ast, "Instantiates", true, undefined, ["Engine"])).to
|
|
193
|
+
.be.true;
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe("UsesDynamicPolymorphism", () => {
|
|
198
|
+
it("should detect when a method name is used in at least two different places (polymorphism)", () => {
|
|
199
|
+
const method1 = createMethod("fly");
|
|
200
|
+
const method2 = createMethod("fly");
|
|
201
|
+
const class1 = createClass("Bird", [method1]);
|
|
202
|
+
const class2 = createClass("Airplane", [method2]);
|
|
203
|
+
const ast = [class1, class2];
|
|
204
|
+
expect(runSingleRule(ast, "UsesDynamicPolymorphism", true, undefined, ["fly"]))
|
|
205
|
+
.to.be.true;
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it("should not throw if only one method is found", () => {
|
|
209
|
+
const method1 = createMethod("fly");
|
|
210
|
+
const class1 = createClass("Bird", [method1]);
|
|
211
|
+
const ast = [class1];
|
|
212
|
+
expect(runSingleRule(ast, "UsesDynamicPolymorphism", false, "fly")).to.be
|
|
213
|
+
.true;
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe("UsesInheritance", () => {
|
|
218
|
+
it("should detect inheritance in classes", () => {
|
|
219
|
+
const ast = [createClass("Child", [], "Parent")];
|
|
220
|
+
expect(runSingleRule(ast, "UsesInheritance", true)).to.be.true;
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("should detect inheritance in interfaces", () => {
|
|
224
|
+
const ast = [
|
|
225
|
+
new Interface(
|
|
226
|
+
createSymbol("IChild"),
|
|
227
|
+
[createSymbol("IParent")],
|
|
228
|
+
new Sequence([])
|
|
229
|
+
),
|
|
230
|
+
];
|
|
231
|
+
expect(runSingleRule(ast, "UsesInheritance", true)).to.be.true;
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should ignore classes without parent", () => {
|
|
235
|
+
const ast = [createClass("Orphan")];
|
|
236
|
+
expect(runSingleRule(ast, "UsesInheritance", false)).to.be.true;
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe("UsesMixins", () => {
|
|
241
|
+
it("should detect any mixin usage", () => {
|
|
242
|
+
const ast = [
|
|
243
|
+
createClass("ClassWithMixin", [], undefined, undefined, ["AnyMixin"]),
|
|
244
|
+
];
|
|
245
|
+
expect(runSingleRule(ast, "UsesMixins", true)).to.be.true;
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe("UsesObjectComposition", () => {
|
|
250
|
+
it("should detect composition when an attribute is initialized with New", () => {
|
|
251
|
+
const instantiation = createNew("Engine");
|
|
252
|
+
const attr = createAttribute("myEngine", instantiation);
|
|
253
|
+
const ast = [createClass("A", [attr])];
|
|
254
|
+
expect(runSingleRule(ast, "UsesObjectComposition", true)).to.be.true;
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("should ignore attributes initialized with literals", () => {
|
|
258
|
+
const attr = createAttribute(
|
|
259
|
+
"energy",
|
|
260
|
+
new StringPrimitive("Initialized with string!")
|
|
261
|
+
);
|
|
262
|
+
const ast = [createClass("A", [attr])];
|
|
263
|
+
expect(runSingleRule(ast, "UsesObjectComposition", false)).to.be.true;
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
describe("UsesStaticMethodOverload", () => {
|
|
268
|
+
it("should detect two methods with the same name in the same class", () => {
|
|
269
|
+
const m1 = createMethod("calculate");
|
|
270
|
+
const m2 = createMethod("calculate");
|
|
271
|
+
const ast = [createClass("Calculator", [m1, m2])];
|
|
272
|
+
expect(runSingleRule(ast, "UsesStaticMethodOverload", true)).to.be.true;
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it("should NOT detect overload if methods are in different classes", () => {
|
|
276
|
+
const m1 = createMethod("calculate");
|
|
277
|
+
const m2 = createMethod("calculate");
|
|
278
|
+
const classA = createClass("A", [m1]);
|
|
279
|
+
const classB = createClass("B", [m2]);
|
|
280
|
+
const ast = [classA, classB];
|
|
281
|
+
expect(runSingleRule(ast, "UsesStaticMethodOverload", false)).to.be.true;
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
describe("UsesDynamicMethodOverload", () => {
|
|
286
|
+
it("should detect a method with multiple equations (pattern matching)", () => {
|
|
287
|
+
const ast = [createMethod("fibonacci", 2)];
|
|
288
|
+
expect(runSingleRule(ast, "UsesDynamicMethodOverload", true)).to.be.true;
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
it("should ignore methods with a single equation", () => {
|
|
292
|
+
const ast = [createMethod("fibonacci", 1)];
|
|
293
|
+
expect(runSingleRule(ast, "UsesDynamicMethodOverload", false)).to.be.true;
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
describe("UsesTemplateMethod", () => {
|
|
298
|
+
it("should detect template method usage (call to undeclared method on self)", () => {
|
|
299
|
+
const declaredMethod = createMethod("abstractMethod", 1, true);
|
|
300
|
+
const sendToSelf = new Send(
|
|
301
|
+
new Self(),
|
|
302
|
+
createSymbol("abstractMethod"),
|
|
303
|
+
[]
|
|
304
|
+
);
|
|
305
|
+
const templateMethod = createMethod("process", 1, false, sendToSelf);
|
|
306
|
+
const ast = [createClass("MyClass", [declaredMethod, templateMethod])];
|
|
307
|
+
expect(runSingleRule(ast, "UsesTemplateMethod", true)).to.be.true;
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it("should NOT detect if calling a declared method on self", () => {
|
|
311
|
+
const declaredMethod = createMethod(
|
|
312
|
+
"declared",
|
|
313
|
+
1,
|
|
314
|
+
false,
|
|
315
|
+
new Print(new StringPrimitive("This method is Declared"))
|
|
316
|
+
);
|
|
317
|
+
const sendToSelf = new Send(new Self(), createSymbol("declared"), []);
|
|
318
|
+
const method = createMethod("process", 1, false, sendToSelf);
|
|
319
|
+
const ast = [createClass("MyClass", [declaredMethod, method])];
|
|
320
|
+
expect(runSingleRule(ast, "UsesTemplateMethod", false)).to.be.true;
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
});
|