Skip to content
This repository was archived by the owner on Oct 3, 2024. It is now read-only.

Commit e20175a

Browse files
add no-useless-catch rule (#75)
1 parent 628fc99 commit e20175a

File tree

6 files changed

+171
-0
lines changed

6 files changed

+171
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Code Smells, or maintainability issues, are raised for places of code which migh
2828
* Boolean checks should not be inverted ([`no-inverted-boolean-check`])
2929
* Boolean literals should not be redundant ([`no-redundant-boolean`])
3030
* "switch" statements should have at least 3 "case" clauses ([`no-small-switch`])
31+
* "catch" clauses should do more than rethrow ([`no-useless-catch`])
3132
* Local variables should not be declared and then immediately returned or thrown ([`prefer-immediate-return`]) (:wrench: *fixable*)
3233
* Return of boolean expressions should not be wrapped into an "if-then-else" statement ([`prefer-single-boolean-return`])
3334
* A "while" loop should be used instead of a "for" loop ([`prefer-while`]) (:wrench: *fixable*)
@@ -45,6 +46,7 @@ Code Smells, or maintainability issues, are raised for places of code which migh
4546
[`no-redundant-boolean`]: ./docs/rules/no-redundant-boolean.md
4647
[`no-small-switch`]: ./docs/rules/no-small-switch.md
4748
[`no-use-of-empty-return-value`]: ./docs/rules/no-use-of-empty-return-value.md
49+
[`no-useless-catch`]: ./docs/rules/no-useless-catch.md
4850
[`prefer-immediate-return`]: ./docs/rules/prefer-immediate-return.md
4951
[`prefer-single-boolean-return`]: ./docs/rules/prefer-single-boolean-return.md
5052
[`prefer-while`]: ./docs/rules/prefer-while.md

docs/rules/no-useless-catch.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# no-useless-catch
2+
3+
A catch clause that only rethrows the caught exception has the same effect as omitting the catch altogether and letting it bubble up automatically, but with more code and the additional detriment of leaving maintainers scratching their heads.
4+
5+
Such clauses should either be eliminated or populated with the appropriate logic.
6+
7+
## Noncompliant Code Example
8+
9+
```javascript
10+
try {
11+
doSomething();
12+
} catch (ex) { // Noncompliant
13+
throw ex;
14+
}
15+
```
16+
17+
## Compliant Solution
18+
19+
```javascript
20+
try {
21+
doSomething();
22+
} catch (ex) {
23+
console.err(ex);
24+
throw ex;
25+
}
26+
```
27+
28+
or
29+
30+
```javascript
31+
doSomething();
32+
```

ruling/snapshots/no-useless-catch

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/create-react-app/tasks/screencast.js: 54

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const sonarjsRules: [string, Linter.RuleLevel][] = [
3333
["no-redundant-boolean", "error"],
3434
["no-small-switch", "error"],
3535
["no-use-of-empty-return-value", "error"],
36+
["no-useless-catch", "error"],
3637
["prefer-immediate-return", "error"],
3738
["prefer-single-boolean-return", "error"],
3839
["prefer-while", "error"],

src/rules/no-useless-catch.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* eslint-plugin-sonarjs
3+
* Copyright (C) 2018 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
// https://jira.sonarsource.com/browse/RSPEC-1940
21+
22+
import { Rule, SourceCode } from "eslint";
23+
import { Node, CatchClause, Statement, Pattern } from "estree";
24+
import { isThrowStatement } from "../utils/nodes";
25+
import { areEquivalent } from "../utils/equivalence";
26+
27+
const MESSAGE = "Add logic to this catch clause or eliminate it and rethrow the exception automatically.";
28+
29+
const rule: Rule.RuleModule = {
30+
create(context: Rule.RuleContext) {
31+
return { CatchClause: (node: Node) => visitCatchClause(node as CatchClause, context) };
32+
},
33+
};
34+
35+
function visitCatchClause(catchClause: CatchClause, context: Rule.RuleContext) {
36+
const statements = catchClause.body.body;
37+
if (statements.length === 1 && onlyRethrows(statements[0], catchClause.param, context.getSourceCode())) {
38+
const catchKeyword = context.getSourceCode().getFirstToken(catchClause);
39+
context.report({
40+
message: MESSAGE,
41+
loc: catchKeyword!.loc,
42+
});
43+
}
44+
}
45+
46+
function onlyRethrows(statement: Statement, catchParam: Pattern, sourceCode: SourceCode) {
47+
return isThrowStatement(statement) && areEquivalent(catchParam, statement.argument, sourceCode);
48+
}
49+
50+
export = rule;
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* eslint-plugin-sonarjs
3+
* Copyright (C) 2018 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
import { RuleTester } from "eslint";
21+
22+
const ruleTester = new RuleTester();
23+
import rule = require("../../src/rules/no-useless-catch");
24+
25+
ruleTester.run("no-useless-catch", rule, {
26+
valid: [
27+
{ code: `try {} catch (e) {}` },
28+
{
29+
code: `try {} catch (e) {
30+
foo();
31+
throw e;
32+
}`,
33+
},
34+
{
35+
code: `try {} catch (e) {
36+
if (x) {
37+
throw e;
38+
}
39+
}`,
40+
},
41+
{
42+
code: `try {} catch(e) { throw "foo"; }`,
43+
},
44+
{
45+
code: `try {} catch(e) { throw new Error("improve error message"); }`,
46+
},
47+
],
48+
invalid: [
49+
{
50+
code: `try {} catch (e) { throw e; }`,
51+
errors: [
52+
{
53+
message: "Add logic to this catch clause or eliminate it and rethrow the exception automatically.",
54+
line: 1,
55+
endLine: 1,
56+
column: 8,
57+
endColumn: 13,
58+
},
59+
],
60+
},
61+
{
62+
code: `try {} catch(e) {
63+
// some comment
64+
throw e;
65+
}`,
66+
errors: 1,
67+
},
68+
{
69+
code: `try {} catch({ message }) {
70+
throw { message };
71+
}`,
72+
errors: 1,
73+
},
74+
{
75+
code: `try {
76+
doSomething();
77+
} catch(e) {
78+
throw e;
79+
} finally {
80+
// ...
81+
}`,
82+
errors: 1,
83+
},
84+
],
85+
});

0 commit comments

Comments
 (0)