Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
this.addFinding(
start,
node.end,
"'try' statement is unnecessary because the 'try' block is empty.",
hasFinally ? deleteStatementLeavingBlock(node, finallyBlock!, this.sourceFile) : deleteStatement(node),
);
} else if (catchClause !== undefined && isRethrow(catchClause)) {
// reminder for myself: empty catch clause can be used to simply ignore errors and is never redundant
this.addFinding(
start,
node.end,
`${
hasFinally ? "'catch' clause" : "'try' statement"
} is unnecessary because the 'catch' clause only rethrows the error.`,
hasFinally
? Replacement.delete(catchClause.getStart(this.sourceFile), finallyBlock!.pos - 'finally'.length)
: deleteStatementLeavingBlock(node, tryBlock, this.sourceFile),
);
} else if (finallyBlock !== undefined && finallyBlock.statements.length === 0) {
if (catchClause === undefined) {
this.addFinding(
start,
node.end,
"'try' statement is unnecessary because the 'finally' block is empty.",
deleteStatementLeavingBlock(node, tryBlock, this.sourceFile),
);
} else {
this.addFinding(
finallyBlock!.pos - 'finally'.length,
node.end,
"Empty 'finally' clause is unnecessary.",
Replacement.delete(catchClause.end, finallyBlock.end),
private createFinding(message: string, severity: Severity, location: ts.TextRange, fixLocation = location): Finding {
return {
ruleName: 'useless-line-switch',
severity, // tslint:disable-line:object-shorthand-properties-first
message, // tslint:disable-line:object-shorthand-properties-first
start: this.createPosition(location.pos),
end: this.createPosition(location.end),
fix: {replacements: [Replacement.delete(fixLocation.pos, fixLocation.end)]},
};
}
}
let end = arg.end;
if (i !== args.length - 1) {
end = args[i + 1].getStart(sourceFile);
} else if (args.hasTrailingComma) {
end = args.end;
}
// remove empty object iteral and the following comma if exists
fix.push(Replacement.delete(removedPrevious ? arg.getStart(sourceFile) : arg.pos, end));
removedPrevious = true;
} else {
const start = arg.getStart(sourceFile);
fix.push(
// remove open brace
Replacement.delete(start, start + 1),
// remove trailing comma if exists and close brace
Replacement.delete(arg.properties[arg.properties.length - 1].end, arg.end),
);
removedPrevious = false;
}
}
return fix;
}
grandparent.arguments.length !== 2 ||
grandparent.arguments.some(isSpreadElement)
)
continue;
const fixed = ts.createBinary(
ts.getMutableClone(grandparent.arguments[0]),
ts.SyntaxKind.AsteriskAsteriskToken,
ts.getMutableClone(grandparent.arguments[1]),
);
const fix = [Replacement.replace(grandparent.arguments[1].pos - 1, grandparent.arguments[1].pos, '**')];
fixed.left.parent = fixed.right.parent = fixed;
if (expressionNeedsParensWhenReplacingNode(
fixed,
grandparent,
)) {
fix.push(Replacement.delete(grandparent.getStart(this.sourceFile), grandparent.arguments[0].pos - 1));
} else {
fix.push(
Replacement.delete(grandparent.getStart(this.sourceFile), grandparent.arguments[0].getStart(this.sourceFile)),
Replacement.delete(grandparent.end - 1, grandparent.end),
);
}
if (expressionNeedsParens(fixed.left))
fix.push(
Replacement.append(grandparent.arguments[0].getStart(this.sourceFile), '('),
Replacement.append(grandparent.arguments[0].end, ')'),
);
if (expressionNeedsParens(fixed.right))
fix.push(
Replacement.append(grandparent.arguments[1].getStart(this.sourceFile), '('),
Replacement.append(grandparent.arguments[1].end, ')'),
);
function deleteStatement(node: ts.TryStatement) {
return isInSingleStatementContext(node)
? Replacement.replace(getStart(node), node.end, '{}')
: Replacement.delete(node.pos, node.end);
}
function deleteStatementLeavingBlock(node: ts.TryStatement, block: ts.Block, sourceFile: ts.SourceFile) {
const start = getStart(node);
return canStripBlockOnRemove(node, block)
? [
Replacement.delete(start, block.statements[0].getStart(sourceFile)),
Replacement.delete(block.statements[block.statements.length - 1].end, node.end),
]
: [
Replacement.delete(start, block.statements.pos - 1),
Replacement.delete(block.end, node.end),
];
}
: deleteStatementLeavingBlock(node, tryBlock, this.sourceFile),
);
} else if (finallyBlock !== undefined && finallyBlock.statements.length === 0) {
if (catchClause === undefined) {
this.addFinding(
start,
node.end,
"'try' statement is unnecessary because the 'finally' block is empty.",
deleteStatementLeavingBlock(node, tryBlock, this.sourceFile),
);
} else {
this.addFinding(
finallyBlock!.pos - 'finally'.length,
node.end,
"Empty 'finally' clause is unnecessary.",
Replacement.delete(catchClause.end, finallyBlock.end),
);
}
}
}
}
}
function deleteStatementLeavingBlock(node: ts.TryStatement, block: ts.Block, sourceFile: ts.SourceFile) {
const start = getStart(node);
return canStripBlockOnRemove(node, block)
? [
Replacement.delete(start, block.statements[0].getStart(sourceFile)),
Replacement.delete(block.statements[block.statements.length - 1].end, node.end),
]
: [
Replacement.delete(start, block.statements.pos - 1),
Replacement.delete(block.end, node.end),
];
}
);
this.addFinding(
match.index,
node.end,
"Unnecessary 'await' of a non-Promise value.",
fix,
);
} else if (node.kind === ts.SyntaxKind.AwaitKeyword && node.end === re.lastIndex) {
const parent = node.parent!;
if (isForOfStatement(parent) && !this.isAsyncIterable(parent.expression)) {
const start = node.pos - 'for'.length;
this.addFinding(
start,
parent.statement.pos,
"Unnecessary 'for await' of a non-AsyncIterable value.",
Replacement.delete(start + 'for'.length, re.lastIndex),
);
}
}
}
}