UNPKG

2.4 kBJavaScriptView Raw
1'use strict';
2const astUtils = require('eslint-ast-utils');
3const getDocumentationUrl = require('./utils/get-documentation-url');
4const isLiteralValue = require('./utils/is-literal-value');
5
6const isApplySignature = (argument1, argument2) => (
7 (
8 // eslint-disable-next-line unicorn/no-null
9 isLiteralValue(argument1, null) ||
10 argument1.type === 'ThisExpression'
11 ) &&
12 (
13 argument2.type === 'ArrayExpression' ||
14 (argument2.type === 'Identifier' && argument2.name === 'arguments')
15 )
16);
17
18const getReflectApplyCall = (sourceCode, func, receiver, arguments_) => (
19 `Reflect.apply(${sourceCode.getText(func)}, ${sourceCode.getText(receiver)}, ${sourceCode.getText(arguments_)})`
20);
21
22const fixDirectApplyCall = (node, sourceCode) => {
23 if (
24 astUtils.getPropertyName(node.callee) === 'apply' &&
25 node.arguments.length === 2 &&
26 isApplySignature(node.arguments[0], node.arguments[1])
27 ) {
28 return fixer => (
29 fixer.replaceText(
30 node,
31 getReflectApplyCall(sourceCode, node.callee.object, node.arguments[0], node.arguments[1])
32 )
33 );
34 }
35};
36
37const fixFunctionPrototypeCall = (node, sourceCode) => {
38 if (
39 astUtils.getPropertyName(node.callee) === 'call' &&
40 astUtils.getPropertyName(node.callee.object) === 'apply' &&
41 astUtils.getPropertyName(node.callee.object.object) === 'prototype' &&
42 node.callee.object.object.object &&
43 node.callee.object.object.object.type === 'Identifier' &&
44 node.callee.object.object.object.name === 'Function' &&
45 node.arguments.length === 3 &&
46 isApplySignature(node.arguments[1], node.arguments[2])
47 ) {
48 return fixer => (
49 fixer.replaceText(
50 node,
51 getReflectApplyCall(sourceCode, node.arguments[0], node.arguments[1], node.arguments[2])
52 )
53 );
54 }
55};
56
57const create = context => {
58 return {
59 CallExpression: node => {
60 if (
61 !(
62 node.callee.type === 'MemberExpression' &&
63 !['Literal', 'ArrayExpression', 'ObjectExpression'].includes(node.callee.object.type)
64 )
65 ) {
66 return;
67 }
68
69 const sourceCode = context.getSourceCode();
70 const fix = fixDirectApplyCall(node, sourceCode) || fixFunctionPrototypeCall(node, sourceCode);
71 if (fix) {
72 context.report({
73 node,
74 message: 'Prefer `Reflect.apply()` over `Function#apply()`.',
75 fix
76 });
77 }
78 }
79 };
80};
81
82module.exports = {
83 create,
84 meta: {
85 type: 'suggestion',
86 docs: {
87 url: getDocumentationUrl(__filename)
88 },
89 fixable: 'code'
90 }
91};