Skip to content

Commit 880856e

Browse files
authored
ESLint - Require capture and custom message (#3220)
* added require capture to eslint no direct import rule * fixed autofix * removed extra import * added custom message option * added a more complex require example * change imp to use the utils * removed autofix change * fixed identation * combined implemetation
1 parent cc8ad20 commit 880856e

File tree

2 files changed

+98
-18
lines changed

2 files changed

+98
-18
lines changed

eslint-rules/lib/rules/no-direct-import.js

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const {handleError} = require('../utils');
1+
const {handleError, addToImports} = require('../utils');
22

33
const RULE_ID = 'no-direct-import';
44
const MAP_SCHEMA = {
@@ -50,19 +50,29 @@ module.exports = {
5050
schema: [MAP_SCHEMA]
5151
},
5252
create(context) {
53-
function reportDirectImport(node, rule) {
53+
function getErrorMessage(rule, type) {
54+
const {origin, destination, applyAutofix, customMessage} = rule;
55+
const autofixMessage = applyAutofix ? ' (autofix available)' : '';
56+
return customMessage || `Do not ${type} directly from '${origin}'. Please use '${destination}'${autofixMessage}.`;
57+
}
58+
59+
function checkAndReport(node, type, importedModuleNameToReplace) {
60+
const imports = [];
61+
addToImports(node, imports);
62+
const modules = new Set(collectModulesFromImports(imports));
63+
const rule = getRules().find((rule) => modules.has(rule.origin));
64+
if (!rule) {
65+
return;
66+
}
5467
try {
55-
const origin = rule.origin;
56-
const destination = rule.destination;
57-
const applyAutofix = rule.applyAutofix;
58-
const autofixMessage = applyAutofix ? ' (autofix available)' : '';
59-
const message = `Do not import directly from '${origin}'. Please use '${destination}'${autofixMessage}.`;
68+
const {applyAutofix, destination} = rule;
69+
const message = getErrorMessage(rule, type);
6070
context.report({
6171
node,
6272
message,
6373
fix(fixer) {
6474
if (node && applyAutofix && destination) {
65-
return fixer.replaceText(node.source, `'${destination}'`);
75+
return fixer.replaceText(importedModuleNameToReplace, `'${destination}'`);
6676
}
6777
}
6878
});
@@ -76,17 +86,25 @@ module.exports = {
7686
return context.options[0].rules || [context.options[0]];
7787
}
7888

79-
function checkImportDeclaration(node) {
80-
const source = node.source.value;
81-
const rule = getRules().find((rule) => rule.origin === source);
82-
83-
if (rule) {
84-
reportDirectImport(node, rule);
85-
}
89+
function collectModulesFromImports(imports) {
90+
const collection = [];
91+
imports.forEach((moduleImports) => {
92+
collection.push(...Object.keys(moduleImports));
93+
});
94+
return collection;
95+
}
96+
97+
function getModuleNameFromRequire(node) {
98+
return (node.init.object ? node.init.object.arguments : node.init.arguments)[0]
99+
}
100+
101+
function getModuleNameFromImport(node) {
102+
return node.source;
86103
}
87104

88105
return {
89-
ImportDeclaration: checkImportDeclaration
106+
ImportDeclaration: (node) => checkAndReport(node, 'import', getModuleNameFromImport(node)),
107+
VariableDeclarator: (node) => checkAndReport(node, 'require', getModuleNameFromRequire(node)),
90108
};
91109
}
92110
};

eslint-rules/tests/lib/rules/no-direct-import.js

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ const ruleOptionsArray = [
1414
}
1515
];
1616

17+
customErrorMessage = 'This is a custom message';
18+
const ruleWithCustomMessage = [
19+
{origin: 'some-module', destination: 'another-module', applyAutofix: true, customMessage: customErrorMessage}
20+
]
21+
1722
RuleTester.setDefaultConfig({
1823
parser: 'babel-eslint',
1924
parserOptions: {ecmaVersion: 6, ecmaFeatures: {jsx: true}}
@@ -23,26 +28,45 @@ const ruleTester = new RuleTester();
2328

2429
const validExample1 = `import {Component} from 'another-module';`;
2530
const validExample2 = `import {Component} from 'new-module';`;
31+
const validExample3 = `const {Component} = require('another-module');`;
32+
const validExample4 = `const test = require('new-module').test;`;
2633

2734
const invalidExample1 = `import {Component} from 'some-module';`;
2835
const invalidExample2 = `import {Component} from 'old-module';`;
36+
const invalidExample3 = `const {Component} = require('some-module');`;
37+
const invalidExample4 = `const {Component} = require('old-module');`;
38+
const invalidExample5 = `const test = require(\'some-module\').test;`;
2939

3040
const error1 = `Do not import directly from 'some-module'. Please use 'another-module' (autofix available).`;
3141
const error2 = `Do not import directly from 'old-module'. Please use 'new-module' (autofix available).`;
42+
const requireError1 = `Do not require directly from 'some-module'. Please use 'another-module' (autofix available).`;
43+
const requireError2 = `Do not require directly from 'old-module'. Please use 'new-module' (autofix available).`;
3244

3345
ruleTester.run('no-direct-import', rule, {
3446
valid: [
3547
{
3648
options: ruleOptions,
37-
code: validExample1
49+
code: validExample1
50+
},
51+
{
52+
options: ruleOptions,
53+
code: validExample3
3854
},
3955
{
4056
options: ruleOptionsArray,
4157
code: validExample1
4258
},
4359
{
4460
options: ruleOptionsArray,
45-
code: validExample2
61+
code: validExample2
62+
},
63+
{
64+
options: ruleOptionsArray,
65+
code: validExample3
66+
},
67+
{
68+
options: ruleOptionsArray,
69+
code: validExample4
4670
}
4771
],
4872
invalid: [
@@ -69,6 +93,44 @@ ruleTester.run('no-direct-import', rule, {
6993
errors: [
7094
{message: error2}
7195
]
96+
},
97+
{
98+
options: ruleOptions,
99+
code: invalidExample3,
100+
output: `const {Component} = require('another-module');`,
101+
errors: [
102+
{message: requireError1}
103+
]
104+
},
105+
{
106+
options: ruleOptionsArray,
107+
code: invalidExample4,
108+
output: `const {Component} = require('new-module');`,
109+
errors: [
110+
{message: requireError2}
111+
]
112+
},
113+
{
114+
options: ruleWithCustomMessage,
115+
code: invalidExample1,
116+
errors: [
117+
{message: customErrorMessage}
118+
]
119+
},
120+
{
121+
options: ruleWithCustomMessage,
122+
code: invalidExample3,
123+
errors: [
124+
{message: customErrorMessage}
125+
]
126+
},
127+
{
128+
options: ruleOptions,
129+
code: invalidExample5,
130+
output: 'const test = require(\'another-module\').test;',
131+
errors: [
132+
{message: requireError1}
133+
]
72134
}
73135
]
74136
});

0 commit comments

Comments
 (0)