yukigo 0.2.0 → 0.2.3
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 +38 -0
- package/dist/analyzer/index.d.ts +7 -0
- package/dist/analyzer/inspections/generic/generic.d.ts +1 -2
- package/dist/analyzer/inspections/generic/generic.js +2 -5
- 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 +82 -6
- package/package.json +4 -2
- package/src/analyzer/index.ts +9 -0
- package/src/analyzer/inspections/generic/generic.ts +2 -6
- package/src/utils/helpers.ts +112 -10
- package/tests/analyzer/helpers.spec.ts +16 -10
- package/tests/tester/Tester.spec.ts +0 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AssignOperation, Exist, UnifyOperation } from "yukigo-ast";
|
|
2
|
+
import { ScopedVisitor, VisitorConstructor } from "../../utils.js";
|
|
3
|
+
export declare class HasRedundantReduction extends ScopedVisitor {
|
|
4
|
+
visitAssignOperation(node: AssignOperation): void;
|
|
5
|
+
}
|
|
6
|
+
export declare class UsesUnificationOperator extends ScopedVisitor {
|
|
7
|
+
visitUnifyOperation(node: UnifyOperation): void;
|
|
8
|
+
}
|
|
9
|
+
export declare class UsesCut extends ScopedVisitor {
|
|
10
|
+
visitExist(node: Exist): void;
|
|
11
|
+
}
|
|
12
|
+
export declare class UsesFail extends ScopedVisitor {
|
|
13
|
+
visitExist(node: Exist): void;
|
|
14
|
+
}
|
|
15
|
+
export declare const logicSmells: Record<string, VisitorConstructor>;
|
|
@@ -0,0 +1,60 @@
|
|
|
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 { Exist, isYukigoPrimitive, StopTraversalException, SymbolPrimitive, } from "yukigo-ast";
|
|
8
|
+
import { AutoScoped, ScopedVisitor } from "../../utils.js";
|
|
9
|
+
let HasRedundantReduction = class HasRedundantReduction extends ScopedVisitor {
|
|
10
|
+
visitAssignOperation(node) {
|
|
11
|
+
const left = node.left;
|
|
12
|
+
const right = node.right;
|
|
13
|
+
if (!(left instanceof SymbolPrimitive))
|
|
14
|
+
return;
|
|
15
|
+
const redundantReductionParameters = isYukigoPrimitive(right);
|
|
16
|
+
const redundantReductionFunctors = right instanceof Exist;
|
|
17
|
+
const isRedundant = redundantReductionParameters || redundantReductionFunctors;
|
|
18
|
+
if (isRedundant)
|
|
19
|
+
throw new StopTraversalException();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
HasRedundantReduction = __decorate([
|
|
23
|
+
AutoScoped
|
|
24
|
+
], HasRedundantReduction);
|
|
25
|
+
export { HasRedundantReduction };
|
|
26
|
+
let UsesUnificationOperator = class UsesUnificationOperator extends ScopedVisitor {
|
|
27
|
+
visitUnifyOperation(node) {
|
|
28
|
+
throw new StopTraversalException();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
UsesUnificationOperator = __decorate([
|
|
32
|
+
AutoScoped
|
|
33
|
+
], UsesUnificationOperator);
|
|
34
|
+
export { UsesUnificationOperator };
|
|
35
|
+
let UsesCut = class UsesCut extends ScopedVisitor {
|
|
36
|
+
visitExist(node) {
|
|
37
|
+
if (node.identifier.value === "!")
|
|
38
|
+
throw new StopTraversalException();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
UsesCut = __decorate([
|
|
42
|
+
AutoScoped
|
|
43
|
+
], UsesCut);
|
|
44
|
+
export { UsesCut };
|
|
45
|
+
let UsesFail = class UsesFail extends ScopedVisitor {
|
|
46
|
+
visitExist(node) {
|
|
47
|
+
if (node.identifier.value === "fail")
|
|
48
|
+
throw new StopTraversalException();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
UsesFail = __decorate([
|
|
52
|
+
AutoScoped
|
|
53
|
+
], UsesFail);
|
|
54
|
+
export { UsesFail };
|
|
55
|
+
export const logicSmells = {
|
|
56
|
+
HasRedundantReduction: HasRedundantReduction,
|
|
57
|
+
UsesCut: UsesCut,
|
|
58
|
+
UsesFail: UsesFail,
|
|
59
|
+
UsesUnificationOperator: UsesUnificationOperator,
|
|
60
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ASTNode, Attribute, Class, Interface, Method, New, Object, PrimitiveMethod, Send } from "yukigo-ast";
|
|
2
|
+
import { InspectionVisitor, ScopedVisitor, VisitorConstructor } from "../../utils.js";
|
|
3
|
+
export declare class DeclaresAttribute extends ScopedVisitor {
|
|
4
|
+
private attributeName;
|
|
5
|
+
constructor(attributeName: string, scope?: string);
|
|
6
|
+
visitAttribute(node: Attribute): void;
|
|
7
|
+
}
|
|
8
|
+
export declare class DeclaresClass extends ScopedVisitor {
|
|
9
|
+
private className;
|
|
10
|
+
constructor(className: string, scope?: string);
|
|
11
|
+
visitClass(node: Class): void;
|
|
12
|
+
}
|
|
13
|
+
export declare class DeclaresInterface extends InspectionVisitor {
|
|
14
|
+
private interfaceName;
|
|
15
|
+
constructor(interfaceName: string);
|
|
16
|
+
visitInterface(node: Interface): void;
|
|
17
|
+
fallback(node: ASTNode): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class DeclaresMethod extends ScopedVisitor {
|
|
20
|
+
private methodName;
|
|
21
|
+
constructor(methodName: string, scope?: string);
|
|
22
|
+
visitMethod(node: Method): void;
|
|
23
|
+
}
|
|
24
|
+
export declare class DeclaresObject extends InspectionVisitor {
|
|
25
|
+
private objectName;
|
|
26
|
+
constructor(objectName: string);
|
|
27
|
+
visitObject(node: Object): void;
|
|
28
|
+
fallback(node: ASTNode): void;
|
|
29
|
+
}
|
|
30
|
+
export declare class DeclaresPrimitive extends ScopedVisitor {
|
|
31
|
+
private operatorName;
|
|
32
|
+
constructor(operatorName: string, scope?: string);
|
|
33
|
+
visitPrimitiveMethod(node: PrimitiveMethod): void;
|
|
34
|
+
}
|
|
35
|
+
export declare class DeclaresSuperclass extends ScopedVisitor {
|
|
36
|
+
private superclassName;
|
|
37
|
+
constructor(superclassName: string, scope?: string);
|
|
38
|
+
visitClass(node: Class): void;
|
|
39
|
+
}
|
|
40
|
+
export declare class Implements extends ScopedVisitor {
|
|
41
|
+
private interfaceName;
|
|
42
|
+
constructor(interfaceName: string, scope?: string);
|
|
43
|
+
visitClass(node: Class): void;
|
|
44
|
+
}
|
|
45
|
+
export declare class IncludeMixin extends ScopedVisitor {
|
|
46
|
+
private mixinsName;
|
|
47
|
+
constructor(mixinsName: string, scope?: string);
|
|
48
|
+
visitClass(node: Class): void;
|
|
49
|
+
}
|
|
50
|
+
export declare class Instantiates extends ScopedVisitor {
|
|
51
|
+
private className;
|
|
52
|
+
constructor(className: string, scope?: string);
|
|
53
|
+
visitNew(node: New): void;
|
|
54
|
+
}
|
|
55
|
+
export declare class UsesDynamicPolymorphism extends ScopedVisitor {
|
|
56
|
+
private selectorName;
|
|
57
|
+
private count;
|
|
58
|
+
constructor(selectorName: string, scope?: string);
|
|
59
|
+
visitMethod(node: Method): void;
|
|
60
|
+
}
|
|
61
|
+
export declare class UsesInheritance extends ScopedVisitor {
|
|
62
|
+
constructor(scope?: string);
|
|
63
|
+
visitClass(node: Class): void;
|
|
64
|
+
visitInterface(node: Interface): void;
|
|
65
|
+
}
|
|
66
|
+
export declare class UsesMixins extends ScopedVisitor {
|
|
67
|
+
constructor(scope?: string);
|
|
68
|
+
visitClass(node: Class): void;
|
|
69
|
+
}
|
|
70
|
+
export declare class UsesObjectComposition extends ScopedVisitor {
|
|
71
|
+
constructor(scope?: string);
|
|
72
|
+
visitAttribute(node: Attribute): void;
|
|
73
|
+
}
|
|
74
|
+
export declare class UsesStaticMethodOverload extends InspectionVisitor {
|
|
75
|
+
private scopes;
|
|
76
|
+
visitClass(node: Class): void;
|
|
77
|
+
visitObject(node: Object): void;
|
|
78
|
+
visitMethod(node: Method): void;
|
|
79
|
+
}
|
|
80
|
+
export declare class UsesDynamicMethodOverload extends ScopedVisitor {
|
|
81
|
+
constructor(scope?: string);
|
|
82
|
+
visitMethod(node: Method): void;
|
|
83
|
+
}
|
|
84
|
+
export declare class UsesTemplateMethod extends ScopedVisitor {
|
|
85
|
+
private abstractMethodsStack;
|
|
86
|
+
constructor(scope?: string);
|
|
87
|
+
visitClass(node: Class): void;
|
|
88
|
+
visitSend(node: Send): void;
|
|
89
|
+
}
|
|
90
|
+
export declare const objectInspections: Record<string, VisitorConstructor>;
|
|
@@ -0,0 +1,321 @@
|
|
|
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 { New, Self, StopTraversalException, SymbolPrimitive, } from "yukigo-ast";
|
|
8
|
+
import { AutoScoped, InspectionVisitor, ScopedVisitor } from "../../utils.js";
|
|
9
|
+
let DeclaresAttribute = class DeclaresAttribute extends ScopedVisitor {
|
|
10
|
+
attributeName;
|
|
11
|
+
constructor(attributeName, scope) {
|
|
12
|
+
super(scope);
|
|
13
|
+
this.attributeName = attributeName;
|
|
14
|
+
}
|
|
15
|
+
visitAttribute(node) {
|
|
16
|
+
if (node.identifier.value === this.attributeName)
|
|
17
|
+
throw new StopTraversalException();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
DeclaresAttribute = __decorate([
|
|
21
|
+
AutoScoped
|
|
22
|
+
], DeclaresAttribute);
|
|
23
|
+
export { DeclaresAttribute };
|
|
24
|
+
let DeclaresClass = class DeclaresClass extends ScopedVisitor {
|
|
25
|
+
className;
|
|
26
|
+
constructor(className, scope) {
|
|
27
|
+
super(scope);
|
|
28
|
+
this.className = className;
|
|
29
|
+
}
|
|
30
|
+
visitClass(node) {
|
|
31
|
+
if (node.identifier.value === this.className)
|
|
32
|
+
throw new StopTraversalException();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
DeclaresClass = __decorate([
|
|
36
|
+
AutoScoped
|
|
37
|
+
], DeclaresClass);
|
|
38
|
+
export { DeclaresClass };
|
|
39
|
+
export class DeclaresInterface extends InspectionVisitor {
|
|
40
|
+
interfaceName;
|
|
41
|
+
constructor(interfaceName) {
|
|
42
|
+
super();
|
|
43
|
+
this.interfaceName = interfaceName;
|
|
44
|
+
}
|
|
45
|
+
visitInterface(node) {
|
|
46
|
+
if (node.identifier.value === this.interfaceName)
|
|
47
|
+
throw new StopTraversalException();
|
|
48
|
+
}
|
|
49
|
+
fallback(node) { }
|
|
50
|
+
}
|
|
51
|
+
let DeclaresMethod = class DeclaresMethod extends ScopedVisitor {
|
|
52
|
+
methodName;
|
|
53
|
+
constructor(methodName, scope) {
|
|
54
|
+
super(scope);
|
|
55
|
+
this.methodName = methodName;
|
|
56
|
+
}
|
|
57
|
+
visitMethod(node) {
|
|
58
|
+
if (node.identifier.value === this.methodName)
|
|
59
|
+
throw new StopTraversalException();
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
DeclaresMethod = __decorate([
|
|
63
|
+
AutoScoped
|
|
64
|
+
], DeclaresMethod);
|
|
65
|
+
export { DeclaresMethod };
|
|
66
|
+
export class DeclaresObject extends InspectionVisitor {
|
|
67
|
+
objectName;
|
|
68
|
+
constructor(objectName) {
|
|
69
|
+
super();
|
|
70
|
+
this.objectName = objectName;
|
|
71
|
+
}
|
|
72
|
+
visitObject(node) {
|
|
73
|
+
if (node.identifier.value === this.objectName)
|
|
74
|
+
throw new StopTraversalException();
|
|
75
|
+
}
|
|
76
|
+
fallback(node) { }
|
|
77
|
+
}
|
|
78
|
+
let DeclaresPrimitive = class DeclaresPrimitive extends ScopedVisitor {
|
|
79
|
+
operatorName;
|
|
80
|
+
constructor(operatorName, scope) {
|
|
81
|
+
super(scope);
|
|
82
|
+
this.operatorName = operatorName;
|
|
83
|
+
}
|
|
84
|
+
visitPrimitiveMethod(node) {
|
|
85
|
+
if (node.operator === this.operatorName)
|
|
86
|
+
throw new StopTraversalException();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
DeclaresPrimitive = __decorate([
|
|
90
|
+
AutoScoped
|
|
91
|
+
], DeclaresPrimitive);
|
|
92
|
+
export { DeclaresPrimitive };
|
|
93
|
+
let DeclaresSuperclass = class DeclaresSuperclass extends ScopedVisitor {
|
|
94
|
+
superclassName;
|
|
95
|
+
constructor(superclassName, scope) {
|
|
96
|
+
super(scope);
|
|
97
|
+
this.superclassName = superclassName;
|
|
98
|
+
}
|
|
99
|
+
visitClass(node) {
|
|
100
|
+
if (node.extendsSymbol && node.extendsSymbol.value === this.superclassName)
|
|
101
|
+
throw new StopTraversalException();
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
DeclaresSuperclass = __decorate([
|
|
105
|
+
AutoScoped
|
|
106
|
+
], DeclaresSuperclass);
|
|
107
|
+
export { DeclaresSuperclass };
|
|
108
|
+
let Implements = class Implements extends ScopedVisitor {
|
|
109
|
+
interfaceName;
|
|
110
|
+
constructor(interfaceName, scope) {
|
|
111
|
+
super(scope);
|
|
112
|
+
this.interfaceName = interfaceName;
|
|
113
|
+
}
|
|
114
|
+
visitClass(node) {
|
|
115
|
+
if (node.implementsNode &&
|
|
116
|
+
node.implementsNode.identifier.value === this.interfaceName)
|
|
117
|
+
throw new StopTraversalException();
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
Implements = __decorate([
|
|
121
|
+
AutoScoped
|
|
122
|
+
], Implements);
|
|
123
|
+
export { Implements };
|
|
124
|
+
let IncludeMixin = class IncludeMixin extends ScopedVisitor {
|
|
125
|
+
mixinsName;
|
|
126
|
+
constructor(mixinsName, scope) {
|
|
127
|
+
super(scope);
|
|
128
|
+
this.mixinsName = mixinsName;
|
|
129
|
+
}
|
|
130
|
+
visitClass(node) {
|
|
131
|
+
if (node.includes.some((sym) => sym.value === this.mixinsName))
|
|
132
|
+
throw new StopTraversalException();
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
IncludeMixin = __decorate([
|
|
136
|
+
AutoScoped
|
|
137
|
+
], IncludeMixin);
|
|
138
|
+
export { IncludeMixin };
|
|
139
|
+
let Instantiates = class Instantiates extends ScopedVisitor {
|
|
140
|
+
className;
|
|
141
|
+
constructor(className, scope) {
|
|
142
|
+
super(scope);
|
|
143
|
+
this.className = className;
|
|
144
|
+
}
|
|
145
|
+
visitNew(node) {
|
|
146
|
+
if (node.identifier.value === this.className)
|
|
147
|
+
throw new StopTraversalException();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
Instantiates = __decorate([
|
|
151
|
+
AutoScoped
|
|
152
|
+
], Instantiates);
|
|
153
|
+
export { Instantiates };
|
|
154
|
+
let UsesDynamicPolymorphism = class UsesDynamicPolymorphism extends ScopedVisitor {
|
|
155
|
+
selectorName;
|
|
156
|
+
count = 0;
|
|
157
|
+
constructor(selectorName, scope) {
|
|
158
|
+
super(scope);
|
|
159
|
+
this.selectorName = selectorName;
|
|
160
|
+
}
|
|
161
|
+
visitMethod(node) {
|
|
162
|
+
if (node.identifier.value === this.selectorName) {
|
|
163
|
+
this.count++;
|
|
164
|
+
if (this.count >= 2)
|
|
165
|
+
throw new StopTraversalException();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
UsesDynamicPolymorphism = __decorate([
|
|
170
|
+
AutoScoped
|
|
171
|
+
], UsesDynamicPolymorphism);
|
|
172
|
+
export { UsesDynamicPolymorphism };
|
|
173
|
+
let UsesInheritance = class UsesInheritance extends ScopedVisitor {
|
|
174
|
+
constructor(scope) {
|
|
175
|
+
super(scope);
|
|
176
|
+
}
|
|
177
|
+
visitClass(node) {
|
|
178
|
+
if (node.extendsSymbol)
|
|
179
|
+
throw new StopTraversalException();
|
|
180
|
+
}
|
|
181
|
+
visitInterface(node) {
|
|
182
|
+
if (node.extendsSymbol && node.extendsSymbol.length > 0)
|
|
183
|
+
throw new StopTraversalException();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
UsesInheritance = __decorate([
|
|
187
|
+
AutoScoped
|
|
188
|
+
], UsesInheritance);
|
|
189
|
+
export { UsesInheritance };
|
|
190
|
+
let UsesMixins = class UsesMixins extends ScopedVisitor {
|
|
191
|
+
constructor(scope) {
|
|
192
|
+
super(scope);
|
|
193
|
+
}
|
|
194
|
+
visitClass(node) {
|
|
195
|
+
if (node.includes.length > 0)
|
|
196
|
+
throw new StopTraversalException();
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
UsesMixins = __decorate([
|
|
200
|
+
AutoScoped
|
|
201
|
+
], UsesMixins);
|
|
202
|
+
export { UsesMixins };
|
|
203
|
+
let UsesObjectComposition = class UsesObjectComposition extends ScopedVisitor {
|
|
204
|
+
constructor(scope) {
|
|
205
|
+
super(scope);
|
|
206
|
+
}
|
|
207
|
+
visitAttribute(node) {
|
|
208
|
+
if (node.expression instanceof New)
|
|
209
|
+
throw new StopTraversalException();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
UsesObjectComposition = __decorate([
|
|
213
|
+
AutoScoped
|
|
214
|
+
], UsesObjectComposition);
|
|
215
|
+
export { UsesObjectComposition };
|
|
216
|
+
export class UsesStaticMethodOverload extends InspectionVisitor {
|
|
217
|
+
scopes = [];
|
|
218
|
+
visitClass(node) {
|
|
219
|
+
this.scopes.push(new Set());
|
|
220
|
+
node.expression.accept(this);
|
|
221
|
+
this.scopes.pop();
|
|
222
|
+
}
|
|
223
|
+
visitObject(node) {
|
|
224
|
+
this.scopes.push(new Set());
|
|
225
|
+
node.expression.accept(this);
|
|
226
|
+
this.scopes.pop();
|
|
227
|
+
}
|
|
228
|
+
visitMethod(node) {
|
|
229
|
+
const currentScope = this.scopes[0];
|
|
230
|
+
const methodName = node.identifier.value;
|
|
231
|
+
if (currentScope.has(methodName))
|
|
232
|
+
throw new StopTraversalException();
|
|
233
|
+
currentScope.add(methodName);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
let UsesDynamicMethodOverload = class UsesDynamicMethodOverload extends ScopedVisitor {
|
|
237
|
+
constructor(scope) {
|
|
238
|
+
super(scope);
|
|
239
|
+
}
|
|
240
|
+
visitMethod(node) {
|
|
241
|
+
if (node.equations.length > 1)
|
|
242
|
+
throw new StopTraversalException();
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
UsesDynamicMethodOverload = __decorate([
|
|
246
|
+
AutoScoped
|
|
247
|
+
], UsesDynamicMethodOverload);
|
|
248
|
+
export { UsesDynamicMethodOverload };
|
|
249
|
+
let AbstractMethodCollector = class AbstractMethodCollector extends ScopedVisitor {
|
|
250
|
+
abstractMethods = new Set();
|
|
251
|
+
constructor(scope) {
|
|
252
|
+
super(scope);
|
|
253
|
+
}
|
|
254
|
+
visitMethod(node) {
|
|
255
|
+
if (node.getMetadata("isAbstract") === true)
|
|
256
|
+
this.abstractMethods.add(node.identifier.value);
|
|
257
|
+
}
|
|
258
|
+
// stop propagation to not mix scopes
|
|
259
|
+
visitClass(node) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
visitObject(node) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
AbstractMethodCollector = __decorate([
|
|
267
|
+
AutoScoped
|
|
268
|
+
], AbstractMethodCollector);
|
|
269
|
+
let UsesTemplateMethod = class UsesTemplateMethod extends ScopedVisitor {
|
|
270
|
+
abstractMethodsStack = [];
|
|
271
|
+
constructor(scope) {
|
|
272
|
+
super(scope);
|
|
273
|
+
}
|
|
274
|
+
visitClass(node) {
|
|
275
|
+
const collector = new AbstractMethodCollector(this.binding);
|
|
276
|
+
if (node.expression)
|
|
277
|
+
node.expression.accept(collector);
|
|
278
|
+
this.abstractMethodsStack.push(collector.abstractMethods);
|
|
279
|
+
node.expression.accept(this);
|
|
280
|
+
this.abstractMethodsStack.pop();
|
|
281
|
+
}
|
|
282
|
+
visitSend(node) {
|
|
283
|
+
if (node.receiver instanceof Self) {
|
|
284
|
+
if (this.abstractMethodsStack.length === 0)
|
|
285
|
+
return;
|
|
286
|
+
const currentAbstractMethods = this.abstractMethodsStack[0];
|
|
287
|
+
// This doesnt match if message is complex expression
|
|
288
|
+
if (!(node.selector instanceof SymbolPrimitive))
|
|
289
|
+
return;
|
|
290
|
+
const selectorName = node.selector.value;
|
|
291
|
+
const isMessageAbstract = currentAbstractMethods.has(selectorName);
|
|
292
|
+
if (isMessageAbstract)
|
|
293
|
+
throw new StopTraversalException();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
UsesTemplateMethod = __decorate([
|
|
298
|
+
AutoScoped
|
|
299
|
+
], UsesTemplateMethod);
|
|
300
|
+
export { UsesTemplateMethod };
|
|
301
|
+
export const objectInspections = {
|
|
302
|
+
DeclaresAttribute: DeclaresAttribute,
|
|
303
|
+
DeclaresClass: DeclaresClass,
|
|
304
|
+
DeclaresInterface: DeclaresInterface,
|
|
305
|
+
DeclaresMethod: DeclaresMethod,
|
|
306
|
+
DeclaresObject: DeclaresObject,
|
|
307
|
+
DeclaresPrimitive: DeclaresPrimitive,
|
|
308
|
+
DeclaresSuperclass: DeclaresSuperclass,
|
|
309
|
+
Implements: Implements,
|
|
310
|
+
IncludeMixin: IncludeMixin,
|
|
311
|
+
Inherits: DeclaresSuperclass, // alias for DeclaresSuperclass
|
|
312
|
+
Instantiates: Instantiates,
|
|
313
|
+
UsesDynamicPolymorphism: UsesDynamicPolymorphism,
|
|
314
|
+
UsesInheritance: UsesInheritance,
|
|
315
|
+
UsesMixins: UsesMixins,
|
|
316
|
+
UsesObjectComposition: UsesObjectComposition,
|
|
317
|
+
UsesStaticMethodOverload: UsesStaticMethodOverload,
|
|
318
|
+
UsesDynamicMethodOverload: UsesDynamicMethodOverload,
|
|
319
|
+
UsesTemplateMethod: UsesTemplateMethod,
|
|
320
|
+
UsesStaticPolymorphism: UsesStaticMethodOverload, // alias for UsesStaticMethodOverload
|
|
321
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Class, Interface, LogicalBinaryOperation, Method, Object, Return } from "yukigo-ast";
|
|
2
|
+
import { ScopedVisitor, VisitorConstructor } from "../../utils.js";
|
|
3
|
+
export declare class DoesNilTest extends ScopedVisitor {
|
|
4
|
+
visitLogicalBinaryOperation(node: LogicalBinaryOperation): void;
|
|
5
|
+
}
|
|
6
|
+
export declare class DoesTypeTest extends ScopedVisitor {
|
|
7
|
+
visitLogicalBinaryOperation(node: LogicalBinaryOperation): void;
|
|
8
|
+
}
|
|
9
|
+
export declare class ReturnsNil extends ScopedVisitor {
|
|
10
|
+
visitReturn(node: Return): void;
|
|
11
|
+
}
|
|
12
|
+
export declare class HasTooManyMethods extends ScopedVisitor {
|
|
13
|
+
private counter;
|
|
14
|
+
private readonly maxMethods;
|
|
15
|
+
constructor(maxMethods?: number, scopeName?: string);
|
|
16
|
+
visitInterface(node: Interface): void;
|
|
17
|
+
visitClass(node: Class): void;
|
|
18
|
+
visitObject(node: Object): void;
|
|
19
|
+
visitMethod(node: Method): void;
|
|
20
|
+
private checkMethodCount;
|
|
21
|
+
}
|
|
22
|
+
export declare class OverridesEqualOrHashButNotBoth extends ScopedVisitor {
|
|
23
|
+
visitClass(node: Class): void;
|
|
24
|
+
}
|
|
25
|
+
export declare class UsesNamedSelfReference extends ScopedVisitor {
|
|
26
|
+
visitObject(node: Object): void;
|
|
27
|
+
visitClass(node: Class): void;
|
|
28
|
+
private checkSelfReference;
|
|
29
|
+
}
|
|
30
|
+
export declare const objectSmells: Record<string, VisitorConstructor>;
|
|
@@ -0,0 +1,135 @@
|
|
|
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 { NilPrimitive, StopTraversalException, StringPrimitive, } from "yukigo-ast";
|
|
8
|
+
import { AutoScoped, InspectionVisitor, ScopedVisitor } from "../../utils.js";
|
|
9
|
+
import { Uses } from "../generic/generic.js";
|
|
10
|
+
class MethodCollector extends InspectionVisitor {
|
|
11
|
+
collectedMethods = [];
|
|
12
|
+
collect(node) {
|
|
13
|
+
node.expression.accept(this);
|
|
14
|
+
return this.collectedMethods;
|
|
15
|
+
}
|
|
16
|
+
visitMethod(node) {
|
|
17
|
+
this.collectedMethods.push(node);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
let DoesNilTest = class DoesNilTest extends ScopedVisitor {
|
|
21
|
+
visitLogicalBinaryOperation(node) {
|
|
22
|
+
if (node.left instanceof NilPrimitive ||
|
|
23
|
+
node.right instanceof NilPrimitive) {
|
|
24
|
+
throw new StopTraversalException();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
DoesNilTest = __decorate([
|
|
29
|
+
AutoScoped
|
|
30
|
+
], DoesNilTest);
|
|
31
|
+
export { DoesNilTest };
|
|
32
|
+
let DoesTypeTest = class DoesTypeTest extends ScopedVisitor {
|
|
33
|
+
visitLogicalBinaryOperation(node) {
|
|
34
|
+
if (node.left instanceof StringPrimitive ||
|
|
35
|
+
node.right instanceof StringPrimitive) {
|
|
36
|
+
throw new StopTraversalException();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
DoesTypeTest = __decorate([
|
|
41
|
+
AutoScoped
|
|
42
|
+
], DoesTypeTest);
|
|
43
|
+
export { DoesTypeTest };
|
|
44
|
+
let ReturnsNil = class ReturnsNil extends ScopedVisitor {
|
|
45
|
+
visitReturn(node) {
|
|
46
|
+
if (!Boolean(node.body) || node.body instanceof NilPrimitive)
|
|
47
|
+
throw new StopTraversalException();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
ReturnsNil = __decorate([
|
|
51
|
+
AutoScoped
|
|
52
|
+
], ReturnsNil);
|
|
53
|
+
export { ReturnsNil };
|
|
54
|
+
let HasTooManyMethods = class HasTooManyMethods extends ScopedVisitor {
|
|
55
|
+
counter = 0;
|
|
56
|
+
maxMethods;
|
|
57
|
+
constructor(maxMethods = 10, scopeName) {
|
|
58
|
+
super(scopeName);
|
|
59
|
+
this.maxMethods = maxMethods;
|
|
60
|
+
}
|
|
61
|
+
visitInterface(node) {
|
|
62
|
+
node.expression.accept(this);
|
|
63
|
+
this.checkMethodCount();
|
|
64
|
+
this.counter = 0;
|
|
65
|
+
}
|
|
66
|
+
visitClass(node) {
|
|
67
|
+
node.expression.accept(this);
|
|
68
|
+
this.checkMethodCount();
|
|
69
|
+
this.counter = 0;
|
|
70
|
+
}
|
|
71
|
+
visitObject(node) {
|
|
72
|
+
node.expression.accept(this);
|
|
73
|
+
this.checkMethodCount();
|
|
74
|
+
this.counter = 0;
|
|
75
|
+
}
|
|
76
|
+
visitMethod(node) {
|
|
77
|
+
this.counter += 1;
|
|
78
|
+
}
|
|
79
|
+
checkMethodCount() {
|
|
80
|
+
if (this.counter > this.maxMethods)
|
|
81
|
+
throw new StopTraversalException();
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
HasTooManyMethods = __decorate([
|
|
85
|
+
AutoScoped
|
|
86
|
+
], HasTooManyMethods);
|
|
87
|
+
export { HasTooManyMethods };
|
|
88
|
+
let OverridesEqualOrHashButNotBoth = class OverridesEqualOrHashButNotBoth extends ScopedVisitor {
|
|
89
|
+
visitClass(node) {
|
|
90
|
+
const collector = new MethodCollector();
|
|
91
|
+
const methods = collector.collect(node);
|
|
92
|
+
const names = methods.map((m) => m.identifier.value);
|
|
93
|
+
const hasEquals = names.includes("equals") ||
|
|
94
|
+
names.includes("==") ||
|
|
95
|
+
names.includes("eql?");
|
|
96
|
+
const hasHash = names.includes("hashCode") || names.includes("hash");
|
|
97
|
+
if ((hasEquals && !hasHash) || (!hasEquals && hasHash))
|
|
98
|
+
throw new StopTraversalException();
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
OverridesEqualOrHashButNotBoth = __decorate([
|
|
102
|
+
AutoScoped
|
|
103
|
+
], OverridesEqualOrHashButNotBoth);
|
|
104
|
+
export { OverridesEqualOrHashButNotBoth };
|
|
105
|
+
let UsesNamedSelfReference = class UsesNamedSelfReference extends ScopedVisitor {
|
|
106
|
+
visitObject(node) {
|
|
107
|
+
this.checkSelfReference(node.identifier.value, node.expression);
|
|
108
|
+
}
|
|
109
|
+
visitClass(node) {
|
|
110
|
+
this.checkSelfReference(node.identifier.value, node.expression);
|
|
111
|
+
}
|
|
112
|
+
checkSelfReference(selfName, body) {
|
|
113
|
+
const checker = new Uses(selfName, this.binding);
|
|
114
|
+
try {
|
|
115
|
+
body.accept(checker);
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
if (e instanceof StopTraversalException)
|
|
119
|
+
throw new StopTraversalException();
|
|
120
|
+
throw e;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
UsesNamedSelfReference = __decorate([
|
|
125
|
+
AutoScoped
|
|
126
|
+
], UsesNamedSelfReference);
|
|
127
|
+
export { UsesNamedSelfReference };
|
|
128
|
+
export const objectSmells = {
|
|
129
|
+
DoesNilTest: DoesNilTest,
|
|
130
|
+
DoesTypeTest: DoesTypeTest,
|
|
131
|
+
HasTooManyMethods: HasTooManyMethods,
|
|
132
|
+
OverridesEqualOrHashButNotBoth: OverridesEqualOrHashButNotBoth,
|
|
133
|
+
ReturnsNil: ReturnsNil,
|
|
134
|
+
UsesNamedSelfReference: UsesNamedSelfReference,
|
|
135
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Class, Fact, Function, Method, Object as YuObject, Procedure, Rule, TraverseVisitor, Variable, ASTNode } from "yukigo-ast";
|
|
2
|
+
export declare class InspectionVisitor extends TraverseVisitor {
|
|
3
|
+
fallback(node: ASTNode): void;
|
|
4
|
+
}
|
|
5
|
+
export interface VisitorConstructor {
|
|
6
|
+
new (...args: any[]): TraverseVisitor & {
|
|
7
|
+
setBinding?(binding: string): void;
|
|
8
|
+
};
|
|
9
|
+
IS_INTRANSITIVE?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export type InspectionMap = Record<string, VisitorConstructor>;
|
|
12
|
+
export declare class ScopedVisitor extends InspectionVisitor {
|
|
13
|
+
protected binding?: string;
|
|
14
|
+
inScope: boolean;
|
|
15
|
+
constructor(binding?: string);
|
|
16
|
+
setBinding(binding?: string): void;
|
|
17
|
+
visitVariable(node: Variable): void;
|
|
18
|
+
visitFunction(node: Function): void;
|
|
19
|
+
visitClass(node: Class): void;
|
|
20
|
+
visitObject(node: YuObject): void;
|
|
21
|
+
visitMethod(node: Method): void;
|
|
22
|
+
visitRule(node: Rule): void;
|
|
23
|
+
visitFact(node: Fact): void;
|
|
24
|
+
visitProcedure(node: Procedure): void;
|
|
25
|
+
fallback(node: ASTNode): void;
|
|
26
|
+
private manageScope;
|
|
27
|
+
}
|
|
28
|
+
export declare function AutoScoped<T extends {
|
|
29
|
+
new (...args: any[]): any;
|
|
30
|
+
}>(constructor: T): void;
|