Use explicit extensions for imports within src (#58421)

This commit is contained in:
Jake Bailey
2024-05-06 17:07:54 -07:00
committed by GitHub
parent 9598d35074
commit 16beff101a
582 changed files with 2583 additions and 2360 deletions

View File

@@ -0,0 +1,70 @@
const { createRule } = require("./utils.cjs");
module.exports = createRule({
name: "js-extensions",
meta: {
docs: {
description: ``,
},
messages: {
missingJsExtension: `This relative module reference is missing a '.js' extension`,
},
schema: [],
type: "suggestion",
fixable: "code",
},
defaultOptions: [],
create(context) {
/** @type {(
* node:
* | import("@typescript-eslint/utils").TSESTree.ImportDeclaration
* | import("@typescript-eslint/utils").TSESTree.ExportAllDeclaration
* | import("@typescript-eslint/utils").TSESTree.ExportNamedDeclaration
* | import("@typescript-eslint/utils").TSESTree.TSImportEqualsDeclaration
* | import("@typescript-eslint/utils").TSESTree.TSModuleDeclaration
* ) => 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 if (node.type === "TSModuleDeclaration") {
if (node.kind === "module" && node.id.type === "Literal") {
source = node.id;
}
}
else {
source = node.source;
}
// This is not 100% accurate; this could point to a nested package, or to a directory
// containing an index.js file. But we don't have anything like that in our repo,
// so this check is good enough. Replicate this logic at your own risk.
if (source?.value.startsWith(".") && !/\.[cm]?js$/.test(source.value)) {
const quote = source.raw[0];
context.report({
messageId: "missingJsExtension",
node: source,
fix: fixer => fixer.replaceText(source, `${quote}${source.value}.js${quote}`),
});
}
};
return {
ImportDeclaration: check,
ExportAllDeclaration: check,
ExportNamedDeclaration: check,
TSImportEqualsDeclaration: check,
TSModuleDeclaration: check,
};
},
});

View File

@@ -0,0 +1,149 @@
const { RuleTester } = require("./support/RuleTester.cjs");
const rule = require("../rules/js-extensions.cjs");
const ruleTester = new RuleTester({
parserOptions: {
warnOnUnsupportedTypeScriptVersion: false,
},
parser: require.resolve("@typescript-eslint/parser"),
});
ruleTester.run("js-extensions", rule, {
valid: [
{
code: `
import "some-library";
import "./a.js";
import "./a.mjs";
import "./a.cjs";
import "../foo/a.js";
import "../foo/a.mjs";
import "../foo/a.cjs";
`,
},
{
code: `
import * as blah from "some-library";
import * as blah from "./a.js";
import * as blah from "./a.mjs";
import * as blah from "./a.cjs";
import * as blah from "../foo/a.js";
import * as blah from "../foo/a.mjs";
import * as blah from "../foo/a.cjs";
`,
},
{
code: `
export * from "some-library";
export * from "./a.js";
export * from "./a.mjs";
export * from "./a.cjs";
export * from "../foo/a.js";
export * from "../foo/a.mjs";
export * from "../foo/a.cjs";
`,
},
{
code: `
import blah = require("some-library");
import blah = require("./a.js");
import blah = require("./a.mjs");
import blah = require("./a.cjs");
import blah = require("../foo/a.js");
import blah = require("../foo/a.mjs");
import blah = require("../foo/a.cjs");
`,
},
],
invalid: [
{
code: `
import "./a";
import "../foo/a";
`,
errors: [
{
messageId: "missingJsExtension",
line: 2,
column: 8,
},
{
messageId: "missingJsExtension",
line: 3,
column: 8,
},
],
output: `
import "./a.js";
import "../foo/a.js";
`,
},
{
code: `
import * as blah from "./a";
import * as blah from "../foo/a";
`,
errors: [
{
messageId: "missingJsExtension",
line: 2,
column: 23,
},
{
messageId: "missingJsExtension",
line: 3,
column: 23,
},
],
output: `
import * as blah from "./a.js";
import * as blah from "../foo/a.js";
`,
},
{
code: `
export * from "./a";
export * from "../foo/a";
`,
errors: [
{
messageId: "missingJsExtension",
line: 2,
column: 15,
},
{
messageId: "missingJsExtension",
line: 3,
column: 15,
},
],
output: `
export * from "./a.js";
export * from "../foo/a.js";
`,
},
{
code: `
import blah = require("./a");
import blah = require("../foo/a");
`,
errors: [
{
messageId: "missingJsExtension",
line: 2,
column: 23,
},
{
messageId: "missingJsExtension",
line: 3,
column: 23,
},
],
output: `
import blah = require("./a.js");
import blah = require("../foo/a.js");
`,
},
],
});