Skip to content

Commit 18637ed

Browse files
authored
Clean up options & remove explicit function types (#239)
This is a bit of a cleanup PR, and does two main things: - Removes function types from `src/types.ts`, and defines the types directly on the functions themselves. This was a holdover from before the conversion of the project to typescript, when we had to have a separate types file, but it's backwards from how types are normally defined. It's clearer and more typesafe to define the types directly on the functions, which this PR does now. - Improves the options that we present to prettier (for it to show in `prettier --help`, supposedly, though I'm not sure whether that actually works or not). Note: this doesn't have any impact on the types that we expose to users (which is manually maintained in `types/index.d.ts`
1 parent cdb13e5 commit 18637ed

15 files changed

Lines changed: 113 additions & 129 deletions

src/index.ts

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,35 @@
1-
import type { RequiredOptions as PrettierRequiredOptions } from 'prettier';
1+
import type {
2+
BooleanSupportOption,
3+
StringArraySupportOption,
4+
StringSupportOption,
5+
} from 'prettier';
26
import { parsers as babelParsers } from 'prettier/parser-babel';
37
import { parsers as flowParsers } from 'prettier/parser-flow';
48
import { parsers as htmlParsers } from 'prettier/parser-html';
59
import { parsers as typescriptParsers } from 'prettier/parser-typescript';
610

11+
import { PluginConfig } from '../types';
712
import { DEFAULT_IMPORT_ORDER } from './constants';
813
import { defaultPreprocessor } from './preprocessors/default';
914
import { emberPreprocessor } from './preprocessors/ember';
1015
import { vuePreprocessor } from './preprocessors/vue';
11-
import type { PrettierOptions } from './types';
1216

13-
// Not sure what the type from Prettier should be, but this is a good enough start.
14-
interface PrettierOptionSchema {
15-
type: string;
16-
category: 'Global';
17-
array?: boolean;
18-
default: unknown;
19-
description: string;
20-
}
21-
22-
export const options: Record<
23-
Exclude<keyof PrettierOptions, keyof PrettierRequiredOptions>,
24-
PrettierOptionSchema
25-
> = {
17+
export const options = {
2618
importOrder: {
27-
type: 'path',
19+
type: 'string',
2820
category: 'Global',
2921
array: true,
3022
default: [{ value: DEFAULT_IMPORT_ORDER }],
31-
description:
32-
'Provide an order to sort imports. [node.js built-ins are always first]',
23+
description: 'An array of regex strings for the import sort order.',
3324
},
3425
importOrderParserPlugins: {
35-
type: 'path',
26+
type: 'string',
3627
category: 'Global',
3728
array: true,
3829
// By default, we add ts and jsx as parsers but if users define something
3930
// we take that option
4031
default: [{ value: ['typescript', 'jsx'] }],
41-
description: 'Provide a list of plugins for special syntax',
32+
description: 'A list of babel parser plugins for special syntax.',
4233
},
4334
importOrderTypeScriptVersion: {
4435
type: 'string',
@@ -51,9 +42,13 @@ export const options: Record<
5142
type: 'boolean',
5243
category: 'Global',
5344
default: false,
54-
description: 'Provide a case sensitivity boolean flag',
45+
description:
46+
'Should capitalization be considered when sorting imports?',
5547
},
56-
};
48+
} satisfies Record<
49+
keyof PluginConfig,
50+
StringArraySupportOption | BooleanSupportOption | StringSupportOption
51+
>;
5752

5853
const getEmberPlugin = () => {
5954
try {

src/types.ts

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { ParserPlugin } from '@babel/parser';
21
import {
32
type EmptyStatement,
43
type ExpressionStatement,
@@ -10,14 +9,8 @@ import {
109
import { RequiredOptions } from 'prettier';
1110

1211
import { PluginConfig } from '../types';
13-
import {
14-
chunkTypeOther,
15-
chunkTypeUnsortable,
16-
importFlavorIgnore,
17-
importFlavorSideEffect,
18-
importFlavorType,
19-
importFlavorValue,
20-
} from './constants';
12+
import { chunkTypeOther, chunkTypeUnsortable } from './constants';
13+
import { examineAndNormalizePluginOptions } from './utils/normalize-plugin-options';
2114

2215
export interface PrettierOptions
2316
extends Required<PluginConfig>,
@@ -34,12 +27,7 @@ export type NormalizableOptions = Pick<
3427
// filepath can be undefined when running prettier via the api on text input
3528
Pick<Partial<PrettierOptions>, 'filepath'>;
3629

37-
export type ChunkType = typeof chunkTypeOther | typeof chunkTypeUnsortable;
38-
export type FlavorType =
39-
| typeof importFlavorIgnore
40-
| typeof importFlavorSideEffect
41-
| typeof importFlavorType
42-
| typeof importFlavorValue;
30+
type ChunkType = typeof chunkTypeOther | typeof chunkTypeUnsortable;
4331

4432
export interface ImportChunk {
4533
nodes: ImportDeclaration[];
@@ -63,43 +51,9 @@ export type ImportRelated = ImportOrLine | SomeSpecifier;
6351
* - behavior flags are derived from the base options
6452
* - plugins is dynamically modified by filepath
6553
*/
66-
export interface ExtendedOptions {
67-
importOrder: PrettierOptions['importOrder'];
68-
importOrderCombineTypeAndValueImports: boolean;
69-
importOrderCaseSensitive: boolean;
70-
hasAnyCustomGroupSeparatorsInImportOrder: boolean;
71-
provideGapAfterTopOfFileComments: boolean;
72-
plugins: ParserPlugin[];
73-
}
74-
75-
export type GetSortedNodes = (
76-
nodes: ImportDeclaration[],
77-
options: Pick<ExtendedOptions, 'importOrder'> & {
78-
importOrderCombineTypeAndValueImports: boolean;
79-
hasAnyCustomGroupSeparatorsInImportOrder?: boolean;
80-
provideGapAfterTopOfFileComments?: boolean;
81-
},
82-
) => ImportOrLine[];
83-
84-
export type GetSortedNodesByImportOrder = (
85-
nodes: ImportDeclaration[],
86-
options: Pick<ExtendedOptions, 'importOrder'> & {
87-
importOrderCaseSensitive?: boolean;
88-
},
89-
) => ImportOrLine[];
90-
91-
export type GetChunkTypeOfNode = (node: ImportDeclaration) => ChunkType;
92-
93-
export type GetImportFlavorOfNode = (node: ImportDeclaration) => FlavorType;
94-
95-
export type MergeNodesWithMatchingImportFlavors = (
96-
nodes: ImportDeclaration[],
97-
options: { importOrderCombineTypeAndValueImports: boolean },
98-
) => ImportDeclaration[];
99-
100-
export type ExplodeTypeAndValueSpecifiers = (
101-
nodes: ImportDeclaration[],
102-
) => ImportDeclaration[];
54+
export type ExtendedOptions = ReturnType<
55+
typeof examineAndNormalizePluginOptions
56+
>;
10357

10458
export interface CommentAttachmentOptions {
10559
provideGapAfterTopOfFileComments?: boolean;

src/utils/__tests__/get-all-comments-from-nodes.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ const getSortedImportNodes = (code: string, options?: ParserOptions) => {
1919
importOrder:
2020
testingOnly.normalizeImportOrderOption(DEFAULT_IMPORT_ORDER),
2121
importOrderCombineTypeAndValueImports: true,
22+
importOrderCaseSensitive: false,
23+
hasAnyCustomGroupSeparatorsInImportOrder: false,
24+
provideGapAfterTopOfFileComments: false,
2225
});
2326
};
2427

src/utils/__tests__/get-code-from-ast.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import a from 'a';
2222
const sortedNodes = getSortedNodes(importNodes, {
2323
importOrder: defaultImportOrder,
2424
importOrderCombineTypeAndValueImports: true,
25+
importOrderCaseSensitive: false,
26+
hasAnyCustomGroupSeparatorsInImportOrder: false,
27+
provideGapAfterTopOfFileComments: false,
2528
});
2629
const formatted = getCodeFromAst({
2730
nodesToOutput: sortedNodes,
@@ -54,6 +57,9 @@ import type {See} from 'c';
5457
const sortedNodes = getSortedNodes(importNodes, {
5558
importOrder: defaultImportOrder,
5659
importOrderCombineTypeAndValueImports: true,
60+
importOrderCaseSensitive: false,
61+
hasAnyCustomGroupSeparatorsInImportOrder: false,
62+
provideGapAfterTopOfFileComments: false,
5763
});
5864
const formatted = getCodeFromAst({
5965
nodesToOutput: sortedNodes,
@@ -83,6 +89,9 @@ import c from 'c' assert { type: 'json' };
8389
const sortedNodes = getSortedNodes(importNodes, {
8490
importOrder: defaultImportOrder,
8591
importOrderCombineTypeAndValueImports: true,
92+
importOrderCaseSensitive: false,
93+
hasAnyCustomGroupSeparatorsInImportOrder: false,
94+
provideGapAfterTopOfFileComments: false,
8695
});
8796
const formatted = getCodeFromAst({
8897
nodesToOutput: sortedNodes,

src/utils/__tests__/get-sorted-nodes-by-import-order.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ test('it returns all sorted nodes', () => {
3030
const result = getImportNodes(code);
3131
const sorted = getSortedNodesByImportOrder(result, {
3232
importOrder: testingOnly.normalizeImportOrderOption(['^[./]']),
33+
importOrderCaseSensitive: false,
3334
}) as ImportDeclaration[];
3435

3536
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([
@@ -84,6 +85,7 @@ test('it returns all sorted nodes with sort order', () => {
8485
'^B',
8586
'^[./]',
8687
]),
88+
importOrderCaseSensitive: false,
8789
}) as ImportDeclaration[];
8890
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([
8991
'node:fs/promises',
@@ -139,6 +141,7 @@ import {type B, A} from 'z';
139141
});
140142
const sorted = getSortedNodesByImportOrder(result, {
141143
importOrder: testingOnly.normalizeImportOrderOption(['^[./]']),
144+
importOrderCaseSensitive: false,
142145
}) as ImportDeclaration[];
143146
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual(['k', 't', 'z']);
144147
expect(
@@ -158,6 +161,7 @@ test('it returns all sorted nodes with builtin specifiers at the top', () => {
158161
const result = getImportNodes(code);
159162
const sorted = getSortedNodesByImportOrder(result, {
160163
importOrder: testingOnly.normalizeImportOrderOption(['^[./]']),
164+
importOrderCaseSensitive: false,
161165
}) as ImportDeclaration[];
162166

163167
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([
@@ -189,6 +193,7 @@ test('it returns all sorted nodes with custom third party modules and builtins a
189193
'^k$',
190194
'^[./]',
191195
]),
196+
importOrderCaseSensitive: false,
192197
}) as ImportDeclaration[];
193198
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([
194199
'node:fs/promises',
@@ -220,6 +225,7 @@ test('it returns all sorted nodes with custom separation', () => {
220225
'^k$',
221226
'^[./]',
222227
]),
228+
importOrderCaseSensitive: false,
223229
}) as ImportDeclaration[];
224230
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([
225231
'node:fs/promises',
@@ -254,6 +260,7 @@ test('it does not add multiple custom import separators', () => {
254260
'^k$',
255261
'^[./]',
256262
]),
263+
importOrderCaseSensitive: false,
257264
}) as ImportDeclaration[];
258265
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([
259266
'node:fs/promises',

src/utils/__tests__/get-sorted-nodes.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ test('it returns all sorted nodes, preserving the order side effect nodes', () =
3333
importOrder:
3434
testingOnly.normalizeImportOrderOption(DEFAULT_IMPORT_ORDER),
3535
importOrderCombineTypeAndValueImports: true,
36+
importOrderCaseSensitive: false,
37+
hasAnyCustomGroupSeparatorsInImportOrder: false,
38+
provideGapAfterTopOfFileComments: false,
3639
}) as ImportDeclaration[];
3740
expect(getSortedNodesNamesAndNewlines(sorted)).toEqual([
3841
'se3',

src/utils/__tests__/normalize-plugin-options.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
DEFAULT_IMPORT_ORDER,
77
THIRD_PARTY_MODULES_SPECIAL_WORD,
88
} from '../../constants';
9-
import { NormalizableOptions } from '../../types';
109
import {
1110
examineAndNormalizePluginOptions,
1211
testingOnly,
@@ -99,7 +98,7 @@ describe('examineAndNormalizePluginOptions', () => {
9998
importOrderCaseSensitive: false,
10099
importOrderTypeScriptVersion: '1.0.0',
101100
filepath: __filename,
102-
} as NormalizableOptions),
101+
}),
103102
).toEqual({
104103
hasAnyCustomGroupSeparatorsInImportOrder: false,
105104
importOrder: [
@@ -126,7 +125,7 @@ describe('examineAndNormalizePluginOptions', () => {
126125
importOrderCaseSensitive: false,
127126
importOrderTypeScriptVersion: '1.0.0',
128127
filepath: __filename,
129-
} as NormalizableOptions),
128+
}),
130129
).toEqual({
131130
hasAnyCustomGroupSeparatorsInImportOrder: true,
132131
importOrder: [
@@ -149,7 +148,7 @@ describe('examineAndNormalizePluginOptions', () => {
149148
importOrderCaseSensitive: false,
150149
importOrderTypeScriptVersion: '1.0.0',
151150
filepath: __filename,
152-
} as NormalizableOptions),
151+
}),
153152
).toEqual({
154153
hasAnyCustomGroupSeparatorsInImportOrder: true,
155154
importOrder: [
@@ -169,8 +168,9 @@ describe('examineAndNormalizePluginOptions', () => {
169168
importOrder: DEFAULT_IMPORT_ORDER,
170169
importOrderParserPlugins: ['typescript'],
171170
importOrderTypeScriptVersion: '5.0.0',
171+
importOrderCaseSensitive: false,
172172
filepath: __filename,
173-
} as NormalizableOptions),
173+
}),
174174
).toEqual({
175175
hasAnyCustomGroupSeparatorsInImportOrder: false,
176176
importOrder: [
@@ -193,7 +193,7 @@ describe('examineAndNormalizePluginOptions', () => {
193193
importOrderTypeScriptVersion: '5.0.0',
194194
importOrderCaseSensitive: false,
195195
filepath: __filename,
196-
} as NormalizableOptions),
196+
}),
197197
).toEqual({
198198
hasAnyCustomGroupSeparatorsInImportOrder: false,
199199
importOrder: [
@@ -215,7 +215,7 @@ describe('examineAndNormalizePluginOptions', () => {
215215
importOrderCaseSensitive: false,
216216
importOrderTypeScriptVersion: '1.0.0',
217217
filepath: undefined,
218-
} as NormalizableOptions),
218+
}),
219219
).toEqual({
220220
hasAnyCustomGroupSeparatorsInImportOrder: false,
221221
importOrder: [
@@ -238,7 +238,7 @@ describe('examineAndNormalizePluginOptions', () => {
238238
importOrderCaseSensitive: false,
239239
importOrderTypeScriptVersion: '1.0.0',
240240
filepath: __filename,
241-
} as NormalizableOptions),
241+
}),
242242
).toEqual({
243243
hasAnyCustomGroupSeparatorsInImportOrder: false,
244244
importOrder: [],

src/utils/__tests__/remove-nodes-from-original-code.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ test('it should remove nodes from the original code', async () => {
2828
importOrder:
2929
testingOnly.normalizeImportOrderOption(DEFAULT_IMPORT_ORDER),
3030
importOrderCombineTypeAndValueImports: true,
31+
importOrderCaseSensitive: false,
32+
hasAnyCustomGroupSeparatorsInImportOrder: false,
33+
provideGapAfterTopOfFileComments: false,
3134
});
3235
const allCommentsFromImports = getAllCommentsFromNodes(sortedNodes);
3336

src/utils/explode-type-and-value-specifiers.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { importDeclaration, type ImportSpecifier } from '@babel/types';
2-
3-
import { ExplodeTypeAndValueSpecifiers } from '../types';
1+
import {
2+
importDeclaration,
3+
type ImportDeclaration,
4+
type ImportSpecifier,
5+
} from '@babel/types';
46

57
/**
68
* Breaks apart import declarations containing mixed type and value imports into separate declarations.
@@ -13,9 +15,7 @@ import { ExplodeTypeAndValueSpecifiers } from '../types';
1315
* + import type { Baz } from './source';
1416
* ```
1517
*/
16-
export const explodeTypeAndValueSpecifiers: ExplodeTypeAndValueSpecifiers = (
17-
nodes,
18-
) => {
18+
export const explodeTypeAndValueSpecifiers = (nodes: ImportDeclaration[]) => {
1919
const explodedNodes = [];
2020

2121
for (const node of nodes) {

src/utils/get-chunk-type-of-node.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { ImportDeclaration } from '@babel/types';
2+
13
import { chunkTypeOther, chunkTypeUnsortable } from '../constants';
2-
import type { GetChunkTypeOfNode } from '../types';
34
import { hasIgnoreNextNode } from './has-ignore-next-node';
45

56
/**
@@ -20,7 +21,7 @@ import { hasIgnoreNextNode } from './has-ignore-next-node';
2021
* @param node An import declaration node to classify.
2122
* @returns The type of the chunk into which the node should be put.
2223
*/
23-
export const getChunkTypeOfNode: GetChunkTypeOfNode = (node) => {
24+
export const getChunkTypeOfNode = (node: ImportDeclaration) => {
2425
const hasNoImportedSymbols = node.specifiers.length === 0;
2526
return hasIgnoreNextNode(node.leadingComments) || hasNoImportedSymbols
2627
? chunkTypeUnsortable

0 commit comments

Comments
 (0)