cognitive-complexity-ts 0.6.5 → 0.8.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/build/shared/types.d.ts +6 -1
- package/build/src/cognitive-complexity/Scope.d.ts +4 -0
- package/build/src/cognitive-complexity/Scope.js +4 -0
- package/build/src/cognitive-complexity/cognitive-complexity.js +109 -59
- package/build/src/cognitive-complexity/debug.d.ts +1 -1
- package/build/src/cognitive-complexity/debug.js +2 -2
- package/build/src/cognitive-complexity/depth.d.ts +2 -2
- package/build/src/cognitive-complexity/depth.js +58 -36
- package/build/src/cognitive-complexity/node-inspection.d.ts +28 -2
- package/build/src/cognitive-complexity/node-inspection.js +110 -43
- package/build/src/cognitive-complexity/node-naming.js +25 -16
- package/build/src/cognitive-complexity/output.js +23 -14
- package/build/src/json.js +17 -7
- package/build/src/ui-server/ui-server.d.ts +0 -1
- package/build/src/ui-server/ui-server.js +18 -9
- package/build/src/util/util.d.ts +0 -2
- package/build/src/util/util.js +6 -32
- package/build/ui/ts/complexity-tree/ComplexityController.js +53 -11
- package/build/ui/ts/component/Filterers.js +10 -13
- package/build/ui/ts/domain/sortedOutput.js +5 -3
- package/package.json +13 -15
- package/ui/README.md +0 -26
package/build/shared/types.d.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
+
export type NodeKind = "class" | "file" | "function" | "module" | "type";
|
|
1
2
|
export interface ColumnAndLine {
|
|
2
3
|
column: number;
|
|
3
4
|
line: number;
|
|
4
5
|
}
|
|
5
6
|
export interface FunctionNodeInfo extends ColumnAndLine {
|
|
7
|
+
kind: "function";
|
|
6
8
|
name: string;
|
|
7
9
|
}
|
|
8
|
-
export interface ContainerOutput extends
|
|
10
|
+
export interface ContainerOutput extends ColumnAndLine {
|
|
11
|
+
kind: "class" | "function" | "module" | "type";
|
|
12
|
+
name: string;
|
|
9
13
|
score: number;
|
|
10
14
|
inner: ContainerOutput[];
|
|
11
15
|
}
|
|
12
16
|
export interface FileOutput {
|
|
17
|
+
kind: "file";
|
|
13
18
|
score: number;
|
|
14
19
|
inner: ContainerOutput[];
|
|
15
20
|
}
|
|
@@ -13,6 +13,10 @@ export declare class Scope {
|
|
|
13
13
|
readonly object: ReadonlyArray<string>;
|
|
14
14
|
constructor(local: ReadonlyArray<string>, object: ReadonlyArray<string>);
|
|
15
15
|
includes(name: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* @returns a new scope with the identifier from the node included,
|
|
18
|
+
* or if there is no identifier, it returns the scope not modified nor cloned
|
|
19
|
+
*/
|
|
16
20
|
maybeAdd(node: ts.Node, variableBeingDefined: string | undefined): Scope;
|
|
17
21
|
private scopeToAdd;
|
|
18
22
|
}
|
|
@@ -17,6 +17,10 @@ class Scope {
|
|
|
17
17
|
includes(name) {
|
|
18
18
|
return this.local.includes(name) || this.object.includes(name);
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* @returns a new scope with the identifier from the node included,
|
|
22
|
+
* or if there is no identifier, it returns the scope not modified nor cloned
|
|
23
|
+
*/
|
|
20
24
|
maybeAdd(node, variableBeingDefined) {
|
|
21
25
|
const { local, object } = this.scopeToAdd(node, variableBeingDefined);
|
|
22
26
|
if (local.length !== 0 || object.length !== 0) {
|
|
@@ -15,38 +15,60 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
25
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.fileCost =
|
|
36
|
+
exports.fileCost = fileCost;
|
|
27
37
|
const ts = __importStar(require("typescript"));
|
|
28
|
-
const util_1 = require("../util/util");
|
|
29
38
|
const node_naming_1 = require("./node-naming");
|
|
30
39
|
const depth_1 = require("./depth");
|
|
31
40
|
const node_inspection_1 = require("./node-inspection");
|
|
32
41
|
const Scope_1 = require("./Scope");
|
|
33
42
|
function fileCost(file) {
|
|
34
|
-
|
|
43
|
+
const initialContext = {
|
|
44
|
+
depth: 0,
|
|
45
|
+
scope: new Scope_1.Scope([], []),
|
|
46
|
+
topLevel: true,
|
|
47
|
+
variableBeingDefined: undefined,
|
|
48
|
+
};
|
|
49
|
+
const initialMutableContext = {
|
|
50
|
+
precedingOperator: undefined,
|
|
51
|
+
precedingTypeOperator: undefined,
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
kind: "file",
|
|
55
|
+
...nodeCost(file, initialContext, initialMutableContext),
|
|
56
|
+
};
|
|
35
57
|
}
|
|
36
|
-
|
|
37
|
-
function aggregateCostOfChildren(children, childDepth, topLevel, scope, variableBeingDefined) {
|
|
58
|
+
function aggregateCostOfChildren(children, ctx, mutCtx) {
|
|
38
59
|
let score = 0;
|
|
39
60
|
// The inner containers of a node is defined as the concat of:
|
|
40
61
|
// * all child nodes that are functions/namespaces/classes
|
|
41
62
|
// * all containers declared directly under a non-container child node
|
|
42
63
|
const inner = [];
|
|
43
64
|
for (const child of children) {
|
|
44
|
-
const childCost = nodeCost(child,
|
|
65
|
+
const childCost = nodeCost(child, ctx, mutCtx);
|
|
45
66
|
score += childCost.score;
|
|
46
67
|
// a function/class/namespace/type is part of the inner scope we want to output
|
|
47
|
-
const name = (0, node_naming_1.chooseContainerName)(child, variableBeingDefined);
|
|
68
|
+
const name = (0, node_naming_1.chooseContainerName)(child, ctx.variableBeingDefined);
|
|
48
69
|
if (name !== undefined) {
|
|
49
70
|
inner.push({
|
|
71
|
+
kind: (0, node_inspection_1.getNodeKind)(child),
|
|
50
72
|
...(0, node_inspection_1.getColumnAndLine)(child),
|
|
51
73
|
...childCost,
|
|
52
74
|
name,
|
|
@@ -57,10 +79,7 @@ function aggregateCostOfChildren(children, childDepth, topLevel, scope, variable
|
|
|
57
79
|
inner.push(...childCost.inner);
|
|
58
80
|
}
|
|
59
81
|
}
|
|
60
|
-
return {
|
|
61
|
-
score,
|
|
62
|
-
inner
|
|
63
|
-
};
|
|
82
|
+
return { score, inner };
|
|
64
83
|
}
|
|
65
84
|
function costOfDepth(node, depth) {
|
|
66
85
|
// increment for nesting level
|
|
@@ -89,9 +108,9 @@ function costOfDepth(node, depth) {
|
|
|
89
108
|
}
|
|
90
109
|
return 0;
|
|
91
110
|
}
|
|
92
|
-
function inherentCost(node, scope) {
|
|
111
|
+
function inherentCost(node, scope, mutCtx) {
|
|
93
112
|
// certain language features carry and inherent cost
|
|
94
|
-
if ((0, node_inspection_1.
|
|
113
|
+
if ((0, node_inspection_1.isNewSequenceOfBinaryOperators)(node, mutCtx.precedingOperator)
|
|
95
114
|
|| ts.isCatchClause(node)
|
|
96
115
|
|| ts.isConditionalExpression(node)
|
|
97
116
|
|| ts.isConditionalTypeNode(node)
|
|
@@ -102,7 +121,8 @@ function inherentCost(node, scope) {
|
|
|
102
121
|
|| ts.isMappedTypeNode(node)
|
|
103
122
|
|| ts.isSwitchStatement(node)
|
|
104
123
|
|| ts.isWhileStatement(node)
|
|
105
|
-
|| (0, node_inspection_1.isBreakOrContinueToLabel)(node)
|
|
124
|
+
|| (0, node_inspection_1.isBreakOrContinueToLabel)(node)
|
|
125
|
+
|| (0, node_inspection_1.isNewSequenceOfBinaryTypeOperators)(node, mutCtx.precedingTypeOperator)) {
|
|
106
126
|
return 1;
|
|
107
127
|
}
|
|
108
128
|
const calledName = (0, node_naming_1.getNameIfCalledNode)(node);
|
|
@@ -126,61 +146,91 @@ function inherentCost(node, scope) {
|
|
|
126
146
|
}
|
|
127
147
|
return score;
|
|
128
148
|
}
|
|
129
|
-
if ((0, node_inspection_1.isBinaryTypeOperator)(node)) {
|
|
130
|
-
// This node naturally represents a sequence of binary type operators.
|
|
131
|
-
// (unlike normal binary operators)
|
|
132
|
-
let score = 1;
|
|
133
|
-
// However, this sequence can contain nodes that are a different binary operator.
|
|
134
|
-
// We can assume that children of the internal syntax list that are binary operators
|
|
135
|
-
// are not the same kind as this node.
|
|
136
|
-
// Binary sub-expressions at either end of the syntax list
|
|
137
|
-
// do not break this sequence of operators in the code; they merely bookend it.
|
|
138
|
-
const syntaxList = node.getChildren()[0];
|
|
139
|
-
const numOfSequenceInterrupts = (0, util_1.countNotAtTheEnds)(syntaxList.getChildren(), node_inspection_1.isBinaryTypeOperator);
|
|
140
|
-
score += numOfSequenceInterrupts;
|
|
141
|
-
return score;
|
|
142
|
-
}
|
|
143
149
|
return 0;
|
|
144
150
|
}
|
|
145
151
|
/**
|
|
146
152
|
* @param node The node whose cost we want
|
|
147
|
-
* @param
|
|
148
|
-
* @param
|
|
149
|
-
*
|
|
153
|
+
* @param ctx Information about the context a node is in, which is needed to know the node cost.
|
|
154
|
+
* @param mutCtx Same as above, but this information can be changed while traversing,
|
|
155
|
+
* which will provide information up the call stack (where this function is called and higher).
|
|
150
156
|
*/
|
|
151
|
-
function nodeCost(node,
|
|
152
|
-
|
|
153
|
-
score += costOfDepth(node, depth);
|
|
157
|
+
function nodeCost(node, ctx, mutCtx) {
|
|
158
|
+
const { depth, topLevel, scope, variableBeingDefined } = ctx;
|
|
154
159
|
// get the ancestors container names from the perspective of this node's children
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
const { same, below } = (0, depth_1.whereAreChildren)(node);
|
|
160
|
+
const scopeForChildren = scope.maybeAdd(node, variableBeingDefined);
|
|
161
|
+
const { sameDepth, below } = (0, depth_1.whereAreChildren)(node);
|
|
158
162
|
/**
|
|
159
163
|
* The name being introduced (if there is one)
|
|
160
164
|
* for a variable whose declaration this scope is directly inside of.
|
|
161
165
|
* It is used to give names to anonymous functions and classes.
|
|
162
|
-
* let a = $a$ () => {};
|
|
163
|
-
* let a = ( $a$ () => {} );
|
|
164
|
-
* let a = f( $
|
|
165
|
-
* let a = () => { $undefined$ };
|
|
166
|
+
* let a = $a$ () => { $anonymous$ };
|
|
167
|
+
* let a = ( $a$ () => { $anonymous$ } );
|
|
168
|
+
* let a = f( $anonymous$ () => { $anonymous$ } );
|
|
166
169
|
*/
|
|
167
170
|
let newVariableBeingDefined = (0, node_naming_1.getNameOfAssignment)(node);
|
|
168
171
|
if (newVariableBeingDefined === undefined
|
|
172
|
+
&& variableBeingDefined !== undefined
|
|
169
173
|
&& (0, node_inspection_1.passThroughNameBeingAssigned)(node)) {
|
|
170
174
|
newVariableBeingDefined = variableBeingDefined;
|
|
171
175
|
}
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
const opSequenceInProgress = mutCtx.precedingOperator;
|
|
177
|
+
const typeOpSequenceInProgress = mutCtx.precedingTypeOperator;
|
|
178
|
+
const pauseOpSequence = (0, node_inspection_1.pausesASequenceOfBinaryOperators)(node);
|
|
179
|
+
const pauseTypeOpSequence = (0, node_inspection_1.pausesASequenceOfBinaryTypeOperators)(node);
|
|
180
|
+
// Check if the node ends any ongoing sequence of binary operators
|
|
181
|
+
if ((0, node_inspection_1.breaksASequenceOfBinaryOperators)(node)) {
|
|
182
|
+
mutCtx.precedingTypeOperator = undefined;
|
|
183
|
+
mutCtx.precedingOperator = undefined;
|
|
184
|
+
}
|
|
185
|
+
// Score for the current node
|
|
186
|
+
let score = inherentCost(node, scope, mutCtx);
|
|
187
|
+
score += costOfDepth(node, depth);
|
|
188
|
+
// If this is a binary operator, there won't be any children.
|
|
189
|
+
// Pass along the operator info
|
|
190
|
+
if ((0, node_inspection_1.isChainableBinaryOperator)(node)) {
|
|
191
|
+
mutCtx.precedingOperator = node.kind;
|
|
192
|
+
}
|
|
193
|
+
// If this is a binary type operator, there won't be any children.
|
|
194
|
+
// Pass along the operator info
|
|
195
|
+
else if ((0, node_inspection_1.isChainableBinaryTypeOperator)(node)) {
|
|
196
|
+
mutCtx.precedingTypeOperator = node.kind;
|
|
197
|
+
}
|
|
198
|
+
else if (pauseOpSequence) {
|
|
199
|
+
mutCtx.precedingOperator = undefined;
|
|
200
|
+
}
|
|
201
|
+
else if (pauseTypeOpSequence) {
|
|
202
|
+
mutCtx.precedingTypeOperator = undefined;
|
|
203
|
+
}
|
|
204
|
+
const ctxForChildrenSameDepth = {
|
|
205
|
+
depth,
|
|
206
|
+
topLevel,
|
|
207
|
+
precedingOperator: mutCtx.precedingOperator,
|
|
208
|
+
scope: scopeForChildren,
|
|
209
|
+
variableBeingDefined: newVariableBeingDefined,
|
|
210
|
+
};
|
|
211
|
+
const costOfSameDepthChildren = aggregateCostOfChildren(sameDepth, ctxForChildrenSameDepth, mutCtx);
|
|
212
|
+
// The nodes below this node have an increased depth number,
|
|
213
|
+
// unless this node is top level and it is a container.
|
|
214
|
+
const depthOfBelow = depth + (topLevel && (0, node_inspection_1.isContainer)(node) ? 0 : 1);
|
|
215
|
+
const ctxForChildrenBelow = {
|
|
216
|
+
...ctxForChildrenSameDepth,
|
|
217
|
+
depth: depthOfBelow,
|
|
218
|
+
topLevel: false,
|
|
219
|
+
};
|
|
220
|
+
const costOfBelowChildren = aggregateCostOfChildren(below, ctxForChildrenBelow, mutCtx);
|
|
221
|
+
// continue a paused sequence
|
|
222
|
+
if (pauseOpSequence) {
|
|
223
|
+
mutCtx.precedingOperator = opSequenceInProgress;
|
|
224
|
+
}
|
|
225
|
+
else if (pauseTypeOpSequence) {
|
|
226
|
+
mutCtx.precedingTypeOperator = typeOpSequenceInProgress;
|
|
227
|
+
}
|
|
178
228
|
score += costOfSameDepthChildren.score;
|
|
179
229
|
score += costOfBelowChildren.score;
|
|
180
|
-
const inner = [
|
|
181
|
-
|
|
182
|
-
inner
|
|
183
|
-
|
|
184
|
-
};
|
|
230
|
+
const inner = [
|
|
231
|
+
...costOfSameDepthChildren.inner,
|
|
232
|
+
...costOfBelowChildren.inner
|
|
233
|
+
];
|
|
234
|
+
return { inner, score };
|
|
185
235
|
}
|
|
186
236
|
//# sourceMappingURL=cognitive-complexity.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.testLog = void 0;
|
|
4
|
+
exports.logNode = logNode;
|
|
4
5
|
const util_1 = require("util");
|
|
5
6
|
exports.testLog = (0, util_1.debuglog)("test");
|
|
6
7
|
function logNode(child) {
|
|
7
8
|
(0, exports.testLog)(child.getFullText());
|
|
8
9
|
}
|
|
9
|
-
exports.logNode = logNode;
|
|
10
10
|
//# sourceMappingURL=debug.js.map
|
|
@@ -6,11 +6,11 @@ interface DepthOfChildren {
|
|
|
6
6
|
/**
|
|
7
7
|
* The same level of depth.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
sameDepth: readonly ts.Node[];
|
|
10
10
|
/**
|
|
11
11
|
* One level of depth below.
|
|
12
12
|
*/
|
|
13
|
-
below: ts.Node[];
|
|
13
|
+
below: readonly ts.Node[];
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* @param node The node whose children to categorise by depth
|
|
@@ -18,15 +18,25 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
18
18
|
}) : function(o, v) {
|
|
19
19
|
o["default"] = v;
|
|
20
20
|
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || function (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
};
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
28
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.whereAreChildren =
|
|
39
|
+
exports.whereAreChildren = whereAreChildren;
|
|
30
40
|
const ts = __importStar(require("typescript"));
|
|
31
41
|
const node_util_1 = require("../util/node-util");
|
|
32
42
|
const node_inspection_1 = require("./node-inspection");
|
|
@@ -39,6 +49,9 @@ function whereAreChildren(node) {
|
|
|
39
49
|
if (ts.isArrowFunction(node)) {
|
|
40
50
|
return arrowFunction(node);
|
|
41
51
|
}
|
|
52
|
+
else if (ts.isBinaryExpression(node)) {
|
|
53
|
+
return binaryExpression(node);
|
|
54
|
+
}
|
|
42
55
|
else if (ts.isCatchClause(node)) {
|
|
43
56
|
return catchClause(node);
|
|
44
57
|
}
|
|
@@ -74,20 +87,32 @@ function whereAreChildren(node) {
|
|
|
74
87
|
}
|
|
75
88
|
else {
|
|
76
89
|
return {
|
|
77
|
-
|
|
78
|
-
below: []
|
|
90
|
+
sameDepth: node.getChildren(),
|
|
91
|
+
below: [],
|
|
79
92
|
};
|
|
80
93
|
}
|
|
81
94
|
}
|
|
82
|
-
exports.whereAreChildren = whereAreChildren;
|
|
83
95
|
function arrowFunction(node) {
|
|
84
96
|
const children = node.getChildren();
|
|
85
97
|
// aggregate code inside SyntaxList
|
|
86
|
-
const
|
|
98
|
+
const sameDepth = children.slice(1, -1);
|
|
87
99
|
// aggregate code inside arrow function
|
|
88
100
|
const below = [children[children.length - 1]];
|
|
89
|
-
return {
|
|
101
|
+
return { sameDepth, below };
|
|
90
102
|
}
|
|
103
|
+
function binaryExpression(node) {
|
|
104
|
+
return {
|
|
105
|
+
sameDepth: node.getChildren(),
|
|
106
|
+
below: [],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// function binaryTypeExpression(node: ts.UnionTypeNode | ts.IntersectionTypeNode): DepthOfChildren {
|
|
110
|
+
// return {
|
|
111
|
+
// sameDepth: [node.types[0]],
|
|
112
|
+
// right: node.types.slice(1),
|
|
113
|
+
// below: [],
|
|
114
|
+
// }
|
|
115
|
+
// }
|
|
91
116
|
function catchClause(node) {
|
|
92
117
|
const children = node.getChildren();
|
|
93
118
|
const variableDeclaration = children.find(child => ts.isVariableDeclaration(child));
|
|
@@ -95,7 +120,7 @@ function catchClause(node) {
|
|
|
95
120
|
if (block === undefined)
|
|
96
121
|
throw new node_util_1.UnreachableNodeState(node, "catch clause has no block");
|
|
97
122
|
return {
|
|
98
|
-
|
|
123
|
+
sameDepth: variableDeclaration ? [variableDeclaration] : [],
|
|
99
124
|
below: [block],
|
|
100
125
|
};
|
|
101
126
|
}
|
|
@@ -105,7 +130,7 @@ function conditionalExpression(node) {
|
|
|
105
130
|
const thenCode = children[2];
|
|
106
131
|
const elseCode = children[4];
|
|
107
132
|
return {
|
|
108
|
-
|
|
133
|
+
sameDepth: [condition],
|
|
109
134
|
below: [thenCode, elseCode]
|
|
110
135
|
};
|
|
111
136
|
}
|
|
@@ -121,22 +146,22 @@ function conditionalType(node) {
|
|
|
121
146
|
// else code
|
|
122
147
|
below.push(...children.slice(endOfThen + 1));
|
|
123
148
|
return {
|
|
124
|
-
|
|
149
|
+
sameDepth: condition,
|
|
125
150
|
below,
|
|
126
151
|
};
|
|
127
152
|
}
|
|
128
153
|
function doStatement(node) {
|
|
129
|
-
const
|
|
154
|
+
const sameDepth = [];
|
|
130
155
|
const below = [];
|
|
131
156
|
const children = node.getChildren();
|
|
132
157
|
// aggregate block
|
|
133
158
|
below.push(children[1]);
|
|
134
159
|
// aggregate condition
|
|
135
|
-
|
|
136
|
-
return {
|
|
160
|
+
sameDepth.push(children[4]);
|
|
161
|
+
return { sameDepth, below };
|
|
137
162
|
}
|
|
138
163
|
function forLikeStatement(node) {
|
|
139
|
-
const
|
|
164
|
+
const sameDepth = [];
|
|
140
165
|
const below = [];
|
|
141
166
|
const children = node.getChildren();
|
|
142
167
|
// consume everything form the open parenthesis to the close parenthesis
|
|
@@ -146,27 +171,24 @@ function forLikeStatement(node) {
|
|
|
146
171
|
if (ts.isToken(child) && child.kind === ts.SyntaxKind.CloseParenToken) {
|
|
147
172
|
break;
|
|
148
173
|
}
|
|
149
|
-
|
|
174
|
+
sameDepth.push(child);
|
|
150
175
|
}
|
|
151
176
|
// consume looped code
|
|
152
177
|
below.push(children[i]);
|
|
153
|
-
return {
|
|
178
|
+
return { sameDepth, below };
|
|
154
179
|
}
|
|
155
180
|
function functionDeclaration(node) {
|
|
156
181
|
const children = node.getChildren();
|
|
157
|
-
const
|
|
182
|
+
const sameDepth = children.slice(1, -1);
|
|
158
183
|
const below = [children[children.length - 1]];
|
|
159
|
-
return {
|
|
160
|
-
below,
|
|
161
|
-
same,
|
|
162
|
-
};
|
|
184
|
+
return { sameDepth, below };
|
|
163
185
|
}
|
|
164
186
|
function functionExpression(node) {
|
|
165
187
|
const children = node.getChildren();
|
|
166
188
|
const functionBody = children.slice(-1);
|
|
167
189
|
const functionDecl = children.slice(0, -1);
|
|
168
190
|
return {
|
|
169
|
-
|
|
191
|
+
sameDepth: functionBody,
|
|
170
192
|
below: functionDecl
|
|
171
193
|
};
|
|
172
194
|
}
|
|
@@ -179,34 +201,34 @@ function ifStatement(node) {
|
|
|
179
201
|
if (ts.isIfStatement(elseCode)) {
|
|
180
202
|
// an else if structure is on the same depth
|
|
181
203
|
return {
|
|
182
|
-
|
|
204
|
+
sameDepth: [condition, elseCode],
|
|
183
205
|
below: [thenCode]
|
|
184
206
|
};
|
|
185
207
|
}
|
|
186
208
|
else {
|
|
187
209
|
// the contents of a solo else are at one depth below
|
|
188
210
|
return {
|
|
189
|
-
|
|
211
|
+
sameDepth: [condition],
|
|
190
212
|
below: [thenCode, elseCode]
|
|
191
213
|
};
|
|
192
214
|
}
|
|
193
215
|
}
|
|
194
216
|
return {
|
|
195
|
-
|
|
217
|
+
sameDepth: [condition],
|
|
196
218
|
below: [thenCode]
|
|
197
219
|
};
|
|
198
220
|
}
|
|
199
221
|
function methodDeclaration(node) {
|
|
200
|
-
const
|
|
222
|
+
const sameDepth = [];
|
|
201
223
|
const below = [];
|
|
202
224
|
for (const child of node.getChildren()) {
|
|
203
225
|
if (ts.isBlock(child)) {
|
|
204
226
|
below.push(child);
|
|
205
227
|
break;
|
|
206
228
|
}
|
|
207
|
-
|
|
229
|
+
sameDepth.push(child);
|
|
208
230
|
}
|
|
209
|
-
return {
|
|
231
|
+
return { sameDepth, below };
|
|
210
232
|
}
|
|
211
233
|
function switchStatement(node) {
|
|
212
234
|
const children = node.getChildren();
|
|
@@ -215,7 +237,7 @@ function switchStatement(node) {
|
|
|
215
237
|
// consume cases
|
|
216
238
|
const cases = [children[4]];
|
|
217
239
|
return {
|
|
218
|
-
|
|
240
|
+
sameDepth: condition,
|
|
219
241
|
below: cases
|
|
220
242
|
};
|
|
221
243
|
}
|
|
@@ -224,7 +246,7 @@ function whileStatement(node) {
|
|
|
224
246
|
const condition = children[2];
|
|
225
247
|
const loopCode = children[4];
|
|
226
248
|
return {
|
|
227
|
-
|
|
249
|
+
sameDepth: [condition],
|
|
228
250
|
below: [loopCode]
|
|
229
251
|
};
|
|
230
252
|
}
|
|
@@ -5,13 +5,39 @@ export type FunctionNode = ts.AccessorDeclaration | ts.ArrowFunction | ts.Functi
|
|
|
5
5
|
export declare function getColumnAndLine(node: ts.Node): ColumnAndLine;
|
|
6
6
|
export declare function getIdentifier(node: ts.Node): string | undefined;
|
|
7
7
|
export declare function getFirstNonParenthesizedAncestor(node: ts.Node): ts.Node;
|
|
8
|
+
export declare function getNodeKind(node: ts.Node): "class" | "function" | "module" | "type" | undefined;
|
|
8
9
|
export declare function getTextWithoutBrackets(node: ts.Node): string;
|
|
9
|
-
export declare function isBinaryTypeOperator(node: ts.Node): node is ts.UnionOrIntersectionTypeNode;
|
|
10
10
|
export declare function isBreakOrContinueToLabel(node: ts.Node): boolean;
|
|
11
11
|
export declare function isContainer(node: ts.Node): boolean;
|
|
12
12
|
export declare function isForLikeStatement(node: ts.Node): node is ForLikeStatement;
|
|
13
13
|
export declare function isFunctionNode(node: ts.Node): node is FunctionNode;
|
|
14
|
-
export declare function isSequenceOfDifferentBooleanOperations(node: ts.Node): boolean;
|
|
15
14
|
export declare function isSyntaxList(node: ts.Node): node is ts.SyntaxList;
|
|
15
|
+
export declare function isNewSequenceOfBinaryOperators(node: ts.Node, precedingOperator: ChainableBinaryOperator["kind"] | undefined): boolean;
|
|
16
|
+
export declare function isNewSequenceOfBinaryTypeOperators(node: ts.Node, precedingTypeOperator: ChainableBinaryTypeOperator["kind"] | undefined): boolean;
|
|
17
|
+
export type ChainableBinaryOperator = ts.Node & {
|
|
18
|
+
kind: ts.SyntaxKind.AmpersandAmpersandToken | ts.SyntaxKind.BarBarToken | ts.SyntaxKind.QuestionQuestionToken;
|
|
19
|
+
};
|
|
20
|
+
export declare function isChainableBinaryOperator(node: ts.Node): node is ChainableBinaryOperator;
|
|
21
|
+
export type ChainableBinaryTypeOperator = ts.Node & {
|
|
22
|
+
kind: ts.SyntaxKind.AmpersandToken | ts.SyntaxKind.BarToken;
|
|
23
|
+
};
|
|
24
|
+
export declare function isChainableBinaryTypeOperator(node: ts.Node): node is ChainableBinaryTypeOperator;
|
|
25
|
+
/**
|
|
26
|
+
* A node that causes an end to a sequence of binary operators
|
|
27
|
+
* (i.e. A && B { C && D }, the curly braces end the prior sequence;
|
|
28
|
+
* C will not be interpreted as part of the last sequence.
|
|
29
|
+
*/
|
|
30
|
+
export declare function breaksASequenceOfBinaryOperators(node: ts.Node): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* A node that doesn't cause an end to a sequence of binary operators
|
|
33
|
+
* (i.e. A && Node && B, the 2 && are in the same sequence)
|
|
34
|
+
* but the node's children don't form part of that sequence
|
|
35
|
+
* (i.e. A && Node(B && C) && D, this is two sequences, one inside Node(), the other outside)
|
|
36
|
+
*/
|
|
37
|
+
export declare function pausesASequenceOfBinaryOperators(node: ts.Node): node is ts.ElementAccessExpression | ts.CallLikeExpression | ts.PrefixUnaryExpression;
|
|
38
|
+
/**
|
|
39
|
+
* @see {pausesASequenceOfBinaryOperators} but for type operators
|
|
40
|
+
*/
|
|
41
|
+
export declare function pausesASequenceOfBinaryTypeOperators(node: ts.Node): node is ts.ParenthesizedExpression | ts.TypeReferenceNode | ts.AsExpression;
|
|
16
42
|
export declare function passThroughNameBeingAssigned(node: ts.Node): boolean;
|
|
17
43
|
export declare function report(node: ts.Node, depth?: number): void;
|