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
package/dist/analyzer/index.js
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
import { StopTraversalException } from "yukigo-ast";
|
|
2
|
+
import { genericInspections } from "./inspections/generic/generic.js";
|
|
3
|
+
import { functionalInspections } from "./inspections/functional/functional.js";
|
|
4
|
+
import { logicInspections } from "./inspections/logic/logic.js";
|
|
5
|
+
import { objectInspections } from "./inspections/object/object.js";
|
|
6
|
+
import { imperativeInspections } from "./inspections/imperative/imperative.js";
|
|
7
|
+
import { functionalSmells } from "./inspections/functional/smells.js";
|
|
8
|
+
import { logicSmells } from "./inspections/logic/smells.js";
|
|
9
|
+
import { objectSmells } from "./inspections/object/smells.js";
|
|
10
|
+
import { imperativeSmells } from "./inspections/imperative/smells.js";
|
|
11
|
+
import { genericSmells } from "./inspections/generic/smells.js";
|
|
12
|
+
import { GraphBuilder } from "./GraphBuilder.js";
|
|
13
|
+
export const DefaultInspectionSet = {
|
|
7
14
|
...genericInspections,
|
|
8
15
|
...functionalInspections,
|
|
9
16
|
...logicInspections,
|
|
10
17
|
...objectInspections,
|
|
11
18
|
...imperativeInspections,
|
|
12
19
|
};
|
|
20
|
+
export const DefaultSmellsSet = {
|
|
21
|
+
...genericSmells,
|
|
22
|
+
...functionalSmells,
|
|
23
|
+
...logicSmells,
|
|
24
|
+
...objectSmells,
|
|
25
|
+
...imperativeSmells,
|
|
26
|
+
};
|
|
13
27
|
/**
|
|
14
28
|
* The Analyzer class.
|
|
15
29
|
* @remarks
|
|
16
|
-
* The Analyzer is the part of Yukigo which runs the inspections on the AST.
|
|
30
|
+
* The Analyzer is the part of Yukigo which runs the inspections on the AST.s
|
|
17
31
|
*/
|
|
18
32
|
export class Analyzer {
|
|
19
33
|
/**
|
|
@@ -21,30 +35,19 @@ export class Analyzer {
|
|
|
21
35
|
* You can load your set of inspections or leave the default one.
|
|
22
36
|
* @defaultValue a default set of inspections for each supported paradigm
|
|
23
37
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
38
|
+
inspectionConstructors = {};
|
|
39
|
+
smellsConstructors = {};
|
|
40
|
+
constructor(inspectionSet, smellsSet) {
|
|
41
|
+
this.inspectionConstructors = inspectionSet ?? DefaultInspectionSet;
|
|
42
|
+
this.smellsConstructors = smellsSet ?? DefaultSmellsSet;
|
|
27
43
|
}
|
|
28
44
|
/**
|
|
29
45
|
* Registers a new custom inspection handler after Analyzer was instantiated.
|
|
30
46
|
* @param name The name of the inspection (e.g., "HasArithmetic").
|
|
31
|
-
* @param
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* // Implementation of HasArithmetic inspection
|
|
35
|
-
* export class UsesArithmetic extends TraverseVisitor {
|
|
36
|
-
* visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation): void {
|
|
37
|
-
* throw new StopTraversalException();
|
|
38
|
-
* }
|
|
39
|
-
* visitArithmeticUnaryOperation(node: ArithmeticUnaryOperation): void {
|
|
40
|
-
* throw new StopTraversalException();
|
|
41
|
-
* }
|
|
42
|
-
* }
|
|
43
|
-
* const analyzer = new ASTAnalyzer(ast);
|
|
44
|
-
* analyzer.registerInspection("HasArithmetic", (node, args) => executeVisitor(node, new UsesArithmetic()));
|
|
47
|
+
* @param visitorConstructor The constructor for the TraverseVisitor class.
|
|
45
48
|
*/
|
|
46
|
-
registerInspection(name,
|
|
47
|
-
this.
|
|
49
|
+
registerInspection(name, visitorConstructor) {
|
|
50
|
+
this.inspectionConstructors[name] = visitorConstructor;
|
|
48
51
|
}
|
|
49
52
|
/**
|
|
50
53
|
* Runs a list of inspection rules against the AST.
|
|
@@ -68,43 +71,82 @@ export class Analyzer {
|
|
|
68
71
|
* const analysisResults = analyzer.analyze(expectations);
|
|
69
72
|
*/
|
|
70
73
|
analyze(ast, rules) {
|
|
71
|
-
const
|
|
74
|
+
const ruleResults = new Map();
|
|
75
|
+
const graphBuilder = new GraphBuilder();
|
|
76
|
+
const { defs, calls } = graphBuilder.build(ast);
|
|
72
77
|
for (const rule of rules) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
rule,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
78
|
+
let inspectionName = rule.inspection;
|
|
79
|
+
let isTransitive = true;
|
|
80
|
+
if (inspectionName.startsWith("Intransitive:")) {
|
|
81
|
+
isTransitive = false;
|
|
82
|
+
inspectionName = inspectionName.replace("Intransitive:", "");
|
|
83
|
+
}
|
|
84
|
+
const InspectionClass = this.inspectionConstructors[inspectionName];
|
|
85
|
+
if (!InspectionClass) {
|
|
86
|
+
ruleResults.set(rule, {
|
|
87
|
+
rule,
|
|
88
|
+
passed: false,
|
|
89
|
+
actual: false,
|
|
90
|
+
error: "Unknown inspection: " + inspectionName,
|
|
91
|
+
});
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (InspectionClass.IS_INTRANSITIVE)
|
|
95
|
+
isTransitive = false;
|
|
96
|
+
let targets = [];
|
|
97
|
+
// Case 1: Global Inspection (No binding or wildcard)
|
|
98
|
+
if (!rule.binding || rule.binding === "*") {
|
|
99
|
+
targets = ast.map((n) => ({ node: n, binding: undefined }));
|
|
100
|
+
}
|
|
101
|
+
// Case 2: Directed Inspection (Specific binding)
|
|
102
|
+
else {
|
|
103
|
+
const workList = [rule.binding];
|
|
104
|
+
const visited = new Set();
|
|
105
|
+
while (workList.length > 0) {
|
|
106
|
+
const currentBinding = workList.shift();
|
|
107
|
+
if (visited.has(currentBinding))
|
|
108
|
+
continue;
|
|
109
|
+
visited.add(currentBinding);
|
|
110
|
+
const node = defs.get(currentBinding);
|
|
111
|
+
if (node)
|
|
112
|
+
node.forEach((n) => targets.push({ node: n, binding: currentBinding }));
|
|
113
|
+
if (isTransitive) {
|
|
114
|
+
const deps = calls.get(currentBinding) || [];
|
|
115
|
+
workList.push(...deps);
|
|
116
|
+
}
|
|
92
117
|
}
|
|
93
118
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
119
|
+
let actual = false;
|
|
120
|
+
let error;
|
|
121
|
+
// Execution Loop
|
|
122
|
+
const isGlobalVisitor = !rule.binding || rule.binding === "*";
|
|
123
|
+
const normalizedBinding = isGlobalVisitor ? undefined : rule.binding;
|
|
124
|
+
const args = rule.args ?? [];
|
|
125
|
+
const visitor = new InspectionClass(...args, normalizedBinding);
|
|
126
|
+
for (const { node, binding } of targets) {
|
|
127
|
+
try {
|
|
128
|
+
if (!isGlobalVisitor && visitor.setBinding) {
|
|
129
|
+
visitor.setBinding(binding);
|
|
130
|
+
}
|
|
131
|
+
node.accept(visitor);
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
if (e instanceof StopTraversalException) {
|
|
135
|
+
actual = true;
|
|
136
|
+
break; // Short-circuit: Rule passed
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
error = e.message;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
ruleResults.set(rule, {
|
|
103
144
|
rule,
|
|
104
|
-
passed:
|
|
105
|
-
actual
|
|
145
|
+
passed: actual === rule.expected,
|
|
146
|
+
actual,
|
|
106
147
|
error,
|
|
107
|
-
};
|
|
148
|
+
});
|
|
108
149
|
}
|
|
150
|
+
return [...ruleResults.values()];
|
|
109
151
|
}
|
|
110
152
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as Yu from "yukigo-ast";
|
|
2
|
+
import { VisitorConstructor, ScopedVisitor } from "../../utils.js";
|
|
3
|
+
export declare class UsesComposition extends ScopedVisitor {
|
|
4
|
+
constructor(scope?: string);
|
|
5
|
+
visitCompositionExpression(node: Yu.CompositionExpression): void;
|
|
6
|
+
}
|
|
7
|
+
export declare class UsesAnonymousVariable extends ScopedVisitor {
|
|
8
|
+
constructor(scope?: string);
|
|
9
|
+
visitWildcardPattern(node: Yu.WildcardPattern): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class UsesComprehension extends ScopedVisitor {
|
|
12
|
+
constructor(scope?: string);
|
|
13
|
+
visitListComprehension(node: Yu.ListComprehension): void;
|
|
14
|
+
}
|
|
15
|
+
export declare class UsesGuards extends ScopedVisitor {
|
|
16
|
+
constructor(scope?: string);
|
|
17
|
+
visitGuardedBody(node: Yu.GuardedBody): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class UsesOtherwise extends ScopedVisitor {
|
|
20
|
+
constructor(scope?: string);
|
|
21
|
+
visitOtherwise(node: Yu.Otherwise): void;
|
|
22
|
+
}
|
|
23
|
+
export declare class UsesLambda extends ScopedVisitor {
|
|
24
|
+
constructor(scope?: string);
|
|
25
|
+
visitLambda(node: Yu.Lambda): void;
|
|
26
|
+
}
|
|
27
|
+
export declare class UsesYield extends ScopedVisitor {
|
|
28
|
+
constructor(scope?: string);
|
|
29
|
+
visitYield(node: Yu.Yield): void;
|
|
30
|
+
}
|
|
31
|
+
export declare class UsesPatternMatching extends ScopedVisitor {
|
|
32
|
+
constructor(scope?: string);
|
|
33
|
+
visitConsPattern(node: Yu.ConsPattern): void;
|
|
34
|
+
visitAsPattern(node: Yu.AsPattern): void;
|
|
35
|
+
visitListPattern(node: Yu.ListPattern): void;
|
|
36
|
+
visitTuplePattern(node: Yu.TuplePattern): void;
|
|
37
|
+
visitLiteralPattern(node: Yu.LiteralPattern): void;
|
|
38
|
+
visitApplicationPattern(node: Yu.ApplicationPattern): void;
|
|
39
|
+
visitConstructorPattern(node: Yu.ConstructorPattern): void;
|
|
40
|
+
visitUnionPattern(node: Yu.UnionPattern): void;
|
|
41
|
+
visitFunctorPattern(node: Yu.FunctorPattern): void;
|
|
42
|
+
visitWildcardPattern(node: Yu.WildcardPattern): void;
|
|
43
|
+
}
|
|
44
|
+
export declare const functionalInspections: Record<string, VisitorConstructor>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import * as Yu from "yukigo-ast";
|
|
8
|
+
import { ScopedVisitor, AutoScoped } from "../../utils.js";
|
|
9
|
+
let UsesComposition = class UsesComposition extends ScopedVisitor {
|
|
10
|
+
constructor(scope) {
|
|
11
|
+
super(scope);
|
|
12
|
+
}
|
|
13
|
+
visitCompositionExpression(node) {
|
|
14
|
+
throw new Yu.StopTraversalException();
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
UsesComposition = __decorate([
|
|
18
|
+
AutoScoped
|
|
19
|
+
], UsesComposition);
|
|
20
|
+
export { UsesComposition };
|
|
21
|
+
let UsesAnonymousVariable = class UsesAnonymousVariable extends ScopedVisitor {
|
|
22
|
+
constructor(scope) {
|
|
23
|
+
super(scope);
|
|
24
|
+
}
|
|
25
|
+
visitWildcardPattern(node) {
|
|
26
|
+
throw new Yu.StopTraversalException();
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
UsesAnonymousVariable = __decorate([
|
|
30
|
+
AutoScoped
|
|
31
|
+
], UsesAnonymousVariable);
|
|
32
|
+
export { UsesAnonymousVariable };
|
|
33
|
+
let UsesComprehension = class UsesComprehension extends ScopedVisitor {
|
|
34
|
+
constructor(scope) {
|
|
35
|
+
super(scope);
|
|
36
|
+
}
|
|
37
|
+
visitListComprehension(node) {
|
|
38
|
+
throw new Yu.StopTraversalException();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
UsesComprehension = __decorate([
|
|
42
|
+
AutoScoped
|
|
43
|
+
], UsesComprehension);
|
|
44
|
+
export { UsesComprehension };
|
|
45
|
+
let UsesGuards = class UsesGuards extends ScopedVisitor {
|
|
46
|
+
constructor(scope) {
|
|
47
|
+
super(scope);
|
|
48
|
+
}
|
|
49
|
+
visitGuardedBody(node) {
|
|
50
|
+
throw new Yu.StopTraversalException();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
UsesGuards = __decorate([
|
|
54
|
+
AutoScoped
|
|
55
|
+
], UsesGuards);
|
|
56
|
+
export { UsesGuards };
|
|
57
|
+
let UsesOtherwise = class UsesOtherwise extends ScopedVisitor {
|
|
58
|
+
constructor(scope) {
|
|
59
|
+
super(scope);
|
|
60
|
+
}
|
|
61
|
+
visitOtherwise(node) {
|
|
62
|
+
throw new Yu.StopTraversalException();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
UsesOtherwise = __decorate([
|
|
66
|
+
AutoScoped
|
|
67
|
+
], UsesOtherwise);
|
|
68
|
+
export { UsesOtherwise };
|
|
69
|
+
let UsesLambda = class UsesLambda extends ScopedVisitor {
|
|
70
|
+
constructor(scope) {
|
|
71
|
+
super(scope);
|
|
72
|
+
}
|
|
73
|
+
visitLambda(node) {
|
|
74
|
+
throw new Yu.StopTraversalException();
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
UsesLambda = __decorate([
|
|
78
|
+
AutoScoped
|
|
79
|
+
], UsesLambda);
|
|
80
|
+
export { UsesLambda };
|
|
81
|
+
let UsesYield = class UsesYield extends ScopedVisitor {
|
|
82
|
+
constructor(scope) {
|
|
83
|
+
super(scope);
|
|
84
|
+
}
|
|
85
|
+
visitYield(node) {
|
|
86
|
+
throw new Yu.StopTraversalException();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
UsesYield = __decorate([
|
|
90
|
+
AutoScoped
|
|
91
|
+
], UsesYield);
|
|
92
|
+
export { UsesYield };
|
|
93
|
+
let UsesPatternMatching = class UsesPatternMatching extends ScopedVisitor {
|
|
94
|
+
constructor(scope) {
|
|
95
|
+
super(scope);
|
|
96
|
+
}
|
|
97
|
+
visitConsPattern(node) {
|
|
98
|
+
throw new Yu.StopTraversalException();
|
|
99
|
+
}
|
|
100
|
+
visitAsPattern(node) {
|
|
101
|
+
throw new Yu.StopTraversalException();
|
|
102
|
+
}
|
|
103
|
+
visitListPattern(node) {
|
|
104
|
+
throw new Yu.StopTraversalException();
|
|
105
|
+
}
|
|
106
|
+
visitTuplePattern(node) {
|
|
107
|
+
throw new Yu.StopTraversalException();
|
|
108
|
+
}
|
|
109
|
+
visitLiteralPattern(node) {
|
|
110
|
+
throw new Yu.StopTraversalException();
|
|
111
|
+
}
|
|
112
|
+
visitApplicationPattern(node) {
|
|
113
|
+
throw new Yu.StopTraversalException();
|
|
114
|
+
}
|
|
115
|
+
visitConstructorPattern(node) {
|
|
116
|
+
throw new Yu.StopTraversalException();
|
|
117
|
+
}
|
|
118
|
+
visitUnionPattern(node) {
|
|
119
|
+
throw new Yu.StopTraversalException();
|
|
120
|
+
}
|
|
121
|
+
visitFunctorPattern(node) {
|
|
122
|
+
throw new Yu.StopTraversalException();
|
|
123
|
+
}
|
|
124
|
+
visitWildcardPattern(node) {
|
|
125
|
+
throw new Yu.StopTraversalException();
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
UsesPatternMatching = __decorate([
|
|
129
|
+
AutoScoped
|
|
130
|
+
], UsesPatternMatching);
|
|
131
|
+
export { UsesPatternMatching };
|
|
132
|
+
export const functionalInspections = {
|
|
133
|
+
UsesComposition: UsesComposition,
|
|
134
|
+
HasComposition: UsesComposition,
|
|
135
|
+
UsesAnonymousVariable: UsesAnonymousVariable,
|
|
136
|
+
HasAnonymousVariable: UsesAnonymousVariable,
|
|
137
|
+
UsesComprehension: UsesComprehension,
|
|
138
|
+
HasComprehension: UsesComprehension,
|
|
139
|
+
UsesGuards: UsesGuards,
|
|
140
|
+
HasGuards: UsesGuards,
|
|
141
|
+
UsesOtherwise: UsesOtherwise,
|
|
142
|
+
HasOtherwise: UsesOtherwise,
|
|
143
|
+
UsesLambda: UsesLambda,
|
|
144
|
+
HasLambda: UsesLambda,
|
|
145
|
+
UsesYield: UsesYield,
|
|
146
|
+
HasYield: UsesYield,
|
|
147
|
+
UsesPatternMatching: UsesPatternMatching,
|
|
148
|
+
HasPatternMatching: UsesPatternMatching,
|
|
149
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Lambda, Equation, GuardedBody } from "yukigo-ast";
|
|
2
|
+
import { ScopedVisitor, VisitorConstructor } from "../../utils.js";
|
|
3
|
+
export declare class HasRedundantLambda extends ScopedVisitor {
|
|
4
|
+
visitLambda(node: Lambda): void;
|
|
5
|
+
}
|
|
6
|
+
export declare class HasRedundantGuards extends ScopedVisitor {
|
|
7
|
+
visitEquation(node: Equation): void;
|
|
8
|
+
private isAlwaysTrue;
|
|
9
|
+
}
|
|
10
|
+
export declare class ShouldUseOtherwise extends ScopedVisitor {
|
|
11
|
+
visitGuardedBody(node: GuardedBody): void;
|
|
12
|
+
}
|
|
13
|
+
export declare class HasRedundantParameter extends ScopedVisitor {
|
|
14
|
+
visitEquation(node: Equation): void;
|
|
15
|
+
}
|
|
16
|
+
export declare const functionalSmells: Record<string, VisitorConstructor>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { Call, VariablePattern, Variable, StopTraversalException, BooleanPrimitive, Application, isUnguardedBody, Otherwise, } from "yukigo-ast";
|
|
8
|
+
import { AutoScoped, ScopedVisitor } from "../../utils.js";
|
|
9
|
+
import { Uses } from "../generic/generic.js";
|
|
10
|
+
let HasRedundantLambda = class HasRedundantLambda extends ScopedVisitor {
|
|
11
|
+
visitLambda(node) {
|
|
12
|
+
if (node.parameters.length !== 1)
|
|
13
|
+
return;
|
|
14
|
+
if (!(node.body instanceof Application))
|
|
15
|
+
return;
|
|
16
|
+
const param = node.parameters[0];
|
|
17
|
+
const call = node.body;
|
|
18
|
+
if (call.functionExpr instanceof Application ||
|
|
19
|
+
call.functionExpr instanceof Call)
|
|
20
|
+
return;
|
|
21
|
+
const arg = call.parameter;
|
|
22
|
+
if (param instanceof VariablePattern &&
|
|
23
|
+
arg instanceof Variable &&
|
|
24
|
+
param.name.value === arg.identifier.value)
|
|
25
|
+
throw new StopTraversalException();
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
HasRedundantLambda = __decorate([
|
|
29
|
+
AutoScoped
|
|
30
|
+
], HasRedundantLambda);
|
|
31
|
+
export { HasRedundantLambda };
|
|
32
|
+
let HasRedundantGuards = class HasRedundantGuards extends ScopedVisitor {
|
|
33
|
+
visitEquation(node) {
|
|
34
|
+
if (isUnguardedBody(node.body))
|
|
35
|
+
return;
|
|
36
|
+
// If there is only 1 guard...
|
|
37
|
+
if (node.body.length === 1) {
|
|
38
|
+
const guard = node.body[0];
|
|
39
|
+
// ...and that guard is "True" or "otherwise"
|
|
40
|
+
if (this.isAlwaysTrue(guard.condition))
|
|
41
|
+
throw new StopTraversalException();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
isAlwaysTrue(node) {
|
|
45
|
+
// check for boolean literal 'True'
|
|
46
|
+
if (node instanceof BooleanPrimitive && node.value === true)
|
|
47
|
+
return true;
|
|
48
|
+
// check for default case
|
|
49
|
+
if (node instanceof Otherwise)
|
|
50
|
+
return true;
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
HasRedundantGuards = __decorate([
|
|
55
|
+
AutoScoped
|
|
56
|
+
], HasRedundantGuards);
|
|
57
|
+
export { HasRedundantGuards };
|
|
58
|
+
let ShouldUseOtherwise = class ShouldUseOtherwise extends ScopedVisitor {
|
|
59
|
+
visitGuardedBody(node) {
|
|
60
|
+
if (node.condition instanceof BooleanPrimitive &&
|
|
61
|
+
node.condition.value === true)
|
|
62
|
+
throw new StopTraversalException();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
ShouldUseOtherwise = __decorate([
|
|
66
|
+
AutoScoped
|
|
67
|
+
], ShouldUseOtherwise);
|
|
68
|
+
export { ShouldUseOtherwise };
|
|
69
|
+
let HasRedundantParameter = class HasRedundantParameter extends ScopedVisitor {
|
|
70
|
+
visitEquation(node) {
|
|
71
|
+
for (const pattern of node.patterns) {
|
|
72
|
+
if (pattern instanceof VariablePattern) {
|
|
73
|
+
const paramName = pattern.name.value;
|
|
74
|
+
const usageChecker = new Uses(paramName, this.binding);
|
|
75
|
+
try {
|
|
76
|
+
node.accept(usageChecker);
|
|
77
|
+
// uses didnt throw so the param is not being used
|
|
78
|
+
throw new StopTraversalException();
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
if (e instanceof StopTraversalException)
|
|
82
|
+
continue;
|
|
83
|
+
throw e;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
HasRedundantParameter = __decorate([
|
|
90
|
+
AutoScoped
|
|
91
|
+
], HasRedundantParameter);
|
|
92
|
+
export { HasRedundantParameter };
|
|
93
|
+
export const functionalSmells = {
|
|
94
|
+
HasRedundantGuards: HasRedundantGuards,
|
|
95
|
+
HasRedundantLambda: HasRedundantLambda,
|
|
96
|
+
HasRedundantParameter: HasRedundantParameter,
|
|
97
|
+
ShouldUseOtherwise: ShouldUseOtherwise,
|
|
98
|
+
};
|