(flow, noCacheCheck)
| 70174 | node.operatorToken.kind === 56 /* SyntaxKind.BarBarToken */ && isFalseExpression(node.left) && isFalseExpression(node.right)); |
| 70175 | } |
| 70176 | function isReachableFlowNodeWorker(flow, noCacheCheck) { |
| 70177 | while (true) { |
| 70178 | if (flow === lastFlowNode) { |
| 70179 | return lastFlowNodeReachable; |
| 70180 | } |
| 70181 | var flags = flow.flags; |
| 70182 | if (flags & 4096 /* FlowFlags.Shared */) { |
| 70183 | if (!noCacheCheck) { |
| 70184 | var id = getFlowNodeId(flow); |
| 70185 | var reachable = flowNodeReachable[id]; |
| 70186 | return reachable !== undefined ? reachable : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*noCacheCheck*/ true)); |
| 70187 | } |
| 70188 | noCacheCheck = false; |
| 70189 | } |
| 70190 | if (flags & (16 /* FlowFlags.Assignment */ | 96 /* FlowFlags.Condition */ | 256 /* FlowFlags.ArrayMutation */)) { |
| 70191 | flow = flow.antecedent; |
| 70192 | } |
| 70193 | else if (flags & 512 /* FlowFlags.Call */) { |
| 70194 | var signature = getEffectsSignature(flow.node); |
| 70195 | if (signature) { |
| 70196 | var predicate = getTypePredicateOfSignature(signature); |
| 70197 | if (predicate && predicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ && !predicate.type) { |
| 70198 | var predicateArgument = flow.node.arguments[predicate.parameterIndex]; |
| 70199 | if (predicateArgument && isFalseExpression(predicateArgument)) { |
| 70200 | return false; |
| 70201 | } |
| 70202 | } |
| 70203 | if (getReturnTypeOfSignature(signature).flags & 131072 /* TypeFlags.Never */) { |
| 70204 | return false; |
| 70205 | } |
| 70206 | } |
| 70207 | flow = flow.antecedent; |
| 70208 | } |
| 70209 | else if (flags & 4 /* FlowFlags.BranchLabel */) { |
| 70210 | // A branching point is reachable if any branch is reachable. |
| 70211 | return ts.some(flow.antecedents, function (f) { return isReachableFlowNodeWorker(f, /*noCacheCheck*/ false); }); |
| 70212 | } |
| 70213 | else if (flags & 8 /* FlowFlags.LoopLabel */) { |
| 70214 | var antecedents = flow.antecedents; |
| 70215 | if (antecedents === undefined || antecedents.length === 0) { |
| 70216 | return false; |
| 70217 | } |
| 70218 | // A loop is reachable if the control flow path that leads to the top is reachable. |
| 70219 | flow = antecedents[0]; |
| 70220 | } |
| 70221 | else if (flags & 128 /* FlowFlags.SwitchClause */) { |
| 70222 | // The control flow path representing an unmatched value in a switch statement with |
| 70223 | // no default clause is unreachable if the switch statement is exhaustive. |
| 70224 | if (flow.clauseStart === flow.clauseEnd && isExhaustiveSwitchStatement(flow.switchStatement)) { |
| 70225 | return false; |
| 70226 | } |
| 70227 | flow = flow.antecedent; |
| 70228 | } |
| 70229 | else if (flags & 1024 /* FlowFlags.ReduceLabel */) { |
| 70230 | // Cache is unreliable once we start adjusting labels |
| 70231 | lastFlowNode = undefined; |
| 70232 | var target = flow.target; |
| 70233 | var saveAntecedents = target.antecedents; |
no test coverage detected
searching dependent graphs…