UNPKG

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