Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduces importOrderBuiltinModulesToTop for Node Builtins #71 #150

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,16 @@ with options as a JSON string of the plugin array:
importOrderParserPlugins: []
```


#### `importOrderBuiltinModulesToTop`

**type**: `boolean`

**default value:** `false`

A boolean value to enable sorting of builtins to the top of all import groups.


### How does import sort work ?

The plugin extracts the imports which are defined in `importOrder`. These imports are considered as _local imports_.
Expand Down
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ParserPlugin } from '@babel/parser';
import { expressionStatement, stringLiteral } from '@babel/types';
import { builtinModules } from 'module';

export const flow: ParserPlugin = 'flow';
export const typescript: ParserPlugin = 'typescript';
Expand All @@ -12,6 +13,7 @@ export const newLineCharacters = '\n\n';
* where the not matched imports should be placed
*/
export const THIRD_PARTY_MODULES_SPECIAL_WORD = '<THIRD_PARTY_MODULES>';
export const BUILTIN_MODULES = builtinModules.join('|');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a bit of warning, this regex needs to be a bit more strict, see IanVS/prettier-plugin-sort-imports#17 for the implementation in a fork.


const PRETTIER_PLUGIN_SORT_IMPORTS_NEW_LINE =
'PRETTIER_PLUGIN_SORT_IMPORTS_NEW_LINE';
Expand Down
2 changes: 2 additions & 0 deletions src/preprocessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function preprocessor(code: string, options: PrettierOptions) {
importOrderSeparation,
importOrderGroupNamespaceSpecifiers,
importOrderSortSpecifiers,
importOrderBuiltinModulesToTop,
} = options;

const importNodes: ImportDeclaration[] = [];
Expand Down Expand Up @@ -46,6 +47,7 @@ export function preprocessor(code: string, options: PrettierOptions) {
importOrderSeparation,
importOrderGroupNamespaceSpecifiers,
importOrderSortSpecifiers,
importOrderBuiltinModulesToTop,
});

return getCodeFromAst(allImports, code, interpreter);
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { RequiredOptions } from 'prettier';
export interface PrettierOptions extends RequiredOptions {
importOrder: string[];
importOrderCaseInsensitive: boolean;
importOrderBuiltinModulesToTop: boolean;
// should be of type ParserPlugin from '@babel/parser' but prettier does not support nested arrays in options
importOrderParserPlugins: string[];
importOrderSeparation: boolean;
Expand All @@ -19,6 +20,7 @@ export type GetSortedNodes = (
options: Pick<
PrettierOptions,
| 'importOrder'
| 'importOrderBuiltinModulesToTop'
| 'importOrderCaseInsensitive'
| 'importOrderSeparation'
| 'importOrderGroupNamespaceSpecifiers'
Expand Down
1 change: 1 addition & 0 deletions src/utils/__tests__/get-all-comments-from-nodes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const getSortedImportNodes = (code: string, options?: ParserOptions) => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
});
};

Expand Down
1 change: 1 addition & 0 deletions src/utils/__tests__/get-code-from-ast.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import a from 'a';
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
});
const formatted = getCodeFromAst(sortedNodes, code, null);
expect(format(formatted, { parser: 'babel' })).toEqual(
Expand Down
2 changes: 0 additions & 2 deletions src/utils/__tests__/get-import-nodes-matched-group.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { THIRD_PARTY_MODULES_SPECIAL_WORD } from '../../constants';
import { ImportGroups } from '../../types';
import { getImportNodes } from '../get-import-nodes';
import { getImportNodesMatchedGroup } from '../get-import-nodes-matched-group';

Expand Down
50 changes: 50 additions & 0 deletions src/utils/__tests__/get-sorted-nodes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { tC, tA, tB } from 't';
import k, { kE, kB } from 'k';
import * as a from 'a';
import * as x from 'x';
import path from 'path';
import BY from 'BY';
import Ba from 'Ba';
import XY from 'XY';
Expand All @@ -28,6 +29,7 @@ test('it returns all sorted nodes', () => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];

expect(getSortedNodesNames(sorted)).toEqual([
Expand All @@ -39,6 +41,7 @@ test('it returns all sorted nodes', () => {
'c',
'g',
'k',
'path',
't',
'x',
'z',
Expand All @@ -58,6 +61,7 @@ test('it returns all sorted nodes', () => {
['c', 'cD'],
['g'],
['k', 'kE', 'kB'],
['path'],
['tC', 'tA', 'tB'],
['x'],
['z'],
Expand All @@ -72,6 +76,7 @@ test('it returns all sorted nodes case-insensitive', () => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];

expect(getSortedNodesNames(sorted)).toEqual([
Expand All @@ -81,6 +86,7 @@ test('it returns all sorted nodes case-insensitive', () => {
'c',
'g',
'k',
'path',
't',
'x',
'Xa',
Expand All @@ -100,6 +106,7 @@ test('it returns all sorted nodes case-insensitive', () => {
['c', 'cD'],
['g'],
['k', 'kE', 'kB'],
['path'],
['tC', 'tA', 'tB'],
['x'],
['Xa'],
Expand All @@ -116,13 +123,15 @@ test('it returns all sorted nodes with sort order', () => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];

expect(getSortedNodesNames(sorted)).toEqual([
'XY',
'Xa',
'c',
'g',
'path',
'x',
'z',
'a',
Expand All @@ -142,6 +151,7 @@ test('it returns all sorted nodes with sort order', () => {
['Xa'],
['c', 'cD'],
['g'],
['path'],
['x'],
['z'],
['a'],
Expand All @@ -160,10 +170,12 @@ test('it returns all sorted nodes with sort order case-insensitive', () => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];
expect(getSortedNodesNames(sorted)).toEqual([
'c',
'g',
'path',
'x',
'Xa',
'XY',
Expand All @@ -183,6 +195,7 @@ test('it returns all sorted nodes with sort order case-insensitive', () => {
).toEqual([
['c', 'cD'],
['g'],
['path'],
['x'],
['Xa'],
['XY'],
Expand All @@ -203,12 +216,14 @@ test('it returns all sorted import nodes with sorted import specifiers', () => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: true,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];
expect(getSortedNodesNames(sorted)).toEqual([
'XY',
'Xa',
'c',
'g',
'path',
'x',
'z',
'a',
Expand All @@ -228,6 +243,7 @@ test('it returns all sorted import nodes with sorted import specifiers', () => {
['Xa'],
['c', 'cD'],
['g'],
['path'],
['x'],
['z'],
['a'],
Expand All @@ -246,10 +262,12 @@ test('it returns all sorted import nodes with sorted import specifiers with case
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: true,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];
expect(getSortedNodesNames(sorted)).toEqual([
'c',
'g',
'path',
'x',
'Xa',
'XY',
Expand All @@ -269,6 +287,7 @@ test('it returns all sorted import nodes with sorted import specifiers with case
).toEqual([
['c', 'cD'],
['g'],
['path'],
['x'],
['Xa'],
['XY'],
Expand All @@ -289,13 +308,15 @@ test('it returns all sorted nodes with custom third party modules', () => {
importOrderCaseInsensitive: true,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];
expect(getSortedNodesNames(sorted)).toEqual([
'a',
'Ba',
'BY',
'c',
'g',
'path',
'x',
'Xa',
'XY',
Expand All @@ -313,6 +334,7 @@ test('it returns all sorted nodes with namespace specifiers at the top', () => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: true,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
}) as ImportDeclaration[];

expect(getSortedNodesNames(sorted)).toEqual([
Expand All @@ -325,7 +347,35 @@ test('it returns all sorted nodes with namespace specifiers at the top', () => {
'c',
'g',
'k',
'path',
't',
'z',
]);
});

test('it returns all sorted nodes with builtin specifiers at the top, ', () => {
const result = getImportNodes(code);
const sorted = getSortedNodes(result, {
importOrder: [],
importOrderCaseInsensitive: false,
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: true,
}) as ImportDeclaration[];

expect(getSortedNodesNames(sorted)).toEqual([
'path',
'BY',
'Ba',
'XY',
'Xa',
'a',
'c',
'g',
'k',
't',
'x',
'z',
]);
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ test('it should remove nodes from the original code', () => {
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderBuiltinModulesToTop: false,
});
const allCommentsFromImports = getAllCommentsFromNodes(sortedNodes);

Expand Down
11 changes: 10 additions & 1 deletion src/utils/get-sorted-nodes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { addComments, removeComments } from '@babel/types';
import { clone, isEqual } from 'lodash';

import { THIRD_PARTY_MODULES_SPECIAL_WORD, newLineNode } from '../constants';
import {
BUILTIN_MODULES,
THIRD_PARTY_MODULES_SPECIAL_WORD,
newLineNode,
} from '../constants';
import { naturalSort } from '../natural-sort';
import { GetSortedNodes, ImportGroups, ImportOrLine } from '../types';
import { getImportNodesMatchedGroup } from './get-import-nodes-matched-group';
Expand All @@ -22,6 +26,7 @@ export const getSortedNodes: GetSortedNodes = (nodes, options) => {
importOrderSeparation,
importOrderSortSpecifiers,
importOrderGroupNamespaceSpecifiers,
importOrderBuiltinModulesToTop,
} = options;

const originalNodes = nodes.map(clone);
Expand All @@ -31,6 +36,10 @@ export const getSortedNodes: GetSortedNodes = (nodes, options) => {
importOrder = [THIRD_PARTY_MODULES_SPECIAL_WORD, ...importOrder];
}

if (importOrderBuiltinModulesToTop) {
importOrder = [BUILTIN_MODULES, ...importOrder];
}

const importOrderGroups = importOrder.reduce<ImportGroups>(
(groups, regexp) => ({
...groups,
Expand Down