Skip to content

Commit

Permalink
[fix] order: Fix import ordering in TypeScript module declarations
Browse files Browse the repository at this point in the history
Without this, `import/order` checks if all imports in a file are sorted. The
autofix would then move all imports to the type of the file, breaking TypeScript
module declarations.

Closes import-js#2217
  • Loading branch information
remcohaszing committed Sep 12, 2021
1 parent 7784948 commit 297a4d1
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 17 deletions.
49 changes: 32 additions & 17 deletions src/rules/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ function registerNode(context, importEntry, ranks, imported, excludedImportTypes
}
}

function isModuleLevelRequire(node) {
function getRequireBlock(node) {
let n = node;
// Handle cases like `const baz = require('foo').bar.baz`
// and `const foo = require('foo')()`
Expand All @@ -346,11 +346,13 @@ function isModuleLevelRequire(node) {
) {
n = n.parent;
}
return (
if (
n.parent.type === 'VariableDeclarator' &&
n.parent.parent.type === 'VariableDeclaration' &&
n.parent.parent.parent.type === 'Program'
);
) {
return n.parent.parent.parent;
}
}

const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object', 'type'];
Expand Down Expand Up @@ -605,7 +607,14 @@ module.exports = {
},
};
}
let imported = [];
const importMap = new Map();

function getBlockImports(node) {
if (!importMap.has(node)) {
importMap.set(node, []);
}
return importMap.get(node);
}

return {
ImportDeclaration: function handleImports(node) {
Expand All @@ -621,7 +630,7 @@ module.exports = {
type: 'import',
},
ranks,
imported,
getBlockImports(node.parent),
pathGroupsExcludedImportTypes
);
}
Expand Down Expand Up @@ -652,12 +661,16 @@ module.exports = {
type,
},
ranks,
imported,
getBlockImports(node.parent),
pathGroupsExcludedImportTypes
);
},
CallExpression: function handleRequires(node) {
if (!isStaticRequire(node) || !isModuleLevelRequire(node)) {
if (!isStaticRequire(node)) {
return;
}
const block = getRequireBlock(node);
if (!block) {
return;
}
const name = node.arguments[0].value;
Expand All @@ -670,22 +683,24 @@ module.exports = {
type: 'require',
},
ranks,
imported,
getBlockImports(block),
pathGroupsExcludedImportTypes
);
},
'Program:exit': function reportAndReset() {
if (newlinesBetweenImports !== 'ignore') {
makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
}
'Program:exit': function reportAndReset(node) {
for (const imported of importMap.values()) {

if (alphabetize.order !== 'ignore') {
mutateRanksToAlphabetize(imported, alphabetize);
}
if (newlinesBetweenImports !== 'ignore') {
makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
}

makeOutOfOrderReport(context, imported);
if (alphabetize.order !== 'ignore') {
mutateRanksToAlphabetize(imported, alphabetize);
}

imported = [];
makeOutOfOrderReport(context, imported);
}
importMap.clear();
},
};
},
Expand Down
50 changes: 50 additions & 0 deletions tests/src/rules/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -2462,6 +2462,24 @@ context('TypeScript', function () {
},
],
}),
// Imports inside module declaration
test({
code: `
import type { CopyOptions } from 'fs';
import type { ParsedPath } from 'path';
declare module 'my-module' {
import type { CopyOptions } from 'fs';
import type { ParsedPath } from 'path';
}
`,
...parserConfig,
options: [
{
alphabetize: { order: 'asc' },
},
],
}),
],
invalid: [
// Option alphabetize: {order: 'asc'}
Expand Down Expand Up @@ -2655,6 +2673,38 @@ context('TypeScript', function () {
}],
options: [{ warnOnUnassignedImports: true }],
}),
// Imports inside module declaration
test({
code: `
import type { ParsedPath } from 'path';
import type { CopyOptions } from 'fs';
declare module 'my-module' {
import type { ParsedPath } from 'path';
import type { CopyOptions } from 'fs';
}
`,
output: `
import type { CopyOptions } from 'fs';
import type { ParsedPath } from 'path';
declare module 'my-module' {
import type { CopyOptions } from 'fs';
import type { ParsedPath } from 'path';
}
`,
errors: [{
message: '`fs` import should occur before import of `path`',
},{
message: '`fs` import should occur before import of `path`',
}],
...parserConfig,
options: [
{
alphabetize: { order: 'asc' },
},
],
}),
],
});
});
Expand Down

0 comments on commit 297a4d1

Please sign in to comment.