Skip to content

Commit

Permalink
deprecated named imports
Browse files Browse the repository at this point in the history
  • Loading branch information
k.stoyanov committed Jul 3, 2023
1 parent 2555364 commit 1265610
Show file tree
Hide file tree
Showing 5 changed files with 3,816 additions and 16 deletions.
11 changes: 11 additions & 0 deletions docs/rules/import.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Let's consider we have this configuration in `.eslintrc`:
"rules": {
"deprecate/import": ["error",
{"name": "path/to/legacyModule", "use": "newModule"},
{"name": "a", "module": "path/to/legacyModule", "use": "newModule"},
{"nameRegExp": "\\.sss", "use": "css imports"},
]
}
Expand All @@ -26,10 +27,13 @@ Let's consider we have this configuration in `.eslintrc`:
import a from 'path/to/legacyModule'
import a from '../../path/to/legacyModule'
import a from 'legacyModule'
import { a } from 'path/to/legacyModule'

const a = require('path/to/legacyModule');
const a = require('../../path/to/legacyModule');
const a = require('legacyModule');
const { a } = require('legacyModule');
const a = require('legacyModule').a;

import style from 'style.sss'
```
Expand All @@ -49,6 +53,13 @@ you can pass objects instead of just modules names:
{"name": "<import name>", "use": "<suggested alternative>"}, ... ]
```

You can control named imports from some module:

```js
"deprecate/import": [ 2,
{"name": "<named import>", "module": "<name of module>", "use": "<suggested alternative>"}, ... ]
```

or use `nameRegExp`:

```js
Expand Down
14 changes: 12 additions & 2 deletions lib/ImportChecker.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ class ImportChecker {
this.name = option;
this.use = null;
this.nameRegExp = null;
this.module = null;
} else {
this.name = option.name || null;
this.nameRegExp = option.nameRegExp || null;
this.use = option.use || null;
this.module = option.module || null;
}

this.regExp = this.nameRegExp ? new RegExp(this.nameRegExp) : null;
Expand All @@ -17,16 +19,24 @@ class ImportChecker {
}
}

check(importPath) {
check(importPath, importModules) {
if (this.module && importModules && importModules.size) {
return importPath === this.module && importModules.has(this.name);
}
if (this.name) {
return importPath === this.name;
} else if (this.regExp) {
}
if (this.regExp) {
return Boolean(importPath.match(this.regExp));
}
throw new Error('You should provide "name" or "nameRegExp" as an option to plugin');
}

getErrMessage() {
if (this.module && this.use && this.name) {
const errorMsg = `${this.name} from ${this.module} is deprecated. Use ${this.use} instead.`;
return errorMsg;
}
if (this.name) {
let errorMsg = `Module ${this.name} is deprecated.`;
if (this.use) {
Expand Down
45 changes: 42 additions & 3 deletions lib/rules/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ module.exports = {
return {
ImportDeclaration(node) {
const importPath = node.source.value;

const importedModules = node.specifiers.length
? node.specifiers
.filter((childNode) => !!childNode.imported)
.map((childNode) => childNode.imported.name)
: [];
imports
.filter((imp) => imp.check(importPath))
.filter((imp) => imp.check(importPath, new Set(importedModules)))
.forEach((imp) => {
context.report({ node, message: imp.getErrMessage() });
});
Expand All @@ -31,7 +35,42 @@ module.exports = {
.forEach((imp) => {
context.report({ node, message: imp.getErrMessage() });
});
}
},
MemberExpression(node) {
if ((node.object.callee.name !== 'require' || !node.object.arguments.length) && !node.property) {
return;
}
const requireArg = node.object.arguments[0];
if (requireArg.type !== 'Literal') {
return;
}
imports
.filter((imp) => imp.check(requireArg.value, new Set([node.property.name])))
.forEach((imp) => {
context.report({ node, message: imp.getErrMessage() });
});
},
VariableDeclaration(node) {
if (!(node.declarations && node.declarations.length)) return;

const childNode = node.declarations[0];
if (!(childNode.id && childNode.id.type === 'ObjectPattern' && childNode.init)) return;

const requireArg = childNode.init.arguments[0];
if (requireArg.type !== 'Literal' || childNode.init.callee.name !== 'require') {
return;
}

const namedImports = childNode.id.properties
.filter((module) => !!module.value.name)
.map((module) => module.value.name);

imports
.filter((imp) => imp.check(requireArg.value, new Set(namedImports)))
.forEach((imp) => {
context.report({ node, message: imp.getErrMessage() });
});
},
};
}
};
Loading

0 comments on commit 1265610

Please sign in to comment.