UNPKG

2.51 kBJavaScriptView Raw
1'use strict';
2const getDocumentationUrl = require('./utils/get-documentation-url');
3const isShadowed = require('./utils/is-shadowed');
4const renameIdentifier = require('./utils/rename-identifier');
5
6const METHOD_ERROR_MESSAGE_ID = 'method-error';
7const METHOD_SUGGESTION_MESSAGE_ID = 'method-suggestion';
8const PROPERTY_ERROR_MESSAGE_ID = 'property-error';
9
10const methods = {
11 // Safe
12 parseInt: true,
13 parseFloat: true,
14 // Unsafe
15 isNaN: false,
16 isFinite: false
17};
18
19const methodsSelector = [
20 'CallExpression',
21 '>',
22 'Identifier.callee',
23 `:matches(${Object.keys(methods).map(name => `[name="${name}"]`).join(', ')})`
24].join('');
25
26const propertiesSelector = [
27 'Identifier',
28 '[name="NaN"]',
29 `:not(${
30 [
31 'MemberExpression[computed=false] > Identifier.property',
32 'FunctionDeclaration > Identifier.id',
33 'ClassDeclaration > Identifier.id',
34 'MethodDefinition > Identifier.key',
35 'VariableDeclarator > Identifier.id',
36 'Property[shorthand=false] > Identifier.key',
37 'TSDeclareFunction > Identifier.id',
38 'TSEnumMember > Identifier.id',
39 'TSPropertySignature > Identifier.key'
40 ].join(', ')
41 })`
42].join('');
43
44const create = context => {
45 const sourceCode = context.getSourceCode();
46
47 return {
48 [methodsSelector]: node => {
49 if (isShadowed(context.getScope(), node)) {
50 return;
51 }
52
53 const {name} = node;
54 const isSafe = methods[name];
55
56 const problem = {
57 node,
58 messageId: METHOD_ERROR_MESSAGE_ID,
59 data: {
60 name
61 }
62 };
63
64 const fix = fixer => renameIdentifier(node, `Number.${name}`, fixer, sourceCode);
65
66 if (isSafe) {
67 problem.fix = fix;
68 } else {
69 problem.suggest = [
70 {
71 messageId: METHOD_SUGGESTION_MESSAGE_ID,
72 data: {
73 name
74 },
75 fix
76 }
77 ];
78 }
79
80 context.report(problem);
81 },
82 [propertiesSelector]: node => {
83 if (isShadowed(context.getScope(), node)) {
84 return;
85 }
86
87 const {name} = node;
88 context.report({
89 node,
90 messageId: PROPERTY_ERROR_MESSAGE_ID,
91 data: {
92 name
93 },
94 fix: fixer => renameIdentifier(node, `Number.${name}`, fixer, sourceCode)
95 });
96 }
97 };
98};
99
100module.exports = {
101 create,
102 meta: {
103 type: 'suggestion',
104 docs: {
105 url: getDocumentationUrl(__filename)
106 },
107 fixable: 'code',
108 messages: {
109 [METHOD_ERROR_MESSAGE_ID]: 'Prefer `Number.{{name}}()` over `{{name}}()`.',
110 [METHOD_SUGGESTION_MESSAGE_ID]: 'Replace `{{name}}()` with `Number.{{name}}()`.',
111 [PROPERTY_ERROR_MESSAGE_ID]: 'Prefer `Number.{{name}}` over `{{name}}`.'
112 }
113 }
114};