yukigo 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/analyzer/index.d.ts +7 -0
- package/dist/src/analyzer/GraphBuilder.d.ts +30 -0
- package/dist/src/analyzer/GraphBuilder.js +100 -0
- package/dist/src/analyzer/index.d.ts +59 -0
- package/dist/src/analyzer/index.js +152 -0
- package/dist/src/analyzer/inspections/functional/functional.d.ts +44 -0
- package/dist/src/analyzer/inspections/functional/functional.js +149 -0
- package/dist/src/analyzer/inspections/functional/smells.d.ts +16 -0
- package/dist/src/analyzer/inspections/functional/smells.js +98 -0
- package/dist/src/analyzer/inspections/generic/generic.d.ts +178 -0
- package/dist/src/analyzer/inspections/generic/generic.js +604 -0
- package/dist/src/analyzer/inspections/generic/smells.d.ts +61 -0
- package/dist/src/analyzer/inspections/generic/smells.js +349 -0
- package/dist/src/analyzer/inspections/imperative/imperative.d.ts +35 -0
- package/dist/src/analyzer/inspections/imperative/imperative.js +109 -0
- package/dist/src/analyzer/inspections/imperative/smells.d.ts +16 -0
- package/dist/src/analyzer/inspections/imperative/smells.js +58 -0
- package/dist/src/analyzer/inspections/logic/logic.d.ts +32 -0
- package/dist/src/analyzer/inspections/logic/logic.js +96 -0
- package/dist/src/analyzer/inspections/logic/smells.d.ts +15 -0
- package/dist/src/analyzer/inspections/logic/smells.js +60 -0
- package/dist/src/analyzer/inspections/object/object.d.ts +90 -0
- package/dist/src/analyzer/inspections/object/object.js +321 -0
- package/dist/src/analyzer/inspections/object/smells.d.ts +30 -0
- package/dist/src/analyzer/inspections/object/smells.js +135 -0
- package/dist/src/analyzer/utils.d.ts +30 -0
- package/dist/src/analyzer/utils.js +78 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +4 -0
- package/dist/src/interpreter/components/EnvBuilder.d.ts +21 -0
- package/dist/src/interpreter/components/EnvBuilder.js +155 -0
- package/dist/src/interpreter/components/Operations.d.ts +14 -0
- package/dist/src/interpreter/components/Operations.js +84 -0
- package/dist/src/interpreter/components/PatternMatcher.d.ts +73 -0
- package/dist/src/interpreter/components/PatternMatcher.js +358 -0
- package/dist/src/interpreter/components/RuntimeContext.d.ts +35 -0
- package/dist/src/interpreter/components/RuntimeContext.js +93 -0
- package/dist/src/interpreter/components/TestRunner.d.ts +19 -0
- package/dist/src/interpreter/components/TestRunner.js +110 -0
- package/dist/src/interpreter/components/Visitor.d.ts +71 -0
- package/dist/src/interpreter/components/Visitor.js +638 -0
- package/dist/src/interpreter/components/logic/LogicEngine.d.ts +29 -0
- package/dist/src/interpreter/components/logic/LogicEngine.js +259 -0
- package/dist/src/interpreter/components/logic/LogicResolver.d.ts +53 -0
- package/dist/src/interpreter/components/logic/LogicResolver.js +484 -0
- package/dist/src/interpreter/components/logic/LogicTranslator.d.ts +14 -0
- package/dist/src/interpreter/components/logic/LogicTranslator.js +99 -0
- package/dist/src/interpreter/components/runtimes/FunctionRuntime.d.ts +12 -0
- package/dist/src/interpreter/components/runtimes/FunctionRuntime.js +149 -0
- package/dist/src/interpreter/components/runtimes/LazyRuntime.d.ts +19 -0
- package/dist/src/interpreter/components/runtimes/LazyRuntime.js +269 -0
- package/dist/src/interpreter/components/runtimes/ObjectRuntime.d.ts +35 -0
- package/dist/src/interpreter/components/runtimes/ObjectRuntime.js +126 -0
- package/dist/src/interpreter/errors.d.ts +19 -0
- package/dist/src/interpreter/errors.js +36 -0
- package/dist/src/interpreter/index.d.ts +24 -0
- package/dist/src/interpreter/index.js +41 -0
- package/dist/src/interpreter/trampoline.d.ts +17 -0
- package/dist/src/interpreter/trampoline.js +38 -0
- package/dist/src/interpreter/utils.d.ts +11 -0
- package/dist/src/interpreter/utils.js +65 -0
- package/dist/src/tester/index.d.ts +25 -0
- package/dist/src/tester/index.js +113 -0
- package/dist/src/utils/helpers.d.ts +13 -0
- package/dist/src/utils/helpers.js +52 -0
- package/dist/utils/helpers.d.ts +5 -1
- package/dist/utils/helpers.js +79 -6
- package/package.json +4 -2
- package/src/analyzer/index.ts +9 -0
- package/src/utils/helpers.ts +111 -10
- package/tests/analyzer/helpers.spec.ts +14 -8
- package/tests/tester/Tester.spec.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
## 0.2.2 (2026-05-01)
|
|
2
|
+
|
|
3
|
+
### 🩹 Fixes
|
|
4
|
+
|
|
5
|
+
- **yukigo:** MulangAdapter handle v1 and v2 inspections ([872558f](https://github.com/miyukiproject/yukigo/commit/872558f))
|
|
6
|
+
|
|
7
|
+
### 🧱 Updated Dependencies
|
|
8
|
+
|
|
9
|
+
- Updated yukigo-ast to 0.2.1
|
|
10
|
+
|
|
11
|
+
### ❤️ Thank You
|
|
12
|
+
|
|
13
|
+
- noiseArch
|
|
14
|
+
|
|
15
|
+
## 0.2.1 (2026-05-01)
|
|
16
|
+
|
|
17
|
+
### 🩹 Fixes
|
|
18
|
+
|
|
19
|
+
- **yukigo:** MulangAdapter handle v1 and v2 inspections ([872558f](https://github.com/miyukiproject/yukigo/commit/872558f))
|
|
20
|
+
|
|
21
|
+
### 🧱 Updated Dependencies
|
|
22
|
+
|
|
23
|
+
- Updated yukigo-ast to 0.2.0
|
|
24
|
+
|
|
25
|
+
### ❤️ Thank You
|
|
26
|
+
|
|
27
|
+
- noiseArch
|
|
28
|
+
|
|
1
29
|
## 0.2.0 (2026-04-11)
|
|
2
30
|
|
|
3
31
|
### 🚀 Features
|
package/dist/analyzer/index.d.ts
CHANGED
|
@@ -6,11 +6,18 @@ export type AnalysisResult = {
|
|
|
6
6
|
actual: boolean;
|
|
7
7
|
error?: string;
|
|
8
8
|
};
|
|
9
|
+
export type TargetSuffix = "named" | "like" | "except";
|
|
10
|
+
export type InspectionMatcher = {
|
|
11
|
+
type: string;
|
|
12
|
+
value?: string;
|
|
13
|
+
};
|
|
9
14
|
export type InspectionRule = {
|
|
10
15
|
inspection: string;
|
|
11
16
|
binding?: string;
|
|
12
17
|
args?: string[];
|
|
13
18
|
expected: boolean;
|
|
19
|
+
targetSuffix?: TargetSuffix;
|
|
20
|
+
matcher?: InspectionMatcher;
|
|
14
21
|
};
|
|
15
22
|
export declare const DefaultInspectionSet: InspectionMap;
|
|
16
23
|
export declare const DefaultSmellsSet: InspectionMap;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Application, AST, ASTNode, Call, Class, Fact, Function, Interface, Method, New, Object as YuObject, Procedure, Rule, TraverseVisitor, TypeAlias, TypeSignature, Exist } from "yukigo-ast";
|
|
2
|
+
type DefinitionMap = Map<string, ASTNode[]>;
|
|
3
|
+
type CallsMap = Map<string, string[]>;
|
|
4
|
+
export type SymbolGraph = {
|
|
5
|
+
defs: DefinitionMap;
|
|
6
|
+
calls: CallsMap;
|
|
7
|
+
};
|
|
8
|
+
export declare class GraphBuilder extends TraverseVisitor {
|
|
9
|
+
private defs;
|
|
10
|
+
private calls;
|
|
11
|
+
private scope;
|
|
12
|
+
build(ast: AST): SymbolGraph;
|
|
13
|
+
private addDefinition;
|
|
14
|
+
visitFunction(node: Function): void;
|
|
15
|
+
visitMethod(node: Method): void;
|
|
16
|
+
visitProcedure(node: Procedure): void;
|
|
17
|
+
visitRule(node: Rule): void;
|
|
18
|
+
visitFact(node: Fact): void;
|
|
19
|
+
visitClass(node: Class): void;
|
|
20
|
+
visitObject(node: YuObject): void;
|
|
21
|
+
visitInterface(node: Interface): void;
|
|
22
|
+
visitTypeAlias(node: TypeAlias): void;
|
|
23
|
+
visitTypeSignature(node: TypeSignature): void;
|
|
24
|
+
visitCall(node: Call): void;
|
|
25
|
+
visitApplication(node: Application): void;
|
|
26
|
+
visitNew(node: New): void;
|
|
27
|
+
visitExist(node: Exist): void;
|
|
28
|
+
fallback(node: ASTNode): void;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { SymbolPrimitive, TraverseVisitor, } from "yukigo-ast";
|
|
2
|
+
export class GraphBuilder extends TraverseVisitor {
|
|
3
|
+
defs = new Map();
|
|
4
|
+
calls = new Map();
|
|
5
|
+
scope = "";
|
|
6
|
+
build(ast) {
|
|
7
|
+
ast.forEach((node) => node.accept(this));
|
|
8
|
+
return { defs: this.defs, calls: this.calls };
|
|
9
|
+
}
|
|
10
|
+
addDefinition(name, node) {
|
|
11
|
+
const existing = this.defs.get(name) || [];
|
|
12
|
+
this.defs.set(name, [...existing, node]);
|
|
13
|
+
}
|
|
14
|
+
visitFunction(node) {
|
|
15
|
+
this.scope = node.identifier.value;
|
|
16
|
+
this.addDefinition(this.scope, node);
|
|
17
|
+
this.traverseCollection(node.equations);
|
|
18
|
+
this.scope = "";
|
|
19
|
+
}
|
|
20
|
+
visitMethod(node) {
|
|
21
|
+
this.scope = node.identifier.value;
|
|
22
|
+
this.addDefinition(this.scope, node);
|
|
23
|
+
this.traverseCollection(node.equations);
|
|
24
|
+
this.scope = "";
|
|
25
|
+
}
|
|
26
|
+
visitProcedure(node) {
|
|
27
|
+
this.scope = node.identifier.value;
|
|
28
|
+
this.addDefinition(this.scope, node);
|
|
29
|
+
this.traverseCollection(node.equations);
|
|
30
|
+
this.scope = "";
|
|
31
|
+
}
|
|
32
|
+
visitRule(node) {
|
|
33
|
+
this.scope = node.identifier.value;
|
|
34
|
+
this.addDefinition(this.scope, node);
|
|
35
|
+
this.traverseCollection(node.equations);
|
|
36
|
+
this.scope = "";
|
|
37
|
+
}
|
|
38
|
+
visitFact(node) {
|
|
39
|
+
this.scope = node.identifier.value;
|
|
40
|
+
this.addDefinition(this.scope, node);
|
|
41
|
+
this.traverseCollection(node.patterns);
|
|
42
|
+
this.scope = "";
|
|
43
|
+
}
|
|
44
|
+
visitClass(node) {
|
|
45
|
+
this.scope = node.identifier.value;
|
|
46
|
+
this.addDefinition(this.scope, node);
|
|
47
|
+
node.expression.accept(this);
|
|
48
|
+
this.scope = "";
|
|
49
|
+
}
|
|
50
|
+
visitObject(node) {
|
|
51
|
+
this.scope = node.identifier.value;
|
|
52
|
+
this.addDefinition(this.scope, node);
|
|
53
|
+
node.expression.accept(this);
|
|
54
|
+
this.scope = "";
|
|
55
|
+
}
|
|
56
|
+
visitInterface(node) {
|
|
57
|
+
this.scope = node.identifier.value;
|
|
58
|
+
this.addDefinition(this.scope, node);
|
|
59
|
+
node.expression.accept(this);
|
|
60
|
+
this.scope = "";
|
|
61
|
+
}
|
|
62
|
+
visitTypeAlias(node) {
|
|
63
|
+
this.scope = node.identifier.value;
|
|
64
|
+
this.addDefinition(this.scope, node);
|
|
65
|
+
this.scope = "";
|
|
66
|
+
}
|
|
67
|
+
visitTypeSignature(node) {
|
|
68
|
+
this.scope = node.identifier.value;
|
|
69
|
+
this.addDefinition(this.scope, node);
|
|
70
|
+
this.scope = "";
|
|
71
|
+
}
|
|
72
|
+
visitCall(node) {
|
|
73
|
+
if (!this.scope)
|
|
74
|
+
return;
|
|
75
|
+
const arr = this.calls.get(this.scope) || [];
|
|
76
|
+
this.calls.set(this.scope, [node.callee.value, ...arr]);
|
|
77
|
+
}
|
|
78
|
+
visitApplication(node) {
|
|
79
|
+
if (!this.scope)
|
|
80
|
+
return;
|
|
81
|
+
const arr = this.calls.get(this.scope) || [];
|
|
82
|
+
if (node.functionExpr instanceof SymbolPrimitive)
|
|
83
|
+
this.calls.set(this.scope, [node.functionExpr.value, ...arr]);
|
|
84
|
+
else
|
|
85
|
+
node.functionExpr.accept(this);
|
|
86
|
+
}
|
|
87
|
+
visitNew(node) {
|
|
88
|
+
if (!this.scope)
|
|
89
|
+
return;
|
|
90
|
+
const arr = this.calls.get(this.scope) || [];
|
|
91
|
+
this.calls.set(this.scope, [node.identifier.value, ...arr]);
|
|
92
|
+
}
|
|
93
|
+
visitExist(node) {
|
|
94
|
+
if (!this.scope)
|
|
95
|
+
return;
|
|
96
|
+
const arr = this.calls.get(this.scope) || [];
|
|
97
|
+
this.calls.set(this.scope, [node.identifier.value, ...arr]);
|
|
98
|
+
}
|
|
99
|
+
fallback(node) { }
|
|
100
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AST } from "yukigo-ast";
|
|
2
|
+
import { InspectionMap, VisitorConstructor } from "./utils.js";
|
|
3
|
+
export type AnalysisResult = {
|
|
4
|
+
rule: InspectionRule;
|
|
5
|
+
passed: boolean;
|
|
6
|
+
actual: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
};
|
|
9
|
+
export type InspectionRule = {
|
|
10
|
+
inspection: string;
|
|
11
|
+
binding?: string;
|
|
12
|
+
args?: string[];
|
|
13
|
+
expected: boolean;
|
|
14
|
+
};
|
|
15
|
+
export declare const DefaultInspectionSet: InspectionMap;
|
|
16
|
+
export declare const DefaultSmellsSet: InspectionMap;
|
|
17
|
+
/**
|
|
18
|
+
* The Analyzer class.
|
|
19
|
+
* @remarks
|
|
20
|
+
* The Analyzer is the part of Yukigo which runs the inspections on the AST.s
|
|
21
|
+
*/
|
|
22
|
+
export declare class Analyzer {
|
|
23
|
+
/**
|
|
24
|
+
* The set of inspections that are available for the Analyzer.
|
|
25
|
+
* You can load your set of inspections or leave the default one.
|
|
26
|
+
* @defaultValue a default set of inspections for each supported paradigm
|
|
27
|
+
*/
|
|
28
|
+
private inspectionConstructors;
|
|
29
|
+
private smellsConstructors;
|
|
30
|
+
constructor(inspectionSet?: InspectionMap, smellsSet?: InspectionMap);
|
|
31
|
+
/**
|
|
32
|
+
* Registers a new custom inspection handler after Analyzer was instantiated.
|
|
33
|
+
* @param name The name of the inspection (e.g., "HasArithmetic").
|
|
34
|
+
* @param visitorConstructor The constructor for the TraverseVisitor class.
|
|
35
|
+
*/
|
|
36
|
+
registerInspection(name: string, visitorConstructor: VisitorConstructor): void;
|
|
37
|
+
/**
|
|
38
|
+
* Runs a list of inspection rules against the AST.
|
|
39
|
+
* @param ast The parsed AST.
|
|
40
|
+
* @param rules The array of inspection rules to run.
|
|
41
|
+
* @returns An array of analysis results.
|
|
42
|
+
* @example
|
|
43
|
+
* const rules: InspectionRule[] = [
|
|
44
|
+
* {
|
|
45
|
+
* inspection: "HasBinding",
|
|
46
|
+
* args: { name: "minimoEntre" },
|
|
47
|
+
* expected: false,
|
|
48
|
+
* },
|
|
49
|
+
* {
|
|
50
|
+
* inspection: "HasBinding",
|
|
51
|
+
* args: { name: "squareList" },
|
|
52
|
+
* expected: true,
|
|
53
|
+
* }
|
|
54
|
+
* ]
|
|
55
|
+
* const analyzer = new ASTAnalyzer(ast);
|
|
56
|
+
* const analysisResults = analyzer.analyze(expectations);
|
|
57
|
+
*/
|
|
58
|
+
analyze(ast: AST, rules: InspectionRule[]): AnalysisResult[];
|
|
59
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
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 = {
|
|
14
|
+
...genericInspections,
|
|
15
|
+
...functionalInspections,
|
|
16
|
+
...logicInspections,
|
|
17
|
+
...objectInspections,
|
|
18
|
+
...imperativeInspections,
|
|
19
|
+
};
|
|
20
|
+
export const DefaultSmellsSet = {
|
|
21
|
+
...genericSmells,
|
|
22
|
+
...functionalSmells,
|
|
23
|
+
...logicSmells,
|
|
24
|
+
...objectSmells,
|
|
25
|
+
...imperativeSmells,
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The Analyzer class.
|
|
29
|
+
* @remarks
|
|
30
|
+
* The Analyzer is the part of Yukigo which runs the inspections on the AST.s
|
|
31
|
+
*/
|
|
32
|
+
export class Analyzer {
|
|
33
|
+
/**
|
|
34
|
+
* The set of inspections that are available for the Analyzer.
|
|
35
|
+
* You can load your set of inspections or leave the default one.
|
|
36
|
+
* @defaultValue a default set of inspections for each supported paradigm
|
|
37
|
+
*/
|
|
38
|
+
inspectionConstructors = {};
|
|
39
|
+
smellsConstructors = {};
|
|
40
|
+
constructor(inspectionSet, smellsSet) {
|
|
41
|
+
this.inspectionConstructors = inspectionSet ?? DefaultInspectionSet;
|
|
42
|
+
this.smellsConstructors = smellsSet ?? DefaultSmellsSet;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Registers a new custom inspection handler after Analyzer was instantiated.
|
|
46
|
+
* @param name The name of the inspection (e.g., "HasArithmetic").
|
|
47
|
+
* @param visitorConstructor The constructor for the TraverseVisitor class.
|
|
48
|
+
*/
|
|
49
|
+
registerInspection(name, visitorConstructor) {
|
|
50
|
+
this.inspectionConstructors[name] = visitorConstructor;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Runs a list of inspection rules against the AST.
|
|
54
|
+
* @param ast The parsed AST.
|
|
55
|
+
* @param rules The array of inspection rules to run.
|
|
56
|
+
* @returns An array of analysis results.
|
|
57
|
+
* @example
|
|
58
|
+
* const rules: InspectionRule[] = [
|
|
59
|
+
* {
|
|
60
|
+
* inspection: "HasBinding",
|
|
61
|
+
* args: { name: "minimoEntre" },
|
|
62
|
+
* expected: false,
|
|
63
|
+
* },
|
|
64
|
+
* {
|
|
65
|
+
* inspection: "HasBinding",
|
|
66
|
+
* args: { name: "squareList" },
|
|
67
|
+
* expected: true,
|
|
68
|
+
* }
|
|
69
|
+
* ]
|
|
70
|
+
* const analyzer = new ASTAnalyzer(ast);
|
|
71
|
+
* const analysisResults = analyzer.analyze(expectations);
|
|
72
|
+
*/
|
|
73
|
+
analyze(ast, rules) {
|
|
74
|
+
const ruleResults = new Map();
|
|
75
|
+
const graphBuilder = new GraphBuilder();
|
|
76
|
+
const { defs, calls } = graphBuilder.build(ast);
|
|
77
|
+
for (const rule of rules) {
|
|
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 (!currentBinding || 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
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
let actual = false;
|
|
120
|
+
let error = undefined;
|
|
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 && binding) {
|
|
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, {
|
|
144
|
+
rule,
|
|
145
|
+
passed: actual === rule.expected,
|
|
146
|
+
actual,
|
|
147
|
+
error,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return [...ruleResults.values()];
|
|
151
|
+
}
|
|
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>;
|