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.
@@ -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 FunctionNodeInfo {
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 (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
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 = void 0;
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
- return nodeCost(file, true);
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
- exports.fileCost = fileCost;
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, topLevel, childDepth, scope, variableBeingDefined);
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.isSequenceOfDifferentBooleanOperations)(node)
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 topLevel Whether the node is at the top level of a file
148
- * @param depth The depth the node is at
149
- * @param scope The scope at the node
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, topLevel, depth = 0, scope = new Scope_1.Scope([], []), variableBeingDefined = undefined) {
152
- let score = inherentCost(node, scope);
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 namedAncestorsOfChildren = scope
156
- .maybeAdd(node, variableBeingDefined);
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( $undefined$ () => {} );
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 costOfSameDepthChildren = aggregateCostOfChildren(same, depth, topLevel, namedAncestorsOfChildren, newVariableBeingDefined);
173
- // The nodes below this node have the same depth number,
174
- // iff this node is top level and it is a container.
175
- const container = (0, node_inspection_1.isContainer)(node);
176
- const depthOfBelow = depth + (topLevel && container ? 0 : 1);
177
- const costOfBelowChildren = aggregateCostOfChildren(below, depthOfBelow, false, namedAncestorsOfChildren, newVariableBeingDefined);
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 = [...costOfSameDepthChildren.inner, ...costOfBelowChildren.inner];
181
- return {
182
- inner,
183
- score,
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,3 +1,3 @@
1
1
  import * as ts from "typescript";
2
- export declare const testLog: (msg: string, ...param: any[]) => void;
2
+ export declare const testLog: import("util").DebugLogger;
3
3
  export declare function logNode(child: ts.Node): void;
@@ -1,10 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.logNode = exports.testLog = void 0;
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
- same: ts.Node[];
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 (mod) {
22
- if (mod && mod.__esModule) return mod;
23
- var result = {};
24
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25
- __setModuleDefault(result, mod);
26
- return result;
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 = void 0;
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
- same: node.getChildren(),
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 same = children.slice(1, -1);
98
+ const sameDepth = children.slice(1, -1);
87
99
  // aggregate code inside arrow function
88
100
  const below = [children[children.length - 1]];
89
- return { same, below };
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
- same: variableDeclaration ? [variableDeclaration] : [],
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
- same: [condition],
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
- same: condition,
149
+ sameDepth: condition,
125
150
  below,
126
151
  };
127
152
  }
128
153
  function doStatement(node) {
129
- const same = [];
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
- same.push(children[4]);
136
- return { same, below };
160
+ sameDepth.push(children[4]);
161
+ return { sameDepth, below };
137
162
  }
138
163
  function forLikeStatement(node) {
139
- const same = [];
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
- same.push(child);
174
+ sameDepth.push(child);
150
175
  }
151
176
  // consume looped code
152
177
  below.push(children[i]);
153
- return { same, below };
178
+ return { sameDepth, below };
154
179
  }
155
180
  function functionDeclaration(node) {
156
181
  const children = node.getChildren();
157
- const same = children.slice(1, -1);
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
- same: functionBody,
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
- same: [condition, elseCode],
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
- same: [condition],
211
+ sameDepth: [condition],
190
212
  below: [thenCode, elseCode]
191
213
  };
192
214
  }
193
215
  }
194
216
  return {
195
- same: [condition],
217
+ sameDepth: [condition],
196
218
  below: [thenCode]
197
219
  };
198
220
  }
199
221
  function methodDeclaration(node) {
200
- const same = [];
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
- same.push(child);
229
+ sameDepth.push(child);
208
230
  }
209
- return { same, below };
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
- same: condition,
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
- same: [condition],
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;