mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-15 14:05:47 -05:00
Fix accidental relative imports from non namespace barrels (#59544)
This commit is contained in:
81
scripts/eslint/rules/no-direct-import.cjs
Normal file
81
scripts/eslint/rules/no-direct-import.cjs
Normal file
@@ -0,0 +1,81 @@
|
||||
const { createRule } = require("./utils.cjs");
|
||||
const path = require("path");
|
||||
|
||||
/** @import { TSESTree } from "@typescript-eslint/utils" */
|
||||
void 0;
|
||||
|
||||
module.exports = createRule({
|
||||
name: "no-direct-import",
|
||||
meta: {
|
||||
docs: {
|
||||
description: ``,
|
||||
},
|
||||
messages: {
|
||||
noDirectImport: `This import relatively references another project; did you mean to import from a local _namespace module?`,
|
||||
},
|
||||
schema: [],
|
||||
type: "problem",
|
||||
},
|
||||
defaultOptions: [],
|
||||
|
||||
create(context) {
|
||||
const containingFileName = context.filename;
|
||||
const containingDirectory = path.dirname(containingFileName);
|
||||
|
||||
/** @type {(node: TSESTree.ImportDeclaration | TSESTree.TSImportEqualsDeclaration) => void} */
|
||||
const check = node => {
|
||||
let source;
|
||||
if (node.type === "TSImportEqualsDeclaration") {
|
||||
const moduleReference = node.moduleReference;
|
||||
if (
|
||||
moduleReference.type === "TSExternalModuleReference"
|
||||
&& moduleReference.expression.type === "Literal"
|
||||
&& typeof moduleReference.expression.value === "string"
|
||||
) {
|
||||
source = moduleReference.expression;
|
||||
}
|
||||
}
|
||||
else {
|
||||
source = node.source;
|
||||
}
|
||||
|
||||
if (!source) return;
|
||||
|
||||
const p = source.value;
|
||||
|
||||
// These appear in place of public API imports.
|
||||
if (p.endsWith("../typescript/typescript.js")) return;
|
||||
|
||||
// The below is similar to https://github.com/microsoft/DefinitelyTyped-tools/blob/main/packages/eslint-plugin/src/rules/no-bad-reference.ts
|
||||
|
||||
// Any relative path that goes to the wrong place will contain "..".
|
||||
if (!p.includes("..")) return;
|
||||
|
||||
const parts = p.split("/");
|
||||
let cwd = containingDirectory;
|
||||
for (const part of parts) {
|
||||
if (part === "" || part === ".") {
|
||||
continue;
|
||||
}
|
||||
if (part === "..") {
|
||||
cwd = path.dirname(cwd);
|
||||
}
|
||||
else {
|
||||
cwd = path.join(cwd, part);
|
||||
}
|
||||
|
||||
if (path.basename(cwd) === "src") {
|
||||
context.report({
|
||||
messageId: "noDirectImport",
|
||||
node: source,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
ImportDeclaration: check,
|
||||
TSImportEqualsDeclaration: check,
|
||||
};
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user