Skip to content

Commit

Permalink
feat(eslint-plugin): [no-unsafe-call] support tagged templates (#1680)
Browse files Browse the repository at this point in the history
  • Loading branch information
bradzacher authored Mar 9, 2020
1 parent 144345c commit 55a58ff
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 10 deletions.
5 changes: 5 additions & 0 deletions packages/eslint-plugin/docs/rules/no-unsafe-call.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ nestedAny.prop['a']();

new anyVar();
new nestedAny.prop();

anyVar`foo`;
nestedAny.prop`foo`;
```

Examples of **correct** code for this rule:
Expand All @@ -33,6 +36,8 @@ nestedAny.prop.a();
(() => {})();

new Map();

String.raw`foo`;
```

## Related to
Expand Down
25 changes: 15 additions & 10 deletions packages/eslint-plugin/src/rules/no-unsafe-call.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { TSESTree } from '@typescript-eslint/experimental-utils';
import * as util from '../util';

type MessageIds = 'unsafeCall' | 'unsafeNew';
type MessageIds = 'unsafeCall' | 'unsafeNew' | 'unsafeTemplateTag';

export default util.createRule<[], MessageIds>({
name: 'no-unsafe-call',
Expand All @@ -16,6 +16,7 @@ export default util.createRule<[], MessageIds>({
messages: {
unsafeCall: 'Unsafe call of an any typed value',
unsafeNew: 'Unsafe construction of an any type value',
unsafeTemplateTag: 'Unsafe any typed template tag',
},
schema: [],
},
Expand All @@ -25,14 +26,11 @@ export default util.createRule<[], MessageIds>({
const checker = program.getTypeChecker();

function checkCall(
node:
| TSESTree.CallExpression
| TSESTree.OptionalCallExpression
| TSESTree.NewExpression,
reportingNode: TSESTree.Expression = node.callee,
messageId: MessageIds = 'unsafeCall',
node: TSESTree.Node,
reportingNode: TSESTree.Node,
messageId: MessageIds,
): void {
const tsNode = esTreeNodeToTSNodeMap.get(node.callee);
const tsNode = esTreeNodeToTSNodeMap.get(node);
const type = checker.getTypeAtLocation(tsNode);
if (util.isTypeAnyType(type)) {
context.report({
Expand All @@ -43,9 +41,16 @@ export default util.createRule<[], MessageIds>({
}

return {
'CallExpression, OptionalCallExpression': checkCall,
'CallExpression, OptionalCallExpression'(
node: TSESTree.CallExpression | TSESTree.OptionalCallExpression,
): void {
checkCall(node.callee, node.callee, 'unsafeCall');
},
NewExpression(node): void {
checkCall(node, node, 'unsafeNew');
checkCall(node.callee, node, 'unsafeNew');
},
'TaggedTemplateExpression > *.tag'(node: TSESTree.Node): void {
checkCall(node, node, 'unsafeTemplateTag');
},
};
},
Expand Down
21 changes: 21 additions & 0 deletions packages/eslint-plugin/tests/rules/no-unsafe-call.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ruleTester.run('no-unsafe-call', rule, {
'function foo(x?: { a: () => void }) { x?.a() }',
'function foo(x: { a?: () => void }) { x.a?.() }',
'new Map()',
'String.raw`foo`',
],
invalid: [
...batchedSingleLineTests({
Expand Down Expand Up @@ -102,5 +103,25 @@ function foo(x: { a: any }) { new x.a() }
},
],
}),
...batchedSingleLineTests({
code: `
function foo(x: any) { x\`foo\` }
function foo(x: { tag: any }) { x.tag\`foo\` }
`,
errors: [
{
messageId: 'unsafeTemplateTag',
line: 2,
column: 24,
endColumn: 25,
},
{
messageId: 'unsafeTemplateTag',
line: 3,
column: 33,
endColumn: 38,
},
],
}),
],
});

0 comments on commit 55a58ff

Please sign in to comment.