Skip to content

Commit e6120c0

Browse files
authored
Merge pull request #9 from Xvezda/feature/fix-bugs
feature/fix bugs
2 parents 986a812 + f440704 commit e6120c0

File tree

5 files changed

+114
-20
lines changed

5 files changed

+114
-20
lines changed

examples/fixed.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,23 @@ class Fizz {
2727
}
2828
}
2929
new Fizz().buzz();
30+
31+
const egg = {
32+
get ham() {
33+
return {
34+
/**
35+
* @throws {Error}
36+
*/
37+
get spam() {
38+
throw new Error();
39+
},
40+
};
41+
}
42+
};
43+
44+
const lol = () => {
45+
try {
46+
console.log(egg.ham.spam);
47+
} catch {}
48+
};
49+
lol();

examples/unsafe.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,18 @@ class Fizz {
1818
}
1919
}
2020
new Fizz().buzz();
21+
22+
const egg = {
23+
get ham() {
24+
return {
25+
get spam() {
26+
throw new Error();
27+
},
28+
};
29+
}
30+
};
31+
32+
const lol = () => {
33+
console.log(egg.ham.spam);
34+
};
35+
lol();

src/rules/no-implicit-propagation.js

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const { ESLintUtils, AST_NODE_TYPES } = require('@typescript-eslint/utils');
33
const utils = require('@typescript-eslint/type-utils');
44
const {
55
createRule,
6+
findClosest,
67
hasThrowsTag,
78
getOptionsFromContext,
89
getCalleeDeclaration,
@@ -164,25 +165,32 @@ module.exports = createRule({
164165
// TODO: Better way to handle this?
165166
if (/^\s*try\s*\{/.test(prevLine)) return;
166167

168+
const nodeToWrap = findClosest(node, (n) =>
169+
n.type === AST_NODE_TYPES.BlockStatement ||
170+
n.type === AST_NODE_TYPES.ExpressionStatement ||
171+
n.type === AST_NODE_TYPES.VariableDeclaration
172+
);
173+
if (!nodeToWrap) return;
174+
167175
context.report({
168176
node,
169177
messageId: 'implicitPropagation',
170178
fix(fixer) {
171179
return [
172-
fixer.insertTextBefore(node, `try {\n${newIndent}`),
173-
fixer.insertTextAfter(node, `\n${indent}} catch {}`),
180+
fixer.insertTextBefore(nodeToWrap, `try {\n${newIndent}`),
181+
fixer.insertTextAfter(nodeToWrap, `\n${indent}} catch {}`),
174182
];
175183
},
176184
});
177185
};
178186

179187
return {
180-
'ArrowFunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement:has(> CallExpression)': visitExpressionStatement,
181-
'FunctionDeclaration :not(TryStatement[handler!=null]) ExpressionStatement:has(> CallExpression)': visitExpressionStatement,
182-
'FunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement:has(> CallExpression)': visitExpressionStatement,
183-
'ArrowFunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement:has(> MemberExpression)': visitExpressionStatement,
184-
'FunctionDeclaration :not(TryStatement[handler!=null]) ExpressionStatement:has(> MemberExpression)': visitExpressionStatement,
185-
'FunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement:has(> MemberExpression)': visitExpressionStatement,
188+
'ArrowFunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement MemberExpression[property.type="Identifier"]': visitExpressionStatement,
189+
'FunctionDeclaration :not(TryStatement[handler!=null]) ExpressionStatement MemberExpression[property.type="Identifier"]': visitExpressionStatement,
190+
'FunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement MemberExpression[property.type="Identifier"]': visitExpressionStatement,
191+
'ArrowFunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement CallExpression[callee.type="Identifier"]': visitExpressionStatement,
192+
'FunctionDeclaration :not(TryStatement[handler!=null]) ExpressionStatement CallExpression[callee.type="Identifier"]': visitExpressionStatement,
193+
'FunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement CallExpression[callee.type="Identifier"]': visitExpressionStatement,
186194
'ArrowFunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement:has(> AssignmentExpression[left.type="MemberExpression"])': visitExpressionStatement,
187195
'FunctionDeclaration :not(TryStatement[handler!=null]) ExpressionStatement:has(> AssignmentExpression[left.type="MemberExpression"])': visitExpressionStatement,
188196
'FunctionExpression :not(TryStatement[handler!=null]) ExpressionStatement:has(> AssignmentExpression[left.type="MemberExpression"])': visitExpressionStatement,

src/rules/no-implicit-propagation.test.js

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,7 +790,56 @@ ruleTester.run(
790790
},
791791
],
792792
},
793+
{
794+
code: `
795+
const egg = {
796+
get ham() {
797+
return {
798+
/**
799+
* @throws {Error}
800+
*/
801+
get spam() {
802+
throw new Error();
803+
},
804+
};
805+
}
806+
};
807+
808+
const lol = () => {
809+
console.log(egg.ham.spam);
810+
};
811+
lol();
812+
`,
813+
output: `
814+
const egg = {
815+
get ham() {
816+
return {
817+
/**
818+
* @throws {Error}
819+
*/
820+
get spam() {
821+
throw new Error();
822+
},
823+
};
824+
}
825+
};
826+
827+
const lol = () => {
828+
try {
829+
console.log(egg.ham.spam);
830+
} catch {}
831+
};
832+
lol();
833+
`,
834+
errors: [
835+
{ messageId: 'implicitPropagation' },
836+
],
837+
options: [
838+
{
839+
tabLength: 2,
840+
},
841+
],
842+
},
793843
],
794844
},
795845
);
796-

src/utils.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,17 @@ const getDeclarationsByNode = (services, node) => {
6666
};
6767

6868
/**
69-
* @param {import('@typescript-eslint/utils').TSESTree.ExpressionStatement} node
69+
* @param {import('@typescript-eslint/utils').TSESTree.Node} node
7070
* @return {import('@typescript-eslint/utils').TSESTree.Node | null}
7171
*/
7272
const getCalleeFromExpression = (node) => {
73-
switch (node.expression.type) {
73+
switch (node.type) {
74+
case AST_NODE_TYPES.MemberExpression:
75+
return node.property;
7476
case AST_NODE_TYPES.CallExpression:
75-
return node.expression.callee;
77+
return node.callee;
7678
case AST_NODE_TYPES.AssignmentExpression:
77-
return node.expression.left;
78-
case AST_NODE_TYPES.MemberExpression:
79-
return node.expression.property;
79+
return node.left;
8080
default:
8181
break;
8282
}
@@ -96,16 +96,18 @@ const getCalleeDeclaration = (services, node) => {
9696
return null;
9797
}
9898

99-
switch (node.expression.type) {
100-
case AST_NODE_TYPES.CallExpression:
101-
return declarations[0];
99+
switch (node.type) {
102100
case AST_NODE_TYPES.MemberExpression:
103101
const getter = declarations
104102
.find(declaration =>
105103
services.tsNodeToESTreeNodeMap
106-
.get(declaration).kind === 'get'
104+
.get(declaration)?.kind === 'get'
107105
);
108-
return getter ?? declarations[0];
106+
if (getter) {
107+
return getter;
108+
}
109+
case AST_NODE_TYPES.CallExpression:
110+
return declarations[0];
109111
case AST_NODE_TYPES.AssignmentExpression:
110112
const setter = declarations
111113
.find(declaration =>

0 commit comments

Comments
 (0)