ts-codemod-lib 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/functions/ast-transformers/convert-to-readonly.d.mts +19 -0
- package/dist/functions/ast-transformers/convert-to-readonly.d.mts.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.mjs +73 -0
- package/dist/functions/ast-transformers/convert-to-readonly.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/constants.d.mts +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/constants.d.mts.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/constants.mjs +3 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/constants.mjs.map +1 -1
- package/package.json +11 -11
- package/src/functions/ast-transformers/convert-to-readonly.mts +165 -0
- package/src/functions/ast-transformers/convert-to-readonly.test.mts +235 -0
- package/src/functions/ast-transformers/readonly-transformer-helpers/constants.mts +2 -0
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ Options:
|
|
|
75
75
|
|
|
76
76
|
- `ignorePrefixes`: Array of string prefixes for identifiers that should not be made readonly (default: `['mut_', '#mut_', '_mut_', 'draft']`)
|
|
77
77
|
- `DeepReadonly.typeName`: Custom name for the DeepReadonly type utility (default: `"DeepReadonly"`)
|
|
78
|
+
- `recordStyle`: Output style used when making `Record<K, V>` readonly (default: `"ReadonlyRecord"`). `"ReadonlyRecord"` uses the `ReadonlyRecord` type utility provided by `ts-type-forge` (no import statement is added, so it has to be available in the transformed code, e.g. globally via `ts-type-forge`'s `global.d.mts`), while `"Readonly<Record>"` uses only built-in utility types (`Readonly<Record<K, V>>`). Whichever style is selected, `Record<K, V>`, `Readonly<Record<K, V>>`, `ReadonlyRecord<K, V>`, and redundant wrappers such as `Readonly<ReadonlyRecord<K, V>>` are all unified to that style.
|
|
78
79
|
|
|
79
80
|
Example:
|
|
80
81
|
|
|
@@ -27,6 +27,25 @@ export type ReadonlyTransformerOptions = DeepReadonly<{
|
|
|
27
27
|
* @default ['mut_', '#mut_', '_mut_', 'draft']
|
|
28
28
|
*/
|
|
29
29
|
ignorePrefixes?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* The output style used when making `Record<K, V>` readonly.
|
|
32
|
+
*
|
|
33
|
+
* - `"ReadonlyRecord"`: Uses the `ReadonlyRecord` type utility provided by
|
|
34
|
+
* `ts-type-forge` (as the `ts-type-forge/prefer-readonly-or-mutable-record`
|
|
35
|
+
* ESLint rule suggests). Occurrences of `Readonly<Record<K, V>>` are also
|
|
36
|
+
* unified to `ReadonlyRecord<K, V>`. Note that no import statement is
|
|
37
|
+
* added, so `ReadonlyRecord` has to be available in the transformed code
|
|
38
|
+
* (e.g. globally via `ts-type-forge`'s `global.d.mts`).
|
|
39
|
+
* - `"Readonly<Record>"`: Uses only built-in utility types
|
|
40
|
+
* (`Readonly<Record<K, V>>`). Occurrences of `ReadonlyRecord<K, V>` are
|
|
41
|
+
* also unified to `Readonly<Record<K, V>>`.
|
|
42
|
+
*
|
|
43
|
+
* Whichever style is selected, redundant wrappers such as
|
|
44
|
+
* `Readonly<ReadonlyRecord<K, V>>` are normalized to that style as well.
|
|
45
|
+
*
|
|
46
|
+
* @default 'ReadonlyRecord'
|
|
47
|
+
*/
|
|
48
|
+
recordStyle?: 'Readonly<Record>' | 'ReadonlyRecord';
|
|
30
49
|
debug?: boolean;
|
|
31
50
|
}>;
|
|
32
51
|
//# sourceMappingURL=convert-to-readonly.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert-to-readonly.d.mts","sourceRoot":"","sources":["../../../src/functions/ast-transformers/convert-to-readonly.mts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,eAAe,CAAC;AAsBvB,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItD,eAAO,MAAM,4BAA4B,aAC7B,0BAA0B,KACnC,
|
|
1
|
+
{"version":3,"file":"convert-to-readonly.d.mts","sourceRoot":"","sources":["../../../src/functions/ast-transformers/convert-to-readonly.mts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,YAAY,EAIlB,MAAM,eAAe,CAAC;AAsBvB,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItD,eAAO,MAAM,4BAA4B,aAC7B,0BAA0B,KACnC,kBAwCF,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG,YAAY,CAAC;IACpD;;OAEG;IACH,YAAY,CAAC,EAAE;QACb;;;;WAIG;QACH,QAAQ,CAAC,EAAE,MAAM,CAAC;KA2BnB,CAAC;IAEF;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;;;;;;;;;;;;;;;OAiBG;IACH,WAAW,CAAC,EAAE,kBAAkB,GAAG,gBAAgB,CAAC;IAEpD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC,CAAC"}
|
|
@@ -31,6 +31,7 @@ const convertToReadonlyTransformer = (options) => {
|
|
|
31
31
|
},
|
|
32
32
|
ignoreEmptyObjectTypes: options?.ignoreEmptyObjectTypes ?? true,
|
|
33
33
|
ignoredPrefixes: ignorePrefixes,
|
|
34
|
+
recordStyle: options?.recordStyle ?? "ReadonlyRecord",
|
|
34
35
|
debugPrint: options?.debug === true ? console.debug : () => {
|
|
35
36
|
},
|
|
36
37
|
replaceNode: options?.debug === true ? replaceNodeWithDebugPrint : (node, newNodeText) => node.replaceWithText(newNodeText)
|
|
@@ -239,6 +240,63 @@ const transformTypeReferenceNode = (node, readonlyContext, options) => {
|
|
|
239
240
|
);
|
|
240
241
|
return;
|
|
241
242
|
}
|
|
243
|
+
if (typeNameStr === "Record") {
|
|
244
|
+
if (!Arr.isFixedLengthArray(2, typeArguments)) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
`Unexpected number of type arguments "${typeArguments.length}" for Record.`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
const nextReadonlyContextValue = nextReadonlyContext({
|
|
250
|
+
currentReadonlyContext: readonlyContext,
|
|
251
|
+
nextReadonlyContextType: "none",
|
|
252
|
+
indexedAccessDepthChange: "keep"
|
|
253
|
+
});
|
|
254
|
+
for (const t of typeArguments) {
|
|
255
|
+
transformNode(t, nextReadonlyContextValue, options);
|
|
256
|
+
}
|
|
257
|
+
if (readonlyContext.type === "none" && readonlyContext.indexedAccessDepth === 0) {
|
|
258
|
+
const [K, V] = node.getTypeArguments();
|
|
259
|
+
options.replaceNode(
|
|
260
|
+
node,
|
|
261
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
262
|
+
readonlyRecordText(K.getFullText(), V.getFullText(), options)
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (typeNameStr === "ReadonlyRecord") {
|
|
268
|
+
if (!Arr.isFixedLengthArray(2, typeArguments)) {
|
|
269
|
+
throw new Error(
|
|
270
|
+
`Unexpected number of type arguments "${typeArguments.length}" for ReadonlyRecord.`
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
const nextReadonlyContextValue = nextReadonlyContext({
|
|
274
|
+
currentReadonlyContext: readonlyContext,
|
|
275
|
+
nextReadonlyContextType: "none",
|
|
276
|
+
indexedAccessDepthChange: "keep"
|
|
277
|
+
});
|
|
278
|
+
for (const t of typeArguments) {
|
|
279
|
+
transformNode(t, nextReadonlyContextValue, options);
|
|
280
|
+
}
|
|
281
|
+
const [K, V] = node.getTypeArguments();
|
|
282
|
+
const bareRecordText = (
|
|
283
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
284
|
+
`Record<${K.getFullText()}, ${V.getFullText()}>`
|
|
285
|
+
);
|
|
286
|
+
if (readonlyContext.type === "Readonly" && readonlyContext.indexedAccessDepth === 0) {
|
|
287
|
+
options.replaceNode(node, bareRecordText);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (options.recordStyle === "Readonly<Record>") {
|
|
291
|
+
if (readonlyContext.type !== "none" || readonlyContext.indexedAccessDepth > 0) {
|
|
292
|
+
options.replaceNode(node, bareRecordText);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
options.replaceNode(node, `Readonly<${bareRecordText}>`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
242
300
|
if (typeNameStr === "Readonly") {
|
|
243
301
|
if (!Arr.isFixedLengthArray(1, typeArguments)) {
|
|
244
302
|
throw new Error(
|
|
@@ -271,6 +329,20 @@ const transformTypeReferenceNode = (node, readonlyContext, options) => {
|
|
|
271
329
|
options.replaceNode(node, T.getFullText());
|
|
272
330
|
return;
|
|
273
331
|
}
|
|
332
|
+
if (T.isKind(tsm.SyntaxKind.TypeReference) && T.getTypeName().getText() === "Record") {
|
|
333
|
+
const recordTypeArguments = T.getTypeArguments();
|
|
334
|
+
if (Arr.isFixedLengthArray(2, recordTypeArguments)) {
|
|
335
|
+
options.replaceNode(
|
|
336
|
+
node,
|
|
337
|
+
readonlyRecordText(
|
|
338
|
+
recordTypeArguments[0].getFullText(),
|
|
339
|
+
recordTypeArguments[1].getFullText(),
|
|
340
|
+
options
|
|
341
|
+
)
|
|
342
|
+
);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
274
346
|
if (T.isKind(tsm.SyntaxKind.ArrayType) || T.isKind(tsm.SyntaxKind.TupleType)) {
|
|
275
347
|
const readonlyText = `readonly ${T.getFullText()}`;
|
|
276
348
|
options.replaceNode(
|
|
@@ -341,6 +413,7 @@ const transformTypeReferenceNode = (node, readonlyContext, options) => {
|
|
|
341
413
|
}
|
|
342
414
|
}
|
|
343
415
|
};
|
|
416
|
+
const readonlyRecordText = (keyText, valueText, options) => options.recordStyle === "ReadonlyRecord" ? `ReadonlyRecord<${keyText}, ${valueText}>` : `Readonly<Record<${keyText}, ${valueText}>>`;
|
|
344
417
|
const transformArrayTypeNode = (node, readonlyContext, options) => {
|
|
345
418
|
transformNode(
|
|
346
419
|
node.getElementTypeNode(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert-to-readonly.mjs","sources":["../../../src/functions/ast-transformers/convert-to-readonly.mts"],"sourcesContent":["import {\n Arr,\n expectType,\n ISet,\n isString,\n mapNullable,\n match,\n pipe,\n} from 'ts-data-forge';\nimport * as tsm from 'ts-morph';\nimport {\n type DeepReadonly,\n type SafeUintWithSmallInt,\n type StrictExclude,\n type StrictExtract,\n} from 'ts-type-forge';\nimport {\n hasDisableNextLineComment,\n isAtomicTypeNode,\n isConditionalTypeDistributionGuard,\n isReadonlyArrayTypeNode,\n isReadonlyTupleOrArrayTypeNode,\n isReadonlyTupleTypeNode,\n isReadonlyTypeReferenceNode,\n removeParentheses,\n shouldAvoidParenthesesForReadonly,\n unwrapReadonlyTypeArgText,\n wrapWithParentheses,\n type ReadonlyTypeReferenceNode,\n} from '../functions/index.mjs';\nimport { replaceNodeWithDebugPrint } from '../utils/index.mjs';\nimport {\n groupUnionIntersectionTypes,\n invalidDeepReadonlyTypeName,\n nextReadonlyContext,\n type ReadonlyContext,\n} from './readonly-transformer-helpers/index.mjs';\nimport { type TsMorphTransformer } from './types.mjs';\n\nconst TRANSFORMER_NAME = 'convert-to-readonly';\n\nexport const convertToReadonlyTransformer = (\n options?: ReadonlyTransformerOptions,\n): TsMorphTransformer => {\n if (\n options?.DeepReadonly?.typeName !== undefined &&\n invalidDeepReadonlyTypeName.has(options.DeepReadonly.typeName)\n ) {\n throw new Error(\n `Invalid DeepReadonly typeName \"${options.DeepReadonly.typeName}\" passed to convertToReadonlyType`,\n );\n }\n\n const DeepReadonlyTypeName =\n options?.DeepReadonly?.typeName ?? 'DeepReadonly';\n\n const ignorePrefixes = ISet.create(\n options?.ignorePrefixes ?? ['mut_', '#mut_', '_mut_', 'draft'],\n );\n\n const optionsInternal: ReadonlyTransformerOptionsInternal = {\n DeepReadonly: {\n typeName: DeepReadonlyTypeName,\n applyLevel: 'keep',\n },\n ignoreEmptyObjectTypes: options?.ignoreEmptyObjectTypes ?? true,\n ignoredPrefixes: ignorePrefixes,\n debugPrint: options?.debug === true ? console.debug : () => {},\n replaceNode:\n options?.debug === true\n ? replaceNodeWithDebugPrint\n : (node, newNodeText) => node.replaceWithText(newNodeText),\n } as const;\n\n return {\n name: TRANSFORMER_NAME,\n transform: (sourceAst) => {\n for (const node of sourceAst.getChildren()) {\n transformNode(node, initialReadonlyContext, optionsInternal);\n }\n },\n };\n};\n\nexport type ReadonlyTransformerOptions = DeepReadonly<{\n /**\n * Options for a type utility `DeepReadonly` that recursively applies readonly.\n */\n DeepReadonly?: {\n /**\n * The name of a type utility that recursively applies `Readonly`.\n *\n * @default \"DeepReadonly\"\n */\n typeName?: string;\n\n /**\n * Whether to apply `DeepReadonly` aggressively or remove `DeepReadonly` as\n * possible.\n *\n * If `applyLevel` is `\"applyAggressively\"`, it applies `DeepReadonly` to all\n * nested type literals without external type references. For example, the\n * following conversions are applied:\n *\n * - `number[][]` to be `DeepReadonly<number[][]>`\n * - `number[]` to be `readonly number[]`\n * - `<T>(arg: T[][]) => void` to be `<T>(arg: readonly (readonly T[])[]>) =>\n * void`\n *\n * If `applyLevel` is `\"removeAsPossible\"`, the following conversions are applied:\n *\n * - `DeepReadonly<number[][]>` to be `readonly (readonly number[])[]`\n * - `DeepReadonly<{ a: number[] }>` to be `Readonly<{ a: readonly number[]\n * }>`\n * - `<T>(arg: DeepReadonly<T[][]>) => void` to be `<T>(arg:\n * DeepReadonly<T[][]>) => void`\n *\n * @default 'keep'\n */\n // TODO\n // applyLevel?: 'applyAggressively' | 'keep' | 'removeAsPossible';\n };\n\n /**\n * Ignore the readonly conversion for `{}`.\n *\n * @default true\n */\n ignoreEmptyObjectTypes?: boolean;\n\n /**\n * A mute keywords to ignore the readonly conversion.\n *\n * (e.g. `\"mut_\"`)\n *\n * @default ['mut_', '#mut_', '_mut_', 'draft']\n */\n ignorePrefixes?: string[];\n\n debug?: boolean;\n}>;\n\ntype ReadonlyTransformerOptionsInternal = Readonly<{\n DeepReadonly: Readonly<{\n typeName: string;\n\n // removeAsPossible: 正規化後、 DeepReadonly の子ノードが typeLiteral かまたはその union or intersection であり、 それぞれの TypeLiteral がプリミティブ値のメンバーしか持たない場合。\n applyLevel: 'applyAggressively' | 'keep' | 'removeAsPossible';\n }>;\n\n ignoreEmptyObjectTypes: boolean;\n\n ignoredPrefixes: ISet<string>;\n\n debugPrint: (...args: readonly unknown[]) => void;\n replaceNode: (node: tsm.Node, newNodeText: string) => void;\n}>;\n\nconst initialReadonlyContext: ReadonlyContext = {\n type: 'none',\n indexedAccessDepth: 0,\n} as const;\n\nconst transformNode = (\n node: tsm.Node,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (\n tsm.Node.isTypeNode(node) ||\n node.isKind(tsm.SyntaxKind.InterfaceDeclaration) ||\n node.isKind(tsm.SyntaxKind.ClassDeclaration)\n ) {\n options.debugPrint();\n\n options.debugPrint(`transformNode [${node.getKindName()}] `);\n\n options.debugPrint(node.getFullText());\n\n options.debugPrint({ readonlyContext });\n\n options.debugPrint();\n }\n\n if (hasDisableNextLineComment(node, TRANSFORMER_NAME)) {\n options.debugPrint('skipped by disable-next-line comment');\n\n return;\n }\n\n // check for ignorePrefix\n if (node.isKind(tsm.SyntaxKind.VariableDeclaration)) {\n const nodeName = node.getName();\n\n if (options.ignoredPrefixes.some((p) => nodeName.startsWith(p))) {\n // Skip conversion for variable declarations with ignored prefixes\n // Example: const mut_foo: string[] = []; -> remains as is, without appending `as const`\n options.debugPrint('skipped variable declaration by ignorePrefixes');\n\n return;\n }\n\n // TODO: Support ignoredPrefixes in ArrayBindingPattern\n // if (ts.isArrayBindingPattern(nodeName)) {\n // // for (const [i, el] of nodeName.elements.entries())\n // }\n\n // TODO: Support ignoredPrefixes in ObjectBindingPattern\n // if (ts.isObjectBindingPattern(nodeName)) {\n // // for (const [i, el] of nodeName.elements.entries())\n // }\n }\n\n // Skip readonly conversion for function declarations with ignored prefixes\n // Example: function mut_foo() {} -> parameters and return types remain as is\n if (\n (node.isKind(tsm.SyntaxKind.FunctionDeclaration) ||\n node.isKind(tsm.SyntaxKind.FunctionExpression)) &&\n options.ignoredPrefixes.some((p) => node.getName()?.startsWith(p) === true)\n ) {\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.Parameter)) {\n const nodeName = node.getName();\n\n if (options.ignoredPrefixes.some((p) => nodeName.startsWith(p))) {\n // Skip readonly conversion for variable declarations with ignored prefixes\n // Example: const mut_foo: string[] = []; -> remains as is, without readonly conversion\n return;\n }\n\n // TODO: Support ignoredPrefixes in ArrayBindingPattern\n // if (ts.isArrayBindingPattern(nodeName)) {\n // }\n\n // TODO: Support ignoredPrefixes in ObjectBindingPattern\n // if (ts.isObjectBindingPattern(nodeName)) {\n // }\n }\n\n // Skip readonly conversion for type alias declarations with ignored prefixes\n // Example: type mut_Foo = number[]; -> remains as number[] without readonly\n if (\n node.isKind(tsm.SyntaxKind.TypeAliasDeclaration) &&\n options.ignoredPrefixes.some((p) => node.getName().startsWith(p))\n ) {\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TypeReference)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to TypeReferenceNode',\n );\n }\n\n transformTypeReferenceNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.ArrayType)) {\n transformArrayTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TupleType)) {\n transformTupleTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.RestType)) {\n transformRestTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TypeOperator)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to TypeOperatorNode',\n );\n }\n\n transformTypeOperatorNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TypeLiteral)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to TypeLiteralNode',\n );\n }\n\n transformTypeLiteralNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.IndexedAccessType)) {\n transformIndexedAccessTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.MappedType)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to MappedTypeNode',\n );\n }\n\n transformMappedTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.InterfaceDeclaration)) {\n // Skip readonly conversion for interface declarations with ignored prefixes\n // Example: interface mut_Interface {...} -> properties remain without readonly\n if (options.ignoredPrefixes.some((p) => node.getName().startsWith(p))) {\n return;\n }\n\n transformInterfaceDeclarationNode(node, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.ClassDeclaration)) {\n // Skip readonly conversion for class declarations with ignored prefixes\n // Example: class mut_Class {...} -> properties remain without readonly\n if (\n options.ignoredPrefixes.some(\n (p) => node.getName()?.startsWith(p) === true,\n )\n ) {\n return;\n }\n\n transformClassDeclarationNode(node, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.IntersectionType)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to IntersectionTypeNode',\n );\n }\n\n transformIntersectionTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.UnionType)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to UnionTypeNode',\n );\n }\n\n transformUnionTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.ParenthesizedType)) {\n // NOTE: readonlyContext を不変のままバケツリレーさせるためにこのケースも必要\n transformParenthesizedTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n for (const child of node.getChildren()) {\n transformNode(child, initialReadonlyContext, options);\n }\n};\n\n//\n// Transformer implementation for each node type\n//\n\n/**\n * - `tr(ReadonlyArray<E>) |-> readonly tr(E)[]`\n * - `tr(Readonly<Readonly<E>>) |-> Readonly<tr(E)>`\n * - `tr(DeepReadonly<Readonly<E>>) |-> DeepReadonly<tr(E)>`\n * - `tr(Readonly<number>) |-> number`\n * - `tr(Readonly<E[]>) |-> readonly tr(E)[]`\n * - `tr(Readonly<[E1, E2, E3]>) |-> readonly [tr(E1), tr(E2), tr(E3)]`\n * - `tr(Readonly<readonly E[]>) |-> readonly tr(E)[]`\n * - `tr(Readonly<readonly [E1, E2, E3]>) |-> readonly [tr(E1), tr(E2), tr(E3)]`\n * - `tr(Readonly<A | readonly E[]>) |-> Readonly<tr(A)> | readonly tr(E)[]>`\n */\nconst transformTypeReferenceNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TypeReferenceNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n const typeNameStr = node.getTypeName().getText();\n\n const typeArguments = node.getTypeArguments();\n\n // Array<T> / ReadonlyArray<T> to readonly T[]\n if (typeNameStr === 'Array' || typeNameStr === 'ReadonlyArray') {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for ${typeNameStr}.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n {\n type: 'none',\n indexedAccessDepth: readonlyContext.indexedAccessDepth,\n },\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = node.getTypeArguments()[0]!;\n\n options.replaceNode(\n node,\n readonlyContext.type === 'DeepReadonly'\n ? wrapWithParentheses(`${wrapWithParentheses(T.getFullText())}[]`)\n : wrapWithParentheses(\n `readonly ${wrapWithParentheses(T.getFullText())}[]`,\n ),\n );\n\n return;\n }\n\n // Set<T> to ReadonlySet<T>\n if (typeNameStr === 'Set') {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Set.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n {\n type: 'none',\n indexedAccessDepth: readonlyContext.indexedAccessDepth,\n },\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = node.getTypeArguments()[0]!;\n\n options.replaceNode(node, `ReadonlySet<${T.getFullText()}>`);\n\n return;\n }\n\n // Map<T> to ReadonlyMap<T>\n if (typeNameStr === 'Map') {\n if (!Arr.isFixedLengthArray(2, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Map.`,\n );\n }\n\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const t of typeArguments) {\n transformNode(t, nextReadonlyContextValue, options);\n }\n\n const [K, V] = node.getTypeArguments();\n\n options.replaceNode(\n node,\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n `ReadonlyMap<${K!.getFullText()}, ${V!.getFullText()}>`,\n );\n\n return;\n }\n\n // remove unnecessary `Readonly` wrapper or convert to readonly operator\n if (typeNameStr === 'Readonly') {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Readonly.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'Readonly',\n indexedAccessDepthChange: 'keep',\n }),\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = removeParentheses(node.getTypeArguments()[0]!);\n\n // DeepReadonly<Readonly<T>> -> DeepReadonly<T>\n if (readonlyContext.type === 'DeepReadonly') {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<{ ... }>[I] -> { ... }[I]\n if (readonlyContext.indexedAccessDepth > 0) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<Readonly<T>> -> Readonly<T>\n if (isReadonlyTypeReferenceNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<number> -> number\n if (isAtomicTypeNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // T = E[]\n // Readonly<E[]> -> readonly E[]\n //\n // T = [E1, E2, E3]\n // Readonly<[E1, E2, E3]> -> readonly [E1, E2, E3]\n if (\n T.isKind(tsm.SyntaxKind.ArrayType) ||\n T.isKind(tsm.SyntaxKind.TupleType)\n ) {\n const readonlyText = `readonly ${T.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n\n return;\n }\n\n // T = readonly E[] or readonly [E1, E2, E3]\n // Readonly<readonly E[]> -> readonly E[]\n // Readonly<readonly [E1, E2, E3]> -> readonly [E1, E2, E3]\n if (isReadonlyTupleOrArrayTypeNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // T = A | B | C\n // T = A & B & C\n if (\n T.isKind(tsm.SyntaxKind.UnionType) ||\n T.isKind(tsm.SyntaxKind.IntersectionType)\n ) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n return;\n }\n\n // DeepReadonly\n if (typeNameStr === options.DeepReadonly.typeName) {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Readonly.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'DeepReadonly',\n }),\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = node.getTypeArguments()[0]!;\n\n // DeepReadonly<DeepReadonly<T>> -> DeepReadonly<T>\n if (readonlyContext.type === 'DeepReadonly') {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<number> -> number\n if (isAtomicTypeNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // T = P[]\n // DeepReadonly<P[]> -> readonly P[] (for primitive type arrays, convert to readonly P[] form)\n // DeepReadonly<O[]> -> DeepReadonly<O[]> (for object type arrays, keep as is to recursively apply Readonly)\n // DeepReadonly<P[][]> -> DeepReadonly<P[][]>\n if (\n T.isKind(tsm.SyntaxKind.ArrayType) &&\n isAtomicTypeNode(T.getElementTypeNode())\n ) {\n const readonlyText = `readonly ${T.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n\n return;\n }\n\n // T = [P1, P2, P3]\n // DeepReadonly<[P1, P2, P3]> -> readonly [P1, P2, P3]\n if (\n T.isKind(tsm.SyntaxKind.TupleType) &&\n T.getElements().every(isAtomicTypeNode)\n ) {\n const readonlyText = `readonly ${T.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n\n return;\n }\n\n return;\n }\n\n {\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const t of node.getTypeArguments()) {\n transformNode(t, nextReadonlyContextValue, options);\n }\n }\n};\n\n/** `tr(E[]) |-> tr(E)[]` */\nconst transformArrayTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.ArrayTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getElementTypeNode(),\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n switch (readonlyContext.type) {\n case 'DeepReadonly':\n case 'readonly':\n return; // remain tr(E)[] as is\n\n // Unnecessary `Readonly` wrapper will be remove in transformTypeReferenceNode\n case 'Readonly':\n case 'none':\n // Skip the `A[] extends B[] ? ...` union-distribution-guard idiom: adding\n // `readonly` there does not improve immutability and breaks the idiom.\n if (\n readonlyContext.indexedAccessDepth === 0 &&\n !isConditionalTypeDistributionGuard(node)\n ) {\n const readonlyText = `readonly ${node.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n }\n }\n};\n\n/** `tr([E1, E2, E3])` |-> `[tr(E1), tr(E2), tr(E3)]` */\nconst transformTupleTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TupleTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n {\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n });\n\n for (const el of node.getElements()) {\n if (el.isKind(tsm.SyntaxKind.NamedTupleMember)) {\n if (options.ignoredPrefixes.every((p) => !el.getName().startsWith(p))) {\n transformNode(el.getTypeNode(), nextReadonlyContextValue, options);\n }\n } else {\n transformNode(el, nextReadonlyContextValue, options);\n }\n }\n }\n\n switch (readonlyContext.type) {\n case 'DeepReadonly':\n case 'readonly':\n return; // remain tr(E)[] as is\n\n // Unnecessary `Readonly` wrapper will be remove in transformTypeReferenceNode\n case 'Readonly':\n case 'none':\n // Skip the `[A] extends [B] ? ...` union-distribution-guard idiom: adding\n // `readonly` there does not improve immutability and breaks the idiom.\n if (\n readonlyContext.indexedAccessDepth === 0 &&\n !isConditionalTypeDistributionGuard(node)\n ) {\n const readonlyText = `readonly ${node.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n }\n }\n};\n\n/** `tr(\"...T\")` |-> `...tr(T)` */\nconst transformRestTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.RestTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getTypeNode() /* = T */,\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n const R = removeParentheses(node.getTypeNode());\n\n // `tr(\"...readonly E[]\") |-> ...tr(E)[]`\n // `tr(\"...readonly [E1, E2]\") |-> ...[tr(E1), tr(E2)]`\n if (isReadonlyArrayTypeNode(R) || isReadonlyTupleTypeNode(R)) {\n options.replaceNode(\n node,\n `...${R.getTypeNode().getFullText()}` /* = tr(E)[] or [tr(E1), tr(E2)] */,\n );\n }\n};\n\n/**\n * - `readonly T[][] |-> readonly (readonly T[])[]`\n * - `keyof { a: number[] } |-> keyof Readonly<{ a: readonly number[] }>`\n */\nconst transformTypeOperatorNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TypeOperatorTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getTypeNode(),\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType:\n node.getOperator() === tsm.SyntaxKind.ReadonlyKeyword\n ? 'readonly'\n : 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n switch (readonlyContext.type) {\n // DeepReadonly<readonly E[]> -> DeepReadonly<E[]>\n case 'DeepReadonly':\n options.replaceNode(node, node.getTypeNode().getFullText());\n\n return;\n\n case 'Readonly':\n case 'none':\n if (readonlyContext.indexedAccessDepth > 0) {\n options.replaceNode(node, node.getTypeNode().getFullText());\n }\n }\n};\n\n// `{ readonly member: V } |-> Readonly<{ member: V }>`\nconst transformTypeLiteralNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TypeLiteralNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (options.ignoreEmptyObjectTypes && Arr.isEmpty(node.getMembers())) {\n return;\n }\n\n // Recursive processing\n transformMembers(\n node.getMembers(),\n 'remove',\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n switch (readonlyContext.type) {\n case 'DeepReadonly':\n case 'Readonly':\n // Don't wrap with Readonly if already readonly\n return;\n\n case 'none': {\n if (readonlyContext.indexedAccessDepth === 0) {\n // `{ readonly x: X, readonly y: Y } |-> Readonly<{ x: X, y: Y }>`\n options.replaceNode(node, `Readonly<${node.getFullText()}>`);\n }\n }\n }\n};\n\n/** `tr([A, B, C][I])` |-> `[tr(A), tr(B), tr(C)][I]` */\nconst transformIndexedAccessTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IndexedAccessTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getObjectTypeNode(),\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'incr',\n }),\n options,\n );\n\n transformNode(\n node.getIndexTypeNode() /* = I */,\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'Readonly',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n};\n\n/**\n * - `{ [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n * - `{ -readonly [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n * - `{ readonly [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n * - `{ +readonly [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n */\nconst transformMappedTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.MappedTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n const typeNode = node.getTypeNode();\n\n if (typeNode !== undefined) {\n transformNode(\n typeNode,\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n }\n\n const questionTokenText =\n pipe(node.getQuestionToken()?.getText()).mapNullable((t) =>\n t === '?' ? '?' : t === '-' ? '-?' : t === '+' ? '+?' : undefined,\n ).value ?? '';\n\n // Key remapping (`as` clause). It is part of the key set the mapped type\n // produces, so dropping it would silently change the type.\n const nameTypeText = pipe(node.getNameTypeNode()?.getFullText()).mapNullable(\n (t) => ` as ${t.trim()}`,\n ).value;\n\n const result: string = pipe(\n // remove readonlyToken\n `{ [${node.getTypeParameter().getFullText()}${nameTypeText ?? ''}]${questionTokenText}: ${node.getTypeNode()?.getFullText()} }`,\n ).map((mpt) =>\n match(readonlyContext.type, {\n // Don't wrap with Readonly if already readonly or unnecessary\n DeepReadonly: mpt,\n Readonly: mpt,\n none: readonlyContext.indexedAccessDepth > 0 ? mpt : `Readonly<${mpt}>`,\n }),\n ).value;\n\n options.replaceNode(node, result);\n};\n\n// Making interface members readonly\nconst transformInterfaceDeclarationNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.InterfaceDeclaration,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n for (const param of node.getTypeParameters()) {\n transformNode(param, initialReadonlyContext, options);\n }\n\n for (const n of node.getHeritageClauses()) {\n transformNode(n, initialReadonlyContext, options);\n }\n\n transformMembers(node.getMembers(), 'add', initialReadonlyContext, options);\n};\n\nconst transformClassDeclarationNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.ClassDeclaration,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n for (const n of node.getTypeParameters()) {\n transformNode(n, initialReadonlyContext, options);\n }\n\n for (const n of node.getHeritageClauses()) {\n transformNode(n, initialReadonlyContext, options);\n }\n\n for (const mb of node.getMembers()) {\n if (hasDisableNextLineComment(mb)) {\n options.debugPrint('skipped member by disable-next-line comment');\n\n continue;\n }\n\n if (mb.isKind(tsm.SyntaxKind.PropertyDeclaration)) {\n if (!checkIfPropertyNameShouldBeIgnored(mb.getNameNode(), options)) {\n mb.setIsReadonly(true);\n\n const type = mb.getTypeNode();\n\n if (type !== undefined) {\n transformNode(type, initialReadonlyContext, options);\n }\n\n const initializer = mb.getInitializer();\n\n if (initializer !== undefined) {\n transformNode(initializer, initialReadonlyContext, options);\n }\n }\n\n continue;\n }\n\n // MethodDeclaration, GetAccessorDeclaration, SetAccessorDeclaration\n // Check if method name has ignored prefix (e.g., mut_)\n if (\n (mb.isKind(tsm.SyntaxKind.MethodDeclaration) ||\n mb.isKind(tsm.SyntaxKind.GetAccessor) ||\n mb.isKind(tsm.SyntaxKind.SetAccessor)) &&\n checkIfPropertyNameShouldBeIgnored(mb.getNameNode(), options)\n ) {\n options.debugPrint('skipped method by ignored prefix');\n\n continue;\n }\n\n transformNode(mb, initialReadonlyContext, options);\n }\n\n for (const mb of node.getChildrenOfKind(tsm.SyntaxKind.IndexSignature)) {\n transformIndexSignatureDeclaration(\n mb,\n 'add',\n initialReadonlyContext,\n options,\n );\n }\n\n for (const ctor of node.getConstructors()) {\n for (const param of ctor.getParameters()) {\n transformConstructorParameter(param, options);\n }\n\n const body = ctor.getBody();\n\n if (body !== undefined) {\n transformNode(body, initialReadonlyContext, options);\n }\n }\n};\n\nconst transformConstructorParameter = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n param: tsm.ParameterDeclaration,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (hasDisableNextLineComment(param)) {\n options.debugPrint(\n 'skipped class constructor parameter by disable-next-line comment',\n );\n\n return;\n }\n\n const name = param.getName();\n\n if (options.ignoredPrefixes.some((p) => name.startsWith(p))) {\n return;\n }\n\n // Check if parameter is a property declaration (public/protected/private)\n const scope = param.getScope();\n\n // public -> public readonly\n // protected -> protected readonly\n // private -> private readonly\n if (\n scope === tsm.Scope.Public ||\n scope === tsm.Scope.Protected ||\n scope === tsm.Scope.Private\n ) {\n param.setIsReadonly(true);\n }\n\n const type = param.getTypeNode();\n\n if (type !== undefined) {\n transformNode(type, initialReadonlyContext, options);\n }\n};\n\n/**\n * - `tr(A & B) -> tr(A) & tr(B)`\n * - `tr(Readonly<A> & Readonly<B>) -> Readonly<tr(A) & tr(B)>`\n */\nconst transformIntersectionTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IntersectionTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n transformUnionOrIntersectionTypeNodeImpl(node, readonlyContext, options, '&');\n};\n\n/**\n * - `tr(A | B) |-> tr(A) | tr(B)`\n * - `tr(Readonly<A> | Readonly<B>) |-> Readonly<tr(A) | tr(B)>`\n */\nconst transformUnionTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.UnionTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n transformUnionOrIntersectionTypeNodeImpl(node, readonlyContext, options, '|');\n};\n\nconst transformUnionOrIntersectionTypeNodeImpl = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IntersectionTypeNode | tsm.UnionTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n operator: '&' | '|',\n): void => {\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const n of node.getTypeNodes() /* = [A, B] */) {\n transformNode(n, nextReadonlyContextValue, options);\n }\n\n const newTypes = node.getTypeNodes();\n\n const { primitives, arraysAndTuples, typeLiterals, others } =\n groupUnionIntersectionTypes(newTypes);\n\n options.debugPrint({ primitives, arraysAndTuples, typeLiterals, others });\n\n // Separate empty type literals from non-empty ones when ignoreEmptyObjectTypes is true\n const isEmptyTypeLiteral = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n n: tsm.TypeLiteralNode | ReadonlyTypeReferenceNode,\n ): boolean =>\n n.isKind(tsm.SyntaxKind.TypeLiteral) && Arr.isEmpty(n.getMembers());\n\n const nonEmptyTypeLiterals =\n typeLiterals === undefined\n ? undefined\n : options.ignoreEmptyObjectTypes\n ? typeLiterals.nodes.filter((n) => !isEmptyTypeLiteral(n))\n : typeLiterals.nodes;\n\n const emptyTypeLiterals =\n typeLiterals === undefined || !options.ignoreEmptyObjectTypes\n ? undefined\n : typeLiterals.nodes.filter(isEmptyTypeLiteral);\n\n const typeLiteralsWrappedWithReadonly: readonly [] | readonly [string] =\n nonEmptyTypeLiterals === undefined || Arr.isEmpty(nonEmptyTypeLiterals)\n ? ([] as const)\n : ([\n unionToString({\n types: nonEmptyTypeLiterals.map((n) =>\n isReadonlyTypeReferenceNode(n)\n ? // NOTE: Readonly<A & B> -> (A & B)\n unwrapReadonlyTypeArgText(n)\n : (n satisfies tsm.TypeLiteralNode).getFullText(),\n ),\n op: operator,\n wrapWithReadonly:\n nextReadonlyContextValue.type !== 'DeepReadonly' &&\n nextReadonlyContextValue.indexedAccessDepth === 0,\n }),\n ] as const);\n\n // Sort by first occurrence (preserving the original union order as much as possible)\n const sorted: readonly string[] = [\n mapNullable(\n primitives,\n (a) => [a.nodes.map((n) => n.getFullText()), a.firstPosition] as const,\n ),\n mapNullable(\n arraysAndTuples,\n (a) => [a.nodes.map((n) => n.getFullText()), a.firstPosition] as const,\n ),\n nonEmptyTypeLiterals !== undefined && Arr.isNonEmpty(nonEmptyTypeLiterals)\n ? mapNullable(\n typeLiterals,\n (a) => [typeLiteralsWrappedWithReadonly, a.firstPosition] as const,\n )\n : undefined,\n emptyTypeLiterals !== undefined && Arr.isNonEmpty(emptyTypeLiterals)\n ? mapNullable(\n typeLiterals,\n (a) =>\n [\n emptyTypeLiterals.map((n) => n.getFullText()),\n // Use a position after non-empty type literals if they exist\n a.firstPosition +\n (nonEmptyTypeLiterals !== undefined &&\n Arr.isNonEmpty(nonEmptyTypeLiterals)\n ? 0.5\n : 0),\n ] as const,\n )\n : undefined,\n mapNullable(\n others,\n (a) =>\n [\n a.nodes.map((n) => wrapWithParentheses(n.getFullText())),\n a.firstPosition,\n ] as const,\n ),\n ]\n .filter((x) => x !== undefined)\n .toSorted((a, b) => a[1] - b[1])\n .flatMap((a) => a[0]);\n\n // Readonly<number & { x: X } & { y: Y } & readonly E[]>\n // -> number & readonly E[] & Readonly<{ x: X } & { y: Y }>\n\n // Readonly<number | { x: X } | { y: Y } | readonly E[]>\n // -> number | readonly E[] | Readonly<{ x: X } | { y: Y }>\n // Readonly<number & { x: X } & { y: Y } & readonly E[]>\n // -> number & readonly E[] & Readonly<{ x: X } & { y: Y }>\n\n // Readonly<number | { x: X } | { y: Y } | readonly E[]>\n // -> number | readonly E[] | Readonly<{ x: X } | { y: Y }>\n //\n // NOTE: The result is wrapped in parentheses (via `unionToString`). This is\n // intentional and required for precedence safety: without it, a member such\n // as a function type (`() => T`), or a mix of `&` and `|`, or a `readonly`\n // operator would produce invalid syntax when this node is spliced back in.\n // Idempotency is guaranteed by `transformParenthesizedTypeNode`, which\n // collapses the redundant nesting (`((X))` -> `(X)`) this wrapping can create\n // — see the note there. That prevents the parentheses from growing without\n // bound when a union/intersection sits inside a `ParenthesizedType`.\n options.replaceNode(\n node,\n unionToString({ types: sorted, op: operator, wrapWithReadonly: false }),\n );\n};\n\nconst unionToString = ({\n types,\n op,\n wrapWithReadonly,\n}: Readonly<{\n types: readonly string[];\n op: '&' | '|';\n wrapWithReadonly: boolean | string;\n}>): string =>\n Arr.isEmpty(types)\n ? 'never'\n : Arr.isFixedLengthArray(1, types)\n ? wrapWithReadonly === false\n ? wrapWithParentheses(types[0])\n : (`${isString(wrapWithReadonly) ? wrapWithReadonly : 'Readonly'}<${types[0]}>` as const)\n : wrapWithReadonly === false\n ? wrapWithParentheses(types.join(` ${op} `))\n : (`${isString(wrapWithReadonly) ? wrapWithReadonly : 'Readonly'}<${types.join(` ${op} `)}>` as const);\n\n/** Convert ((T)) -> (T) recursively */\nconst transformParenthesizedTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.ParenthesizedTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n const typeNode = node.getTypeNode();\n\n if (typeNode.isKind(tsm.SyntaxKind.ParenthesizedType)) {\n // Recursive processing\n transformParenthesizedTypeNode(typeNode, readonlyContext, options);\n }\n\n transformNode(node.getTypeNode(), readonlyContext, options);\n\n const T = node.getTypeNode();\n\n if (\n // remove () if T is TypeReferenceNode\n // e.g. `(Readonly<A>) |-> Readonly<A>`\n T.isKind(tsm.SyntaxKind.TypeReference) ||\n // remove () if T is ArrayTypeNode\n // e.g. `(A[]) |-> A[]`\n T.isKind(tsm.SyntaxKind.ArrayType) ||\n // remove () if T is TupleTypeNode\n // e.g. `([A]) |-> [A]`\n T.isKind(tsm.SyntaxKind.TupleType) ||\n // remove () if T is PrimitiveTypeNode\n // e.g. `(number) |-> number`\n isAtomicTypeNode(T) ||\n // remove () if T is TypeLiteralNode\n // e.g. `({ member: V }) |-> { member: V }`\n T.isKind(tsm.SyntaxKind.TypeLiteral) ||\n // collapse redundant nested parentheses if T is itself a ParenthesizedType\n // e.g. `((X)) |-> (X)`\n //\n // This is what makes the transform terminate on nested parentheses. The\n // union/intersection handler defensively wraps its result in parentheses\n // for precedence safety, which turns `(A | B)` into `((A | B))` when the\n // union already sits inside a `ParenthesizedType`. Collapsing the redundant\n // outer layer here means each pass removes exactly the layer the wrapping\n // added, so the parentheses no longer grow without bound (which previously\n // overflowed the parser stack on inputs like `type T = (('a' | 'b'))`).\n T.isKind(tsm.SyntaxKind.ParenthesizedType)\n ) {\n options.replaceNode(node, T.getFullText());\n }\n};\n\n/**\n * `tr([\"member1: V1\", \"member2: V2\", \"member3: V3\"])`\n *\n * -> `[\"member1: tr(V1)\", \"member2: tr(V2)\", \"member3: tr(V3)\"]`\n */\nconst transformMembers = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n members: readonly tsm.TypeElementTypes[],\n readonlyModifier: 'add' | 'remove',\n readonlyContext: StrictExtract<\n ReadonlyContext,\n Readonly<{\n type: 'DeepReadonly' | 'none';\n indexedAccessDepth: SafeUintWithSmallInt;\n }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n for (const mb of members) {\n if (hasDisableNextLineComment(mb)) {\n options.debugPrint('skipped by member disable-next-line comment');\n\n continue;\n }\n\n if (mb.isKind(tsm.SyntaxKind.PropertySignature)) {\n if (!checkIfPropertyNameShouldBeIgnored(mb.getNameNode(), options)) {\n transformPropertySignature(\n mb,\n readonlyModifier,\n readonlyContext,\n options,\n );\n }\n\n continue;\n }\n\n if (mb.isKind(tsm.SyntaxKind.IndexSignature)) {\n transformIndexSignatureDeclaration(\n mb,\n readonlyModifier,\n readonlyContext,\n options,\n );\n\n continue;\n }\n\n transformNode(mb, readonlyContext, options);\n }\n};\n\nconst transformPropertySignature = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.PropertySignature,\n readonlyModifier: 'add' | 'remove',\n readonlyContext: StrictExtract<\n ReadonlyContext,\n Readonly<{\n type: 'DeepReadonly' | 'none';\n indexedAccessDepth: SafeUintWithSmallInt;\n }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (\n readonlyModifier === 'remove' ||\n readonlyContext.type === 'DeepReadonly'\n ) {\n node.setIsReadonly(false);\n } else {\n node.setIsReadonly(true);\n }\n\n {\n const type = node.getTypeNode();\n\n if (type !== undefined) {\n transformNode(type, readonlyContext, options);\n }\n }\n};\n\nconst transformIndexSignatureDeclaration = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IndexSignatureDeclaration,\n readonlyModifier: 'add' | 'remove',\n readonlyContext: StrictExtract<\n ReadonlyContext,\n Readonly<{\n type: 'DeepReadonly' | 'none';\n indexedAccessDepth: SafeUintWithSmallInt;\n }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (hasDisableNextLineComment(node, TRANSFORMER_NAME)) {\n options.debugPrint('skipped index signature by disable-next-line comment');\n\n return;\n }\n\n if (\n readonlyModifier === 'remove' ||\n readonlyContext.type === 'DeepReadonly'\n ) {\n // node.setIsReadonly(false);\n node.toggleModifier('readonly', false);\n } else {\n node.toggleModifier('readonly', true);\n // node.setIsReadonly(true);\n }\n\n {\n const key = node.getKeyTypeNode();\n\n transformNode(key, readonlyContext, options);\n }\n\n {\n const ret = node.getReturnTypeNode();\n\n if (ret !== undefined) {\n transformNode(ret, readonlyContext, options);\n }\n }\n};\n\nconst checkIfPropertyNameShouldBeIgnored = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n nameNode: tsm.PropertyName,\n options: ReadonlyTransformerOptionsInternal,\n): boolean => {\n expectType<typeof nameNode, tsm.PropertyName>('=');\n\n expectType<\n tsm.PropertyName,\n | tsm.NumericLiteral\n | tsm.BigIntLiteral\n | tsm.NoSubstitutionTemplateLiteral\n | tsm.Identifier\n | tsm.StringLiteral\n | tsm.PrivateIdentifier\n | tsm.ComputedPropertyName // [`mut_x`]: number[]\n >('=');\n\n return (\n // mut_x: number[]\n (nameNode.isKind(tsm.SyntaxKind.Identifier) &&\n pipe(nameNode.getText()).map((nm) =>\n options.ignoredPrefixes.some((p) => nm.startsWith(p)),\n ).value) ||\n // \"mut_x\": number[]\n (nameNode.isKind(tsm.SyntaxKind.StringLiteral) &&\n pipe(nameNode.getLiteralValue()).map((nm) =>\n options.ignoredPrefixes.some((p) => nm.startsWith(p)),\n ).value) ||\n // #memberName: number[] (class only)\n (nameNode.isKind(tsm.SyntaxKind.PrivateIdentifier) &&\n pipe(nameNode.getText()).map((nm) =>\n options.ignoredPrefixes.some((p) => nm.startsWith(`#${p}`)),\n ).value) ||\n // [`mut_x`]: number[]\n (nameNode.isKind(tsm.SyntaxKind.ComputedPropertyName) &&\n pipe(nameNode.getExpression()).map((exp) => {\n if (exp.isKind(tsm.SyntaxKind.StringLiteral)) {\n const nm = exp.getLiteralValue();\n\n return options.ignoredPrefixes.some((p) => nm.startsWith(p));\n }\n\n return false;\n }).value)\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"convert-to-readonly.mjs","sources":["../../../src/functions/ast-transformers/convert-to-readonly.mts"],"sourcesContent":["import {\n Arr,\n expectType,\n ISet,\n isString,\n mapNullable,\n match,\n pipe,\n} from 'ts-data-forge';\nimport * as tsm from 'ts-morph';\nimport {\n type DeepReadonly,\n type SafeUintWithSmallInt,\n type StrictExclude,\n type StrictExtract,\n} from 'ts-type-forge';\nimport {\n hasDisableNextLineComment,\n isAtomicTypeNode,\n isConditionalTypeDistributionGuard,\n isReadonlyArrayTypeNode,\n isReadonlyTupleOrArrayTypeNode,\n isReadonlyTupleTypeNode,\n isReadonlyTypeReferenceNode,\n removeParentheses,\n shouldAvoidParenthesesForReadonly,\n unwrapReadonlyTypeArgText,\n wrapWithParentheses,\n type ReadonlyTypeReferenceNode,\n} from '../functions/index.mjs';\nimport { replaceNodeWithDebugPrint } from '../utils/index.mjs';\nimport {\n groupUnionIntersectionTypes,\n invalidDeepReadonlyTypeName,\n nextReadonlyContext,\n type ReadonlyContext,\n} from './readonly-transformer-helpers/index.mjs';\nimport { type TsMorphTransformer } from './types.mjs';\n\nconst TRANSFORMER_NAME = 'convert-to-readonly';\n\nexport const convertToReadonlyTransformer = (\n options?: ReadonlyTransformerOptions,\n): TsMorphTransformer => {\n if (\n options?.DeepReadonly?.typeName !== undefined &&\n invalidDeepReadonlyTypeName.has(options.DeepReadonly.typeName)\n ) {\n throw new Error(\n `Invalid DeepReadonly typeName \"${options.DeepReadonly.typeName}\" passed to convertToReadonlyType`,\n );\n }\n\n const DeepReadonlyTypeName =\n options?.DeepReadonly?.typeName ?? 'DeepReadonly';\n\n const ignorePrefixes = ISet.create(\n options?.ignorePrefixes ?? ['mut_', '#mut_', '_mut_', 'draft'],\n );\n\n const optionsInternal: ReadonlyTransformerOptionsInternal = {\n DeepReadonly: {\n typeName: DeepReadonlyTypeName,\n applyLevel: 'keep',\n },\n ignoreEmptyObjectTypes: options?.ignoreEmptyObjectTypes ?? true,\n ignoredPrefixes: ignorePrefixes,\n recordStyle: options?.recordStyle ?? 'ReadonlyRecord',\n debugPrint: options?.debug === true ? console.debug : () => {},\n replaceNode:\n options?.debug === true\n ? replaceNodeWithDebugPrint\n : (node, newNodeText) => node.replaceWithText(newNodeText),\n } as const;\n\n return {\n name: TRANSFORMER_NAME,\n transform: (sourceAst) => {\n for (const node of sourceAst.getChildren()) {\n transformNode(node, initialReadonlyContext, optionsInternal);\n }\n },\n };\n};\n\nexport type ReadonlyTransformerOptions = DeepReadonly<{\n /**\n * Options for a type utility `DeepReadonly` that recursively applies readonly.\n */\n DeepReadonly?: {\n /**\n * The name of a type utility that recursively applies `Readonly`.\n *\n * @default \"DeepReadonly\"\n */\n typeName?: string;\n\n /**\n * Whether to apply `DeepReadonly` aggressively or remove `DeepReadonly` as\n * possible.\n *\n * If `applyLevel` is `\"applyAggressively\"`, it applies `DeepReadonly` to all\n * nested type literals without external type references. For example, the\n * following conversions are applied:\n *\n * - `number[][]` to be `DeepReadonly<number[][]>`\n * - `number[]` to be `readonly number[]`\n * - `<T>(arg: T[][]) => void` to be `<T>(arg: readonly (readonly T[])[]>) =>\n * void`\n *\n * If `applyLevel` is `\"removeAsPossible\"`, the following conversions are applied:\n *\n * - `DeepReadonly<number[][]>` to be `readonly (readonly number[])[]`\n * - `DeepReadonly<{ a: number[] }>` to be `Readonly<{ a: readonly number[]\n * }>`\n * - `<T>(arg: DeepReadonly<T[][]>) => void` to be `<T>(arg:\n * DeepReadonly<T[][]>) => void`\n *\n * @default 'keep'\n */\n // TODO\n // applyLevel?: 'applyAggressively' | 'keep' | 'removeAsPossible';\n };\n\n /**\n * Ignore the readonly conversion for `{}`.\n *\n * @default true\n */\n ignoreEmptyObjectTypes?: boolean;\n\n /**\n * A mute keywords to ignore the readonly conversion.\n *\n * (e.g. `\"mut_\"`)\n *\n * @default ['mut_', '#mut_', '_mut_', 'draft']\n */\n ignorePrefixes?: string[];\n\n /**\n * The output style used when making `Record<K, V>` readonly.\n *\n * - `\"ReadonlyRecord\"`: Uses the `ReadonlyRecord` type utility provided by\n * `ts-type-forge` (as the `ts-type-forge/prefer-readonly-or-mutable-record`\n * ESLint rule suggests). Occurrences of `Readonly<Record<K, V>>` are also\n * unified to `ReadonlyRecord<K, V>`. Note that no import statement is\n * added, so `ReadonlyRecord` has to be available in the transformed code\n * (e.g. globally via `ts-type-forge`'s `global.d.mts`).\n * - `\"Readonly<Record>\"`: Uses only built-in utility types\n * (`Readonly<Record<K, V>>`). Occurrences of `ReadonlyRecord<K, V>` are\n * also unified to `Readonly<Record<K, V>>`.\n *\n * Whichever style is selected, redundant wrappers such as\n * `Readonly<ReadonlyRecord<K, V>>` are normalized to that style as well.\n *\n * @default 'ReadonlyRecord'\n */\n recordStyle?: 'Readonly<Record>' | 'ReadonlyRecord';\n\n debug?: boolean;\n}>;\n\ntype ReadonlyTransformerOptionsInternal = Readonly<{\n DeepReadonly: Readonly<{\n typeName: string;\n\n // removeAsPossible: 正規化後、 DeepReadonly の子ノードが typeLiteral かまたはその union or intersection であり、 それぞれの TypeLiteral がプリミティブ値のメンバーしか持たない場合。\n applyLevel: 'applyAggressively' | 'keep' | 'removeAsPossible';\n }>;\n\n ignoreEmptyObjectTypes: boolean;\n\n ignoredPrefixes: ISet<string>;\n\n recordStyle: 'Readonly<Record>' | 'ReadonlyRecord';\n\n debugPrint: (...args: readonly unknown[]) => void;\n replaceNode: (node: tsm.Node, newNodeText: string) => void;\n}>;\n\nconst initialReadonlyContext: ReadonlyContext = {\n type: 'none',\n indexedAccessDepth: 0,\n} as const;\n\nconst transformNode = (\n node: tsm.Node,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (\n tsm.Node.isTypeNode(node) ||\n node.isKind(tsm.SyntaxKind.InterfaceDeclaration) ||\n node.isKind(tsm.SyntaxKind.ClassDeclaration)\n ) {\n options.debugPrint();\n\n options.debugPrint(`transformNode [${node.getKindName()}] `);\n\n options.debugPrint(node.getFullText());\n\n options.debugPrint({ readonlyContext });\n\n options.debugPrint();\n }\n\n if (hasDisableNextLineComment(node, TRANSFORMER_NAME)) {\n options.debugPrint('skipped by disable-next-line comment');\n\n return;\n }\n\n // check for ignorePrefix\n if (node.isKind(tsm.SyntaxKind.VariableDeclaration)) {\n const nodeName = node.getName();\n\n if (options.ignoredPrefixes.some((p) => nodeName.startsWith(p))) {\n // Skip conversion for variable declarations with ignored prefixes\n // Example: const mut_foo: string[] = []; -> remains as is, without appending `as const`\n options.debugPrint('skipped variable declaration by ignorePrefixes');\n\n return;\n }\n\n // TODO: Support ignoredPrefixes in ArrayBindingPattern\n // if (ts.isArrayBindingPattern(nodeName)) {\n // // for (const [i, el] of nodeName.elements.entries())\n // }\n\n // TODO: Support ignoredPrefixes in ObjectBindingPattern\n // if (ts.isObjectBindingPattern(nodeName)) {\n // // for (const [i, el] of nodeName.elements.entries())\n // }\n }\n\n // Skip readonly conversion for function declarations with ignored prefixes\n // Example: function mut_foo() {} -> parameters and return types remain as is\n if (\n (node.isKind(tsm.SyntaxKind.FunctionDeclaration) ||\n node.isKind(tsm.SyntaxKind.FunctionExpression)) &&\n options.ignoredPrefixes.some((p) => node.getName()?.startsWith(p) === true)\n ) {\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.Parameter)) {\n const nodeName = node.getName();\n\n if (options.ignoredPrefixes.some((p) => nodeName.startsWith(p))) {\n // Skip readonly conversion for variable declarations with ignored prefixes\n // Example: const mut_foo: string[] = []; -> remains as is, without readonly conversion\n return;\n }\n\n // TODO: Support ignoredPrefixes in ArrayBindingPattern\n // if (ts.isArrayBindingPattern(nodeName)) {\n // }\n\n // TODO: Support ignoredPrefixes in ObjectBindingPattern\n // if (ts.isObjectBindingPattern(nodeName)) {\n // }\n }\n\n // Skip readonly conversion for type alias declarations with ignored prefixes\n // Example: type mut_Foo = number[]; -> remains as number[] without readonly\n if (\n node.isKind(tsm.SyntaxKind.TypeAliasDeclaration) &&\n options.ignoredPrefixes.some((p) => node.getName().startsWith(p))\n ) {\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TypeReference)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to TypeReferenceNode',\n );\n }\n\n transformTypeReferenceNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.ArrayType)) {\n transformArrayTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TupleType)) {\n transformTupleTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.RestType)) {\n transformRestTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TypeOperator)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to TypeOperatorNode',\n );\n }\n\n transformTypeOperatorNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TypeLiteral)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to TypeLiteralNode',\n );\n }\n\n transformTypeLiteralNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.IndexedAccessType)) {\n transformIndexedAccessTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.MappedType)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to MappedTypeNode',\n );\n }\n\n transformMappedTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.InterfaceDeclaration)) {\n // Skip readonly conversion for interface declarations with ignored prefixes\n // Example: interface mut_Interface {...} -> properties remain without readonly\n if (options.ignoredPrefixes.some((p) => node.getName().startsWith(p))) {\n return;\n }\n\n transformInterfaceDeclarationNode(node, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.ClassDeclaration)) {\n // Skip readonly conversion for class declarations with ignored prefixes\n // Example: class mut_Class {...} -> properties remain without readonly\n if (\n options.ignoredPrefixes.some(\n (p) => node.getName()?.startsWith(p) === true,\n )\n ) {\n return;\n }\n\n transformClassDeclarationNode(node, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.IntersectionType)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to IntersectionTypeNode',\n );\n }\n\n transformIntersectionTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.UnionType)) {\n if (readonlyContext.type === 'readonly') {\n throw new Error(\n 'Invalid readonlyContext \"readonly\" passed to UnionTypeNode',\n );\n }\n\n transformUnionTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.ParenthesizedType)) {\n // NOTE: readonlyContext を不変のままバケツリレーさせるためにこのケースも必要\n transformParenthesizedTypeNode(node, readonlyContext, options);\n\n return;\n }\n\n for (const child of node.getChildren()) {\n transformNode(child, initialReadonlyContext, options);\n }\n};\n\n//\n// Transformer implementation for each node type\n//\n\n/**\n * - `tr(ReadonlyArray<E>) |-> readonly tr(E)[]`\n * - `tr(Readonly<Readonly<E>>) |-> Readonly<tr(E)>`\n * - `tr(DeepReadonly<Readonly<E>>) |-> DeepReadonly<tr(E)>`\n * - `tr(Readonly<number>) |-> number`\n * - `tr(Readonly<E[]>) |-> readonly tr(E)[]`\n * - `tr(Readonly<[E1, E2, E3]>) |-> readonly [tr(E1), tr(E2), tr(E3)]`\n * - `tr(Readonly<readonly E[]>) |-> readonly tr(E)[]`\n * - `tr(Readonly<readonly [E1, E2, E3]>) |-> readonly [tr(E1), tr(E2), tr(E3)]`\n * - `tr(Readonly<A | readonly E[]>) |-> Readonly<tr(A)> | readonly tr(E)[]>`\n * - `tr(Record<K, V>) |-> Readonly<Record<tr(K), tr(V)>>` (or\n * `ReadonlyRecord<tr(K), tr(V)>`, depending on the `recordStyle` option;\n * `Readonly<Record<K, V>>`, `ReadonlyRecord<K, V>` and\n * `Readonly<ReadonlyRecord<K, V>>` are unified to the same style)\n */\nconst transformTypeReferenceNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TypeReferenceNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n const typeNameStr = node.getTypeName().getText();\n\n const typeArguments = node.getTypeArguments();\n\n // Array<T> / ReadonlyArray<T> to readonly T[]\n if (typeNameStr === 'Array' || typeNameStr === 'ReadonlyArray') {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for ${typeNameStr}.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n {\n type: 'none',\n indexedAccessDepth: readonlyContext.indexedAccessDepth,\n },\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = node.getTypeArguments()[0]!;\n\n options.replaceNode(\n node,\n readonlyContext.type === 'DeepReadonly'\n ? wrapWithParentheses(`${wrapWithParentheses(T.getFullText())}[]`)\n : wrapWithParentheses(\n `readonly ${wrapWithParentheses(T.getFullText())}[]`,\n ),\n );\n\n return;\n }\n\n // Set<T> to ReadonlySet<T>\n if (typeNameStr === 'Set') {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Set.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n {\n type: 'none',\n indexedAccessDepth: readonlyContext.indexedAccessDepth,\n },\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = node.getTypeArguments()[0]!;\n\n options.replaceNode(node, `ReadonlySet<${T.getFullText()}>`);\n\n return;\n }\n\n // Map<T> to ReadonlyMap<T>\n if (typeNameStr === 'Map') {\n if (!Arr.isFixedLengthArray(2, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Map.`,\n );\n }\n\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const t of typeArguments) {\n transformNode(t, nextReadonlyContextValue, options);\n }\n\n const [K, V] = node.getTypeArguments();\n\n options.replaceNode(\n node,\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n `ReadonlyMap<${K!.getFullText()}, ${V!.getFullText()}>`,\n );\n\n return;\n }\n\n // Record<K, V> to ReadonlyRecord<K, V> / Readonly<Record<K, V>>\n if (typeNameStr === 'Record') {\n if (!Arr.isFixedLengthArray(2, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Record.`,\n );\n }\n\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const t of typeArguments) {\n transformNode(t, nextReadonlyContextValue, options);\n }\n\n // The bare Record is kept as is in the following cases:\n // - DeepReadonly<Record<K, V>> already applies readonly recursively.\n // - Readonly<Record<K, V>> is unified to the configured record style by\n // the surrounding `Readonly` handler.\n // - Record<K, V>[I] does not need readonly, just like\n // `Readonly<{ ... }>[I] -> { ... }[I]`.\n if (\n readonlyContext.type === 'none' &&\n readonlyContext.indexedAccessDepth === 0\n ) {\n const [K, V] = node.getTypeArguments();\n\n options.replaceNode(\n node,\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n readonlyRecordText(K!.getFullText(), V!.getFullText(), options),\n );\n }\n\n return;\n }\n\n // Unify ReadonlyRecord<K, V> to the configured record style\n if (typeNameStr === 'ReadonlyRecord') {\n if (!Arr.isFixedLengthArray(2, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for ReadonlyRecord.`,\n );\n }\n\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const t of typeArguments) {\n transformNode(t, nextReadonlyContextValue, options);\n }\n\n const [K, V] = node.getTypeArguments();\n\n const bareRecordText =\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n `Record<${K!.getFullText()}, ${V!.getFullText()}>` as const;\n\n // Readonly<ReadonlyRecord<K, V>> -> Readonly<Record<K, V>>\n // (the surrounding `Readonly` handler then unifies it to the configured\n // record style, so the bare Record never survives into the output)\n if (\n readonlyContext.type === 'Readonly' &&\n readonlyContext.indexedAccessDepth === 0\n ) {\n options.replaceNode(node, bareRecordText);\n\n return;\n }\n\n if (options.recordStyle === 'Readonly<Record>') {\n // The ReadonlyRecord name is eliminated everywhere:\n // - DeepReadonly<ReadonlyRecord<K, V>> -> DeepReadonly<Record<K, V>>\n // - ReadonlyRecord<K, V>[I] -> Record<K, V>[I]\n // (readonly is unnecessary under indexed access, as with\n // Readonly<{ ... }>[I] -> { ... }[I])\n if (\n readonlyContext.type !== 'none' ||\n readonlyContext.indexedAccessDepth > 0\n ) {\n options.replaceNode(node, bareRecordText);\n\n return;\n }\n\n options.replaceNode(node, `Readonly<${bareRecordText}>`);\n\n return;\n }\n\n // With `recordStyle: \"ReadonlyRecord\"`, ReadonlyRecord is already the\n // configured style. It is deliberately kept even under DeepReadonly or an\n // indexed access — stripping it to the bare built-in `Record` there would\n // conflict with the `ts-type-forge/prefer-readonly-or-mutable-record`\n // ESLint rule.\n return;\n }\n\n // remove unnecessary `Readonly` wrapper or convert to readonly operator\n if (typeNameStr === 'Readonly') {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Readonly.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'Readonly',\n indexedAccessDepthChange: 'keep',\n }),\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = removeParentheses(node.getTypeArguments()[0]!);\n\n // DeepReadonly<Readonly<T>> -> DeepReadonly<T>\n if (readonlyContext.type === 'DeepReadonly') {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<{ ... }>[I] -> { ... }[I]\n if (readonlyContext.indexedAccessDepth > 0) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<Readonly<T>> -> Readonly<T>\n if (isReadonlyTypeReferenceNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<number> -> number\n if (isAtomicTypeNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<Record<K, V>> -> the configured record style\n // (`ReadonlyRecord<K, V>` or `Readonly<Record<K, V>>` as is)\n if (\n T.isKind(tsm.SyntaxKind.TypeReference) &&\n T.getTypeName().getText() === 'Record'\n ) {\n const recordTypeArguments = T.getTypeArguments();\n\n if (Arr.isFixedLengthArray(2, recordTypeArguments)) {\n options.replaceNode(\n node,\n readonlyRecordText(\n recordTypeArguments[0].getFullText(),\n recordTypeArguments[1].getFullText(),\n options,\n ),\n );\n\n return;\n }\n }\n\n // T = E[]\n // Readonly<E[]> -> readonly E[]\n //\n // T = [E1, E2, E3]\n // Readonly<[E1, E2, E3]> -> readonly [E1, E2, E3]\n if (\n T.isKind(tsm.SyntaxKind.ArrayType) ||\n T.isKind(tsm.SyntaxKind.TupleType)\n ) {\n const readonlyText = `readonly ${T.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n\n return;\n }\n\n // T = readonly E[] or readonly [E1, E2, E3]\n // Readonly<readonly E[]> -> readonly E[]\n // Readonly<readonly [E1, E2, E3]> -> readonly [E1, E2, E3]\n if (isReadonlyTupleOrArrayTypeNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // T = A | B | C\n // T = A & B & C\n if (\n T.isKind(tsm.SyntaxKind.UnionType) ||\n T.isKind(tsm.SyntaxKind.IntersectionType)\n ) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n return;\n }\n\n // DeepReadonly\n if (typeNameStr === options.DeepReadonly.typeName) {\n if (!Arr.isFixedLengthArray(1, typeArguments)) {\n throw new Error(\n `Unexpected number of type arguments \"${typeArguments.length}\" for Readonly.`,\n );\n }\n\n // Recursive processing\n transformNode(\n typeArguments[0],\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'DeepReadonly',\n }),\n options,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const T = node.getTypeArguments()[0]!;\n\n // DeepReadonly<DeepReadonly<T>> -> DeepReadonly<T>\n if (readonlyContext.type === 'DeepReadonly') {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // Readonly<number> -> number\n if (isAtomicTypeNode(T)) {\n options.replaceNode(node, T.getFullText());\n\n return;\n }\n\n // T = P[]\n // DeepReadonly<P[]> -> readonly P[] (for primitive type arrays, convert to readonly P[] form)\n // DeepReadonly<O[]> -> DeepReadonly<O[]> (for object type arrays, keep as is to recursively apply Readonly)\n // DeepReadonly<P[][]> -> DeepReadonly<P[][]>\n if (\n T.isKind(tsm.SyntaxKind.ArrayType) &&\n isAtomicTypeNode(T.getElementTypeNode())\n ) {\n const readonlyText = `readonly ${T.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n\n return;\n }\n\n // T = [P1, P2, P3]\n // DeepReadonly<[P1, P2, P3]> -> readonly [P1, P2, P3]\n if (\n T.isKind(tsm.SyntaxKind.TupleType) &&\n T.getElements().every(isAtomicTypeNode)\n ) {\n const readonlyText = `readonly ${T.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n\n return;\n }\n\n return;\n }\n\n {\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const t of node.getTypeArguments()) {\n transformNode(t, nextReadonlyContextValue, options);\n }\n }\n};\n\n/** Renders a readonly `Record<K, V>` in the configured record style. */\nconst readonlyRecordText = (\n keyText: string,\n valueText: string,\n options: ReadonlyTransformerOptionsInternal,\n): string =>\n options.recordStyle === 'ReadonlyRecord'\n ? (`ReadonlyRecord<${keyText}, ${valueText}>` as const)\n : (`Readonly<Record<${keyText}, ${valueText}>>` as const);\n\n/** `tr(E[]) |-> tr(E)[]` */\nconst transformArrayTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.ArrayTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getElementTypeNode(),\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n switch (readonlyContext.type) {\n case 'DeepReadonly':\n case 'readonly':\n return; // remain tr(E)[] as is\n\n // Unnecessary `Readonly` wrapper will be remove in transformTypeReferenceNode\n case 'Readonly':\n case 'none':\n // Skip the `A[] extends B[] ? ...` union-distribution-guard idiom: adding\n // `readonly` there does not improve immutability and breaks the idiom.\n if (\n readonlyContext.indexedAccessDepth === 0 &&\n !isConditionalTypeDistributionGuard(node)\n ) {\n const readonlyText = `readonly ${node.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n }\n }\n};\n\n/** `tr([E1, E2, E3])` |-> `[tr(E1), tr(E2), tr(E3)]` */\nconst transformTupleTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TupleTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n {\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n });\n\n for (const el of node.getElements()) {\n if (el.isKind(tsm.SyntaxKind.NamedTupleMember)) {\n if (options.ignoredPrefixes.every((p) => !el.getName().startsWith(p))) {\n transformNode(el.getTypeNode(), nextReadonlyContextValue, options);\n }\n } else {\n transformNode(el, nextReadonlyContextValue, options);\n }\n }\n }\n\n switch (readonlyContext.type) {\n case 'DeepReadonly':\n case 'readonly':\n return; // remain tr(E)[] as is\n\n // Unnecessary `Readonly` wrapper will be remove in transformTypeReferenceNode\n case 'Readonly':\n case 'none':\n // Skip the `[A] extends [B] ? ...` union-distribution-guard idiom: adding\n // `readonly` there does not improve immutability and breaks the idiom.\n if (\n readonlyContext.indexedAccessDepth === 0 &&\n !isConditionalTypeDistributionGuard(node)\n ) {\n const readonlyText = `readonly ${node.getFullText()}` as const;\n\n options.replaceNode(\n node,\n shouldAvoidParenthesesForReadonly(node)\n ? readonlyText\n : wrapWithParentheses(readonlyText),\n );\n }\n }\n};\n\n/** `tr(\"...T\")` |-> `...tr(T)` */\nconst transformRestTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.RestTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getTypeNode() /* = T */,\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n const R = removeParentheses(node.getTypeNode());\n\n // `tr(\"...readonly E[]\") |-> ...tr(E)[]`\n // `tr(\"...readonly [E1, E2]\") |-> ...[tr(E1), tr(E2)]`\n if (isReadonlyArrayTypeNode(R) || isReadonlyTupleTypeNode(R)) {\n options.replaceNode(\n node,\n `...${R.getTypeNode().getFullText()}` /* = tr(E)[] or [tr(E1), tr(E2)] */,\n );\n }\n};\n\n/**\n * - `readonly T[][] |-> readonly (readonly T[])[]`\n * - `keyof { a: number[] } |-> keyof Readonly<{ a: readonly number[] }>`\n */\nconst transformTypeOperatorNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TypeOperatorTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getTypeNode(),\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType:\n node.getOperator() === tsm.SyntaxKind.ReadonlyKeyword\n ? 'readonly'\n : 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n switch (readonlyContext.type) {\n // DeepReadonly<readonly E[]> -> DeepReadonly<E[]>\n case 'DeepReadonly':\n options.replaceNode(node, node.getTypeNode().getFullText());\n\n return;\n\n case 'Readonly':\n case 'none':\n if (readonlyContext.indexedAccessDepth > 0) {\n options.replaceNode(node, node.getTypeNode().getFullText());\n }\n }\n};\n\n// `{ readonly member: V } |-> Readonly<{ member: V }>`\nconst transformTypeLiteralNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.TypeLiteralNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (options.ignoreEmptyObjectTypes && Arr.isEmpty(node.getMembers())) {\n return;\n }\n\n // Recursive processing\n transformMembers(\n node.getMembers(),\n 'remove',\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n\n switch (readonlyContext.type) {\n case 'DeepReadonly':\n case 'Readonly':\n // Don't wrap with Readonly if already readonly\n return;\n\n case 'none': {\n if (readonlyContext.indexedAccessDepth === 0) {\n // `{ readonly x: X, readonly y: Y } |-> Readonly<{ x: X, y: Y }>`\n options.replaceNode(node, `Readonly<${node.getFullText()}>`);\n }\n }\n }\n};\n\n/** `tr([A, B, C][I])` |-> `[tr(A), tr(B), tr(C)][I]` */\nconst transformIndexedAccessTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IndexedAccessTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n // Recursive processing\n transformNode(\n node.getObjectTypeNode(),\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'incr',\n }),\n options,\n );\n\n transformNode(\n node.getIndexTypeNode() /* = I */,\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'Readonly',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n};\n\n/**\n * - `{ [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n * - `{ -readonly [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n * - `{ readonly [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n * - `{ +readonly [key in Obj]: V }` -> `Readonly<{ [key in Obj]: V }>`\n */\nconst transformMappedTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.MappedTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n const typeNode = node.getTypeNode();\n\n if (typeNode !== undefined) {\n transformNode(\n typeNode,\n nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'decr',\n }),\n options,\n );\n }\n\n const questionTokenText =\n pipe(node.getQuestionToken()?.getText()).mapNullable((t) =>\n t === '?' ? '?' : t === '-' ? '-?' : t === '+' ? '+?' : undefined,\n ).value ?? '';\n\n // Key remapping (`as` clause). It is part of the key set the mapped type\n // produces, so dropping it would silently change the type.\n const nameTypeText = pipe(node.getNameTypeNode()?.getFullText()).mapNullable(\n (t) => ` as ${t.trim()}`,\n ).value;\n\n const result: string = pipe(\n // remove readonlyToken\n `{ [${node.getTypeParameter().getFullText()}${nameTypeText ?? ''}]${questionTokenText}: ${node.getTypeNode()?.getFullText()} }`,\n ).map((mpt) =>\n match(readonlyContext.type, {\n // Don't wrap with Readonly if already readonly or unnecessary\n DeepReadonly: mpt,\n Readonly: mpt,\n none: readonlyContext.indexedAccessDepth > 0 ? mpt : `Readonly<${mpt}>`,\n }),\n ).value;\n\n options.replaceNode(node, result);\n};\n\n// Making interface members readonly\nconst transformInterfaceDeclarationNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.InterfaceDeclaration,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n for (const param of node.getTypeParameters()) {\n transformNode(param, initialReadonlyContext, options);\n }\n\n for (const n of node.getHeritageClauses()) {\n transformNode(n, initialReadonlyContext, options);\n }\n\n transformMembers(node.getMembers(), 'add', initialReadonlyContext, options);\n};\n\nconst transformClassDeclarationNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.ClassDeclaration,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n for (const n of node.getTypeParameters()) {\n transformNode(n, initialReadonlyContext, options);\n }\n\n for (const n of node.getHeritageClauses()) {\n transformNode(n, initialReadonlyContext, options);\n }\n\n for (const mb of node.getMembers()) {\n if (hasDisableNextLineComment(mb)) {\n options.debugPrint('skipped member by disable-next-line comment');\n\n continue;\n }\n\n if (mb.isKind(tsm.SyntaxKind.PropertyDeclaration)) {\n if (!checkIfPropertyNameShouldBeIgnored(mb.getNameNode(), options)) {\n mb.setIsReadonly(true);\n\n const type = mb.getTypeNode();\n\n if (type !== undefined) {\n transformNode(type, initialReadonlyContext, options);\n }\n\n const initializer = mb.getInitializer();\n\n if (initializer !== undefined) {\n transformNode(initializer, initialReadonlyContext, options);\n }\n }\n\n continue;\n }\n\n // MethodDeclaration, GetAccessorDeclaration, SetAccessorDeclaration\n // Check if method name has ignored prefix (e.g., mut_)\n if (\n (mb.isKind(tsm.SyntaxKind.MethodDeclaration) ||\n mb.isKind(tsm.SyntaxKind.GetAccessor) ||\n mb.isKind(tsm.SyntaxKind.SetAccessor)) &&\n checkIfPropertyNameShouldBeIgnored(mb.getNameNode(), options)\n ) {\n options.debugPrint('skipped method by ignored prefix');\n\n continue;\n }\n\n transformNode(mb, initialReadonlyContext, options);\n }\n\n for (const mb of node.getChildrenOfKind(tsm.SyntaxKind.IndexSignature)) {\n transformIndexSignatureDeclaration(\n mb,\n 'add',\n initialReadonlyContext,\n options,\n );\n }\n\n for (const ctor of node.getConstructors()) {\n for (const param of ctor.getParameters()) {\n transformConstructorParameter(param, options);\n }\n\n const body = ctor.getBody();\n\n if (body !== undefined) {\n transformNode(body, initialReadonlyContext, options);\n }\n }\n};\n\nconst transformConstructorParameter = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n param: tsm.ParameterDeclaration,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (hasDisableNextLineComment(param)) {\n options.debugPrint(\n 'skipped class constructor parameter by disable-next-line comment',\n );\n\n return;\n }\n\n const name = param.getName();\n\n if (options.ignoredPrefixes.some((p) => name.startsWith(p))) {\n return;\n }\n\n // Check if parameter is a property declaration (public/protected/private)\n const scope = param.getScope();\n\n // public -> public readonly\n // protected -> protected readonly\n // private -> private readonly\n if (\n scope === tsm.Scope.Public ||\n scope === tsm.Scope.Protected ||\n scope === tsm.Scope.Private\n ) {\n param.setIsReadonly(true);\n }\n\n const type = param.getTypeNode();\n\n if (type !== undefined) {\n transformNode(type, initialReadonlyContext, options);\n }\n};\n\n/**\n * - `tr(A & B) -> tr(A) & tr(B)`\n * - `tr(Readonly<A> & Readonly<B>) -> Readonly<tr(A) & tr(B)>`\n */\nconst transformIntersectionTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IntersectionTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n transformUnionOrIntersectionTypeNodeImpl(node, readonlyContext, options, '&');\n};\n\n/**\n * - `tr(A | B) |-> tr(A) | tr(B)`\n * - `tr(Readonly<A> | Readonly<B>) |-> Readonly<tr(A) | tr(B)>`\n */\nconst transformUnionTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.UnionTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n transformUnionOrIntersectionTypeNodeImpl(node, readonlyContext, options, '|');\n};\n\nconst transformUnionOrIntersectionTypeNodeImpl = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IntersectionTypeNode | tsm.UnionTypeNode,\n readonlyContext: StrictExclude<\n ReadonlyContext,\n Readonly<{ type: 'readonly'; indexedAccessDepth: SafeUintWithSmallInt }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n operator: '&' | '|',\n): void => {\n const nextReadonlyContextValue = nextReadonlyContext({\n currentReadonlyContext: readonlyContext,\n nextReadonlyContextType: 'none',\n indexedAccessDepthChange: 'keep',\n });\n\n // Recursive processing\n for (const n of node.getTypeNodes() /* = [A, B] */) {\n transformNode(n, nextReadonlyContextValue, options);\n }\n\n const newTypes = node.getTypeNodes();\n\n const { primitives, arraysAndTuples, typeLiterals, others } =\n groupUnionIntersectionTypes(newTypes);\n\n options.debugPrint({ primitives, arraysAndTuples, typeLiterals, others });\n\n // Separate empty type literals from non-empty ones when ignoreEmptyObjectTypes is true\n const isEmptyTypeLiteral = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n n: tsm.TypeLiteralNode | ReadonlyTypeReferenceNode,\n ): boolean =>\n n.isKind(tsm.SyntaxKind.TypeLiteral) && Arr.isEmpty(n.getMembers());\n\n const nonEmptyTypeLiterals =\n typeLiterals === undefined\n ? undefined\n : options.ignoreEmptyObjectTypes\n ? typeLiterals.nodes.filter((n) => !isEmptyTypeLiteral(n))\n : typeLiterals.nodes;\n\n const emptyTypeLiterals =\n typeLiterals === undefined || !options.ignoreEmptyObjectTypes\n ? undefined\n : typeLiterals.nodes.filter(isEmptyTypeLiteral);\n\n const typeLiteralsWrappedWithReadonly: readonly [] | readonly [string] =\n nonEmptyTypeLiterals === undefined || Arr.isEmpty(nonEmptyTypeLiterals)\n ? ([] as const)\n : ([\n unionToString({\n types: nonEmptyTypeLiterals.map((n) =>\n isReadonlyTypeReferenceNode(n)\n ? // NOTE: Readonly<A & B> -> (A & B)\n unwrapReadonlyTypeArgText(n)\n : (n satisfies tsm.TypeLiteralNode).getFullText(),\n ),\n op: operator,\n wrapWithReadonly:\n nextReadonlyContextValue.type !== 'DeepReadonly' &&\n nextReadonlyContextValue.indexedAccessDepth === 0,\n }),\n ] as const);\n\n // Sort by first occurrence (preserving the original union order as much as possible)\n const sorted: readonly string[] = [\n mapNullable(\n primitives,\n (a) => [a.nodes.map((n) => n.getFullText()), a.firstPosition] as const,\n ),\n mapNullable(\n arraysAndTuples,\n (a) => [a.nodes.map((n) => n.getFullText()), a.firstPosition] as const,\n ),\n nonEmptyTypeLiterals !== undefined && Arr.isNonEmpty(nonEmptyTypeLiterals)\n ? mapNullable(\n typeLiterals,\n (a) => [typeLiteralsWrappedWithReadonly, a.firstPosition] as const,\n )\n : undefined,\n emptyTypeLiterals !== undefined && Arr.isNonEmpty(emptyTypeLiterals)\n ? mapNullable(\n typeLiterals,\n (a) =>\n [\n emptyTypeLiterals.map((n) => n.getFullText()),\n // Use a position after non-empty type literals if they exist\n a.firstPosition +\n (nonEmptyTypeLiterals !== undefined &&\n Arr.isNonEmpty(nonEmptyTypeLiterals)\n ? 0.5\n : 0),\n ] as const,\n )\n : undefined,\n mapNullable(\n others,\n (a) =>\n [\n a.nodes.map((n) => wrapWithParentheses(n.getFullText())),\n a.firstPosition,\n ] as const,\n ),\n ]\n .filter((x) => x !== undefined)\n .toSorted((a, b) => a[1] - b[1])\n .flatMap((a) => a[0]);\n\n // Readonly<number & { x: X } & { y: Y } & readonly E[]>\n // -> number & readonly E[] & Readonly<{ x: X } & { y: Y }>\n\n // Readonly<number | { x: X } | { y: Y } | readonly E[]>\n // -> number | readonly E[] | Readonly<{ x: X } | { y: Y }>\n // Readonly<number & { x: X } & { y: Y } & readonly E[]>\n // -> number & readonly E[] & Readonly<{ x: X } & { y: Y }>\n\n // Readonly<number | { x: X } | { y: Y } | readonly E[]>\n // -> number | readonly E[] | Readonly<{ x: X } | { y: Y }>\n //\n // NOTE: The result is wrapped in parentheses (via `unionToString`). This is\n // intentional and required for precedence safety: without it, a member such\n // as a function type (`() => T`), or a mix of `&` and `|`, or a `readonly`\n // operator would produce invalid syntax when this node is spliced back in.\n // Idempotency is guaranteed by `transformParenthesizedTypeNode`, which\n // collapses the redundant nesting (`((X))` -> `(X)`) this wrapping can create\n // — see the note there. That prevents the parentheses from growing without\n // bound when a union/intersection sits inside a `ParenthesizedType`.\n options.replaceNode(\n node,\n unionToString({ types: sorted, op: operator, wrapWithReadonly: false }),\n );\n};\n\nconst unionToString = ({\n types,\n op,\n wrapWithReadonly,\n}: Readonly<{\n types: readonly string[];\n op: '&' | '|';\n wrapWithReadonly: boolean | string;\n}>): string =>\n Arr.isEmpty(types)\n ? 'never'\n : Arr.isFixedLengthArray(1, types)\n ? wrapWithReadonly === false\n ? wrapWithParentheses(types[0])\n : (`${isString(wrapWithReadonly) ? wrapWithReadonly : 'Readonly'}<${types[0]}>` as const)\n : wrapWithReadonly === false\n ? wrapWithParentheses(types.join(` ${op} `))\n : (`${isString(wrapWithReadonly) ? wrapWithReadonly : 'Readonly'}<${types.join(` ${op} `)}>` as const);\n\n/** Convert ((T)) -> (T) recursively */\nconst transformParenthesizedTypeNode = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.ParenthesizedTypeNode,\n readonlyContext: ReadonlyContext,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n const typeNode = node.getTypeNode();\n\n if (typeNode.isKind(tsm.SyntaxKind.ParenthesizedType)) {\n // Recursive processing\n transformParenthesizedTypeNode(typeNode, readonlyContext, options);\n }\n\n transformNode(node.getTypeNode(), readonlyContext, options);\n\n const T = node.getTypeNode();\n\n if (\n // remove () if T is TypeReferenceNode\n // e.g. `(Readonly<A>) |-> Readonly<A>`\n T.isKind(tsm.SyntaxKind.TypeReference) ||\n // remove () if T is ArrayTypeNode\n // e.g. `(A[]) |-> A[]`\n T.isKind(tsm.SyntaxKind.ArrayType) ||\n // remove () if T is TupleTypeNode\n // e.g. `([A]) |-> [A]`\n T.isKind(tsm.SyntaxKind.TupleType) ||\n // remove () if T is PrimitiveTypeNode\n // e.g. `(number) |-> number`\n isAtomicTypeNode(T) ||\n // remove () if T is TypeLiteralNode\n // e.g. `({ member: V }) |-> { member: V }`\n T.isKind(tsm.SyntaxKind.TypeLiteral) ||\n // collapse redundant nested parentheses if T is itself a ParenthesizedType\n // e.g. `((X)) |-> (X)`\n //\n // This is what makes the transform terminate on nested parentheses. The\n // union/intersection handler defensively wraps its result in parentheses\n // for precedence safety, which turns `(A | B)` into `((A | B))` when the\n // union already sits inside a `ParenthesizedType`. Collapsing the redundant\n // outer layer here means each pass removes exactly the layer the wrapping\n // added, so the parentheses no longer grow without bound (which previously\n // overflowed the parser stack on inputs like `type T = (('a' | 'b'))`).\n T.isKind(tsm.SyntaxKind.ParenthesizedType)\n ) {\n options.replaceNode(node, T.getFullText());\n }\n};\n\n/**\n * `tr([\"member1: V1\", \"member2: V2\", \"member3: V3\"])`\n *\n * -> `[\"member1: tr(V1)\", \"member2: tr(V2)\", \"member3: tr(V3)\"]`\n */\nconst transformMembers = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n members: readonly tsm.TypeElementTypes[],\n readonlyModifier: 'add' | 'remove',\n readonlyContext: StrictExtract<\n ReadonlyContext,\n Readonly<{\n type: 'DeepReadonly' | 'none';\n indexedAccessDepth: SafeUintWithSmallInt;\n }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n for (const mb of members) {\n if (hasDisableNextLineComment(mb)) {\n options.debugPrint('skipped by member disable-next-line comment');\n\n continue;\n }\n\n if (mb.isKind(tsm.SyntaxKind.PropertySignature)) {\n if (!checkIfPropertyNameShouldBeIgnored(mb.getNameNode(), options)) {\n transformPropertySignature(\n mb,\n readonlyModifier,\n readonlyContext,\n options,\n );\n }\n\n continue;\n }\n\n if (mb.isKind(tsm.SyntaxKind.IndexSignature)) {\n transformIndexSignatureDeclaration(\n mb,\n readonlyModifier,\n readonlyContext,\n options,\n );\n\n continue;\n }\n\n transformNode(mb, readonlyContext, options);\n }\n};\n\nconst transformPropertySignature = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.PropertySignature,\n readonlyModifier: 'add' | 'remove',\n readonlyContext: StrictExtract<\n ReadonlyContext,\n Readonly<{\n type: 'DeepReadonly' | 'none';\n indexedAccessDepth: SafeUintWithSmallInt;\n }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (\n readonlyModifier === 'remove' ||\n readonlyContext.type === 'DeepReadonly'\n ) {\n node.setIsReadonly(false);\n } else {\n node.setIsReadonly(true);\n }\n\n {\n const type = node.getTypeNode();\n\n if (type !== undefined) {\n transformNode(type, readonlyContext, options);\n }\n }\n};\n\nconst transformIndexSignatureDeclaration = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n node: tsm.IndexSignatureDeclaration,\n readonlyModifier: 'add' | 'remove',\n readonlyContext: StrictExtract<\n ReadonlyContext,\n Readonly<{\n type: 'DeepReadonly' | 'none';\n indexedAccessDepth: SafeUintWithSmallInt;\n }>\n >,\n options: ReadonlyTransformerOptionsInternal,\n): void => {\n if (hasDisableNextLineComment(node, TRANSFORMER_NAME)) {\n options.debugPrint('skipped index signature by disable-next-line comment');\n\n return;\n }\n\n if (\n readonlyModifier === 'remove' ||\n readonlyContext.type === 'DeepReadonly'\n ) {\n // node.setIsReadonly(false);\n node.toggleModifier('readonly', false);\n } else {\n node.toggleModifier('readonly', true);\n // node.setIsReadonly(true);\n }\n\n {\n const key = node.getKeyTypeNode();\n\n transformNode(key, readonlyContext, options);\n }\n\n {\n const ret = node.getReturnTypeNode();\n\n if (ret !== undefined) {\n transformNode(ret, readonlyContext, options);\n }\n }\n};\n\nconst checkIfPropertyNameShouldBeIgnored = (\n // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types\n nameNode: tsm.PropertyName,\n options: ReadonlyTransformerOptionsInternal,\n): boolean => {\n expectType<typeof nameNode, tsm.PropertyName>('=');\n\n expectType<\n tsm.PropertyName,\n | tsm.NumericLiteral\n | tsm.BigIntLiteral\n | tsm.NoSubstitutionTemplateLiteral\n | tsm.Identifier\n | tsm.StringLiteral\n | tsm.PrivateIdentifier\n | tsm.ComputedPropertyName // [`mut_x`]: number[]\n >('=');\n\n return (\n // mut_x: number[]\n (nameNode.isKind(tsm.SyntaxKind.Identifier) &&\n pipe(nameNode.getText()).map((nm) =>\n options.ignoredPrefixes.some((p) => nm.startsWith(p)),\n ).value) ||\n // \"mut_x\": number[]\n (nameNode.isKind(tsm.SyntaxKind.StringLiteral) &&\n pipe(nameNode.getLiteralValue()).map((nm) =>\n options.ignoredPrefixes.some((p) => nm.startsWith(p)),\n ).value) ||\n // #memberName: number[] (class only)\n (nameNode.isKind(tsm.SyntaxKind.PrivateIdentifier) &&\n pipe(nameNode.getText()).map((nm) =>\n options.ignoredPrefixes.some((p) => nm.startsWith(`#${p}`)),\n ).value) ||\n // [`mut_x`]: number[]\n (nameNode.isKind(tsm.SyntaxKind.ComputedPropertyName) &&\n pipe(nameNode.getExpression()).map((exp) => {\n if (exp.isKind(tsm.SyntaxKind.StringLiteral)) {\n const nm = exp.getLiteralValue();\n\n return options.ignoredPrefixes.some((p) => nm.startsWith(p));\n }\n\n return false;\n }).value)\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ISet } from 'ts-data-forge';
|
|
2
|
-
export declare const invalidDeepReadonlyTypeName: ISet<"Array" | "Map" | "Readonly" | "ReadonlyArray" | "ReadonlyMap" | "ReadonlySet" | "Set" | "readonly">;
|
|
2
|
+
export declare const invalidDeepReadonlyTypeName: ISet<"Array" | "Map" | "Readonly" | "ReadonlyArray" | "ReadonlyMap" | "ReadonlyRecord" | "ReadonlySet" | "Record" | "Set" | "readonly">;
|
|
3
3
|
//# sourceMappingURL=constants.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../../src/functions/ast-transformers/readonly-transformer-helpers/constants.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../../../src/functions/ast-transformers/readonly-transformer-helpers/constants.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,eAAO,MAAM,2BAA2B,yIAWtC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.mjs","sources":["../../../../src/functions/ast-transformers/readonly-transformer-helpers/constants.mts"],"sourcesContent":["import { ISet } from 'ts-data-forge';\n\nexport const invalidDeepReadonlyTypeName = ISet.create([\n 'Readonly',\n 'readonly',\n 'ReadonlyArray',\n 'Array',\n 'Set',\n 'Map',\n 'ReadonlySet',\n 'ReadonlyMap',\n]);\n"],"names":[],"mappings":";;AAEO,MAAM,2BAAA,GAA8B,KAAK,MAAA,CAAO;AAAA,EACrD,UAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAC;;;;"}
|
|
1
|
+
{"version":3,"file":"constants.mjs","sources":["../../../../src/functions/ast-transformers/readonly-transformer-helpers/constants.mts"],"sourcesContent":["import { ISet } from 'ts-data-forge';\n\nexport const invalidDeepReadonlyTypeName = ISet.create([\n 'Readonly',\n 'readonly',\n 'ReadonlyArray',\n 'Array',\n 'Set',\n 'Map',\n 'ReadonlySet',\n 'ReadonlyMap',\n 'Record',\n 'ReadonlyRecord',\n]);\n"],"names":[],"mappings":";;AAEO,MAAM,2BAAA,GAA8B,KAAK,MAAA,CAAO;AAAA,EACrD,UAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAC;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-codemod-lib",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -38,19 +38,23 @@
|
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
+
"ts-data-forge": "^14.4.0",
|
|
41
42
|
"ts-morph": "^28.0.0",
|
|
42
|
-
"ts-data-forge": "^14.3.0",
|
|
43
43
|
"ts-type-forge": "^9.2.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@types/node": "26.
|
|
46
|
+
"@types/node": "26.3.0",
|
|
47
47
|
"@vitest/browser-playwright": "4.1.10",
|
|
48
48
|
"@vitest/coverage-v8": "4.1.10",
|
|
49
49
|
"@vitest/ui": "4.1.10",
|
|
50
50
|
"cspell": "10.0.1",
|
|
51
51
|
"dedent": "1.7.2",
|
|
52
|
-
"esbuild": "0.28.
|
|
52
|
+
"esbuild": "0.28.2",
|
|
53
53
|
"eslint": "10.8.1",
|
|
54
|
+
"eslint-config-typed": "5.9.5",
|
|
55
|
+
"eslint-plugin-ts-data-forge": "0.4.8",
|
|
56
|
+
"eslint-plugin-ts-fortress": "1.0.4",
|
|
57
|
+
"eslint-plugin-ts-type-forge": "0.6.6",
|
|
54
58
|
"jiti": "2.7.0",
|
|
55
59
|
"npm-run-all2": "9.0.3",
|
|
56
60
|
"playwright": "1.62.1",
|
|
@@ -58,18 +62,14 @@
|
|
|
58
62
|
"prettier-plugin-organize-imports": "4.3.0",
|
|
59
63
|
"prettier-plugin-packagejson": "3.0.2",
|
|
60
64
|
"rollup": "4.62.4",
|
|
61
|
-
"
|
|
65
|
+
"ts-repo-utils": "10.3.1",
|
|
66
|
+
"tsx": "4.23.12",
|
|
62
67
|
"typedoc": "0.28.20",
|
|
63
68
|
"typedoc-github-theme": "0.4.0",
|
|
64
69
|
"typescript": "6.0.3",
|
|
65
70
|
"typescript-native": "npm:typescript@7.0.2",
|
|
66
71
|
"vite": "8.2.1",
|
|
67
|
-
"vitest": "4.1.10"
|
|
68
|
-
"eslint-config-typed": "5.9.2",
|
|
69
|
-
"eslint-plugin-ts-data-forge": "0.4.7",
|
|
70
|
-
"eslint-plugin-ts-fortress": "1.0.3",
|
|
71
|
-
"eslint-plugin-ts-type-forge": "0.6.5",
|
|
72
|
-
"ts-repo-utils": "10.2.0"
|
|
72
|
+
"vitest": "4.1.10"
|
|
73
73
|
},
|
|
74
74
|
"engines": {
|
|
75
75
|
"node": ">=22.22.2",
|
|
@@ -65,6 +65,7 @@ export const convertToReadonlyTransformer = (
|
|
|
65
65
|
},
|
|
66
66
|
ignoreEmptyObjectTypes: options?.ignoreEmptyObjectTypes ?? true,
|
|
67
67
|
ignoredPrefixes: ignorePrefixes,
|
|
68
|
+
recordStyle: options?.recordStyle ?? 'ReadonlyRecord',
|
|
68
69
|
debugPrint: options?.debug === true ? console.debug : () => {},
|
|
69
70
|
replaceNode:
|
|
70
71
|
options?.debug === true
|
|
@@ -137,6 +138,26 @@ export type ReadonlyTransformerOptions = DeepReadonly<{
|
|
|
137
138
|
*/
|
|
138
139
|
ignorePrefixes?: string[];
|
|
139
140
|
|
|
141
|
+
/**
|
|
142
|
+
* The output style used when making `Record<K, V>` readonly.
|
|
143
|
+
*
|
|
144
|
+
* - `"ReadonlyRecord"`: Uses the `ReadonlyRecord` type utility provided by
|
|
145
|
+
* `ts-type-forge` (as the `ts-type-forge/prefer-readonly-or-mutable-record`
|
|
146
|
+
* ESLint rule suggests). Occurrences of `Readonly<Record<K, V>>` are also
|
|
147
|
+
* unified to `ReadonlyRecord<K, V>`. Note that no import statement is
|
|
148
|
+
* added, so `ReadonlyRecord` has to be available in the transformed code
|
|
149
|
+
* (e.g. globally via `ts-type-forge`'s `global.d.mts`).
|
|
150
|
+
* - `"Readonly<Record>"`: Uses only built-in utility types
|
|
151
|
+
* (`Readonly<Record<K, V>>`). Occurrences of `ReadonlyRecord<K, V>` are
|
|
152
|
+
* also unified to `Readonly<Record<K, V>>`.
|
|
153
|
+
*
|
|
154
|
+
* Whichever style is selected, redundant wrappers such as
|
|
155
|
+
* `Readonly<ReadonlyRecord<K, V>>` are normalized to that style as well.
|
|
156
|
+
*
|
|
157
|
+
* @default 'ReadonlyRecord'
|
|
158
|
+
*/
|
|
159
|
+
recordStyle?: 'Readonly<Record>' | 'ReadonlyRecord';
|
|
160
|
+
|
|
140
161
|
debug?: boolean;
|
|
141
162
|
}>;
|
|
142
163
|
|
|
@@ -152,6 +173,8 @@ type ReadonlyTransformerOptionsInternal = Readonly<{
|
|
|
152
173
|
|
|
153
174
|
ignoredPrefixes: ISet<string>;
|
|
154
175
|
|
|
176
|
+
recordStyle: 'Readonly<Record>' | 'ReadonlyRecord';
|
|
177
|
+
|
|
155
178
|
debugPrint: (...args: readonly unknown[]) => void;
|
|
156
179
|
replaceNode: (node: tsm.Node, newNodeText: string) => void;
|
|
157
180
|
}>;
|
|
@@ -398,6 +421,10 @@ const transformNode = (
|
|
|
398
421
|
* - `tr(Readonly<readonly E[]>) |-> readonly tr(E)[]`
|
|
399
422
|
* - `tr(Readonly<readonly [E1, E2, E3]>) |-> readonly [tr(E1), tr(E2), tr(E3)]`
|
|
400
423
|
* - `tr(Readonly<A | readonly E[]>) |-> Readonly<tr(A)> | readonly tr(E)[]>`
|
|
424
|
+
* - `tr(Record<K, V>) |-> Readonly<Record<tr(K), tr(V)>>` (or
|
|
425
|
+
* `ReadonlyRecord<tr(K), tr(V)>`, depending on the `recordStyle` option;
|
|
426
|
+
* `Readonly<Record<K, V>>`, `ReadonlyRecord<K, V>` and
|
|
427
|
+
* `Readonly<ReadonlyRecord<K, V>>` are unified to the same style)
|
|
401
428
|
*/
|
|
402
429
|
const transformTypeReferenceNode = (
|
|
403
430
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
@@ -501,6 +528,112 @@ const transformTypeReferenceNode = (
|
|
|
501
528
|
return;
|
|
502
529
|
}
|
|
503
530
|
|
|
531
|
+
// Record<K, V> to ReadonlyRecord<K, V> / Readonly<Record<K, V>>
|
|
532
|
+
if (typeNameStr === 'Record') {
|
|
533
|
+
if (!Arr.isFixedLengthArray(2, typeArguments)) {
|
|
534
|
+
throw new Error(
|
|
535
|
+
`Unexpected number of type arguments "${typeArguments.length}" for Record.`,
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const nextReadonlyContextValue = nextReadonlyContext({
|
|
540
|
+
currentReadonlyContext: readonlyContext,
|
|
541
|
+
nextReadonlyContextType: 'none',
|
|
542
|
+
indexedAccessDepthChange: 'keep',
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// Recursive processing
|
|
546
|
+
for (const t of typeArguments) {
|
|
547
|
+
transformNode(t, nextReadonlyContextValue, options);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// The bare Record is kept as is in the following cases:
|
|
551
|
+
// - DeepReadonly<Record<K, V>> already applies readonly recursively.
|
|
552
|
+
// - Readonly<Record<K, V>> is unified to the configured record style by
|
|
553
|
+
// the surrounding `Readonly` handler.
|
|
554
|
+
// - Record<K, V>[I] does not need readonly, just like
|
|
555
|
+
// `Readonly<{ ... }>[I] -> { ... }[I]`.
|
|
556
|
+
if (
|
|
557
|
+
readonlyContext.type === 'none' &&
|
|
558
|
+
readonlyContext.indexedAccessDepth === 0
|
|
559
|
+
) {
|
|
560
|
+
const [K, V] = node.getTypeArguments();
|
|
561
|
+
|
|
562
|
+
options.replaceNode(
|
|
563
|
+
node,
|
|
564
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
565
|
+
readonlyRecordText(K!.getFullText(), V!.getFullText(), options),
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Unify ReadonlyRecord<K, V> to the configured record style
|
|
573
|
+
if (typeNameStr === 'ReadonlyRecord') {
|
|
574
|
+
if (!Arr.isFixedLengthArray(2, typeArguments)) {
|
|
575
|
+
throw new Error(
|
|
576
|
+
`Unexpected number of type arguments "${typeArguments.length}" for ReadonlyRecord.`,
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const nextReadonlyContextValue = nextReadonlyContext({
|
|
581
|
+
currentReadonlyContext: readonlyContext,
|
|
582
|
+
nextReadonlyContextType: 'none',
|
|
583
|
+
indexedAccessDepthChange: 'keep',
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
// Recursive processing
|
|
587
|
+
for (const t of typeArguments) {
|
|
588
|
+
transformNode(t, nextReadonlyContextValue, options);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const [K, V] = node.getTypeArguments();
|
|
592
|
+
|
|
593
|
+
const bareRecordText =
|
|
594
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
595
|
+
`Record<${K!.getFullText()}, ${V!.getFullText()}>` as const;
|
|
596
|
+
|
|
597
|
+
// Readonly<ReadonlyRecord<K, V>> -> Readonly<Record<K, V>>
|
|
598
|
+
// (the surrounding `Readonly` handler then unifies it to the configured
|
|
599
|
+
// record style, so the bare Record never survives into the output)
|
|
600
|
+
if (
|
|
601
|
+
readonlyContext.type === 'Readonly' &&
|
|
602
|
+
readonlyContext.indexedAccessDepth === 0
|
|
603
|
+
) {
|
|
604
|
+
options.replaceNode(node, bareRecordText);
|
|
605
|
+
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (options.recordStyle === 'Readonly<Record>') {
|
|
610
|
+
// The ReadonlyRecord name is eliminated everywhere:
|
|
611
|
+
// - DeepReadonly<ReadonlyRecord<K, V>> -> DeepReadonly<Record<K, V>>
|
|
612
|
+
// - ReadonlyRecord<K, V>[I] -> Record<K, V>[I]
|
|
613
|
+
// (readonly is unnecessary under indexed access, as with
|
|
614
|
+
// Readonly<{ ... }>[I] -> { ... }[I])
|
|
615
|
+
if (
|
|
616
|
+
readonlyContext.type !== 'none' ||
|
|
617
|
+
readonlyContext.indexedAccessDepth > 0
|
|
618
|
+
) {
|
|
619
|
+
options.replaceNode(node, bareRecordText);
|
|
620
|
+
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
options.replaceNode(node, `Readonly<${bareRecordText}>`);
|
|
625
|
+
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// With `recordStyle: "ReadonlyRecord"`, ReadonlyRecord is already the
|
|
630
|
+
// configured style. It is deliberately kept even under DeepReadonly or an
|
|
631
|
+
// indexed access — stripping it to the bare built-in `Record` there would
|
|
632
|
+
// conflict with the `ts-type-forge/prefer-readonly-or-mutable-record`
|
|
633
|
+
// ESLint rule.
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
|
|
504
637
|
// remove unnecessary `Readonly` wrapper or convert to readonly operator
|
|
505
638
|
if (typeNameStr === 'Readonly') {
|
|
506
639
|
if (!Arr.isFixedLengthArray(1, typeArguments)) {
|
|
@@ -551,6 +684,28 @@ const transformTypeReferenceNode = (
|
|
|
551
684
|
return;
|
|
552
685
|
}
|
|
553
686
|
|
|
687
|
+
// Readonly<Record<K, V>> -> the configured record style
|
|
688
|
+
// (`ReadonlyRecord<K, V>` or `Readonly<Record<K, V>>` as is)
|
|
689
|
+
if (
|
|
690
|
+
T.isKind(tsm.SyntaxKind.TypeReference) &&
|
|
691
|
+
T.getTypeName().getText() === 'Record'
|
|
692
|
+
) {
|
|
693
|
+
const recordTypeArguments = T.getTypeArguments();
|
|
694
|
+
|
|
695
|
+
if (Arr.isFixedLengthArray(2, recordTypeArguments)) {
|
|
696
|
+
options.replaceNode(
|
|
697
|
+
node,
|
|
698
|
+
readonlyRecordText(
|
|
699
|
+
recordTypeArguments[0].getFullText(),
|
|
700
|
+
recordTypeArguments[1].getFullText(),
|
|
701
|
+
options,
|
|
702
|
+
),
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
554
709
|
// T = E[]
|
|
555
710
|
// Readonly<E[]> -> readonly E[]
|
|
556
711
|
//
|
|
@@ -685,6 +840,16 @@ const transformTypeReferenceNode = (
|
|
|
685
840
|
}
|
|
686
841
|
};
|
|
687
842
|
|
|
843
|
+
/** Renders a readonly `Record<K, V>` in the configured record style. */
|
|
844
|
+
const readonlyRecordText = (
|
|
845
|
+
keyText: string,
|
|
846
|
+
valueText: string,
|
|
847
|
+
options: ReadonlyTransformerOptionsInternal,
|
|
848
|
+
): string =>
|
|
849
|
+
options.recordStyle === 'ReadonlyRecord'
|
|
850
|
+
? (`ReadonlyRecord<${keyText}, ${valueText}>` as const)
|
|
851
|
+
: (`Readonly<Record<${keyText}, ${valueText}>>` as const);
|
|
852
|
+
|
|
688
853
|
/** `tr(E[]) |-> tr(E)[]` */
|
|
689
854
|
const transformArrayTypeNode = (
|
|
690
855
|
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// cspell:ignore klass
|
|
2
|
+
|
|
1
3
|
/* eslint-disable tree-shakable/import-star */
|
|
2
4
|
/* eslint-disable vitest/expect-expect */
|
|
3
5
|
import dedent from 'dedent';
|
|
@@ -208,6 +210,239 @@ describe(convertToReadonlyTransformer, () => {
|
|
|
208
210
|
])('$name', testFn);
|
|
209
211
|
});
|
|
210
212
|
|
|
213
|
+
describe('Records', () => {
|
|
214
|
+
describe('recordStyle: "ReadonlyRecord" (default)', () => {
|
|
215
|
+
test.each([
|
|
216
|
+
{
|
|
217
|
+
name: 'Type alias',
|
|
218
|
+
source: dedent`
|
|
219
|
+
type Foo = Record<string, number>
|
|
220
|
+
`,
|
|
221
|
+
expected: dedent`
|
|
222
|
+
type Foo = ReadonlyRecord<string, number>
|
|
223
|
+
`,
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: 'ReadonlyRecord<K, V> is unchanged',
|
|
227
|
+
source: dedent`
|
|
228
|
+
type Foo = ReadonlyRecord<string, number>
|
|
229
|
+
`,
|
|
230
|
+
expected: dedent`
|
|
231
|
+
type Foo = ReadonlyRecord<string, number>
|
|
232
|
+
`,
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
name: 'Readonly<Record<K, V>> is unified to ReadonlyRecord<K, V>',
|
|
236
|
+
source: dedent`
|
|
237
|
+
type Foo = Readonly<Record<string, number>>
|
|
238
|
+
`,
|
|
239
|
+
expected: dedent`
|
|
240
|
+
type Foo = ReadonlyRecord<string, number>
|
|
241
|
+
`,
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: 'Redundant Readonly<ReadonlyRecord<K, V>> is normalized',
|
|
245
|
+
source: dedent`
|
|
246
|
+
type Foo = Readonly<ReadonlyRecord<string, number>>
|
|
247
|
+
`,
|
|
248
|
+
expected: dedent`
|
|
249
|
+
type Foo = ReadonlyRecord<string, number>
|
|
250
|
+
`,
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'Value type is converted recursively',
|
|
254
|
+
source: dedent`
|
|
255
|
+
type Foo = Record<string, number[]>
|
|
256
|
+
`,
|
|
257
|
+
expected: dedent`
|
|
258
|
+
type Foo = ReadonlyRecord<string, readonly number[]>
|
|
259
|
+
`,
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
name: 'Value type inside Readonly<Record<K, V>> is converted recursively',
|
|
263
|
+
source: dedent`
|
|
264
|
+
type Foo = Readonly<Record<string, number[]>>
|
|
265
|
+
`,
|
|
266
|
+
expected: dedent`
|
|
267
|
+
type Foo = ReadonlyRecord<string, readonly number[]>
|
|
268
|
+
`,
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
name: 'Value type inside ReadonlyRecord<K, V> is converted recursively',
|
|
272
|
+
source: dedent`
|
|
273
|
+
type Foo = ReadonlyRecord<string, number[]>
|
|
274
|
+
`,
|
|
275
|
+
expected: dedent`
|
|
276
|
+
type Foo = ReadonlyRecord<string, readonly number[]>
|
|
277
|
+
`,
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
name: 'In type literal member',
|
|
281
|
+
source: dedent`
|
|
282
|
+
type Foo = { a: Record<string, number> }
|
|
283
|
+
`,
|
|
284
|
+
expected: dedent`
|
|
285
|
+
type Foo = Readonly<{ a: ReadonlyRecord<string, number> }>
|
|
286
|
+
`,
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: 'In function args',
|
|
290
|
+
source: dedent`
|
|
291
|
+
function foo(a: Record<string, number>, b: Promise<Record<string, number>>) {}
|
|
292
|
+
`,
|
|
293
|
+
expected: dedent`
|
|
294
|
+
function foo(a: ReadonlyRecord<string, number>, b: Promise<ReadonlyRecord<string, number>>) {}
|
|
295
|
+
`,
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
name: 'DeepReadonly<Record<K, V>> is unchanged',
|
|
299
|
+
source: dedent`
|
|
300
|
+
type Foo = DeepReadonly<Record<string, number[]>>
|
|
301
|
+
`,
|
|
302
|
+
expected: dedent`
|
|
303
|
+
type Foo = DeepReadonly<Record<string, number[]>>
|
|
304
|
+
`,
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
name: 'DeepReadonly<ReadonlyRecord<K, V>> is unchanged',
|
|
308
|
+
source: dedent`
|
|
309
|
+
type Foo = DeepReadonly<ReadonlyRecord<string, number>>
|
|
310
|
+
`,
|
|
311
|
+
expected: dedent`
|
|
312
|
+
type Foo = DeepReadonly<ReadonlyRecord<string, number>>
|
|
313
|
+
`,
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
name: 'Record<K, V> under indexed access is kept as is',
|
|
317
|
+
source: dedent`
|
|
318
|
+
type Foo = Record<string, number>[string]
|
|
319
|
+
`,
|
|
320
|
+
expected: dedent`
|
|
321
|
+
type Foo = Record<string, number>[string]
|
|
322
|
+
`,
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
name: 'ReadonlyRecord<K, V> under indexed access is unchanged',
|
|
326
|
+
source: dedent`
|
|
327
|
+
type Foo = ReadonlyRecord<string, number>[string]
|
|
328
|
+
`,
|
|
329
|
+
expected: dedent`
|
|
330
|
+
type Foo = ReadonlyRecord<string, number>[string]
|
|
331
|
+
`,
|
|
332
|
+
},
|
|
333
|
+
])('$name', testFn);
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
describe('recordStyle: "Readonly<Record>"', () => {
|
|
337
|
+
const options = {
|
|
338
|
+
recordStyle: 'Readonly<Record>',
|
|
339
|
+
} as const satisfies ReadonlyTransformerOptions;
|
|
340
|
+
|
|
341
|
+
test.each([
|
|
342
|
+
{
|
|
343
|
+
name: 'Type alias',
|
|
344
|
+
source: dedent`
|
|
345
|
+
type Foo = Record<string, number>
|
|
346
|
+
`,
|
|
347
|
+
expected: dedent`
|
|
348
|
+
type Foo = Readonly<Record<string, number>>
|
|
349
|
+
`,
|
|
350
|
+
options,
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
name: 'Readonly<Record<K, V>> is unchanged',
|
|
354
|
+
source: dedent`
|
|
355
|
+
type Foo = Readonly<Record<string, number>>
|
|
356
|
+
`,
|
|
357
|
+
expected: dedent`
|
|
358
|
+
type Foo = Readonly<Record<string, number>>
|
|
359
|
+
`,
|
|
360
|
+
options,
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
name: 'ReadonlyRecord<K, V> is unified to Readonly<Record<K, V>>',
|
|
364
|
+
source: dedent`
|
|
365
|
+
type Foo = ReadonlyRecord<string, number>
|
|
366
|
+
`,
|
|
367
|
+
expected: dedent`
|
|
368
|
+
type Foo = Readonly<Record<string, number>>
|
|
369
|
+
`,
|
|
370
|
+
options,
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
name: 'Redundant Readonly<ReadonlyRecord<K, V>> is normalized',
|
|
374
|
+
source: dedent`
|
|
375
|
+
type Foo = Readonly<ReadonlyRecord<string, number>>
|
|
376
|
+
`,
|
|
377
|
+
expected: dedent`
|
|
378
|
+
type Foo = Readonly<Record<string, number>>
|
|
379
|
+
`,
|
|
380
|
+
options,
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
name: 'Value type is converted recursively',
|
|
384
|
+
source: dedent`
|
|
385
|
+
type Foo = Record<string, string[]>
|
|
386
|
+
`,
|
|
387
|
+
expected: dedent`
|
|
388
|
+
type Foo = Readonly<Record<string, readonly string[]>>
|
|
389
|
+
`,
|
|
390
|
+
options,
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
name: 'Value type inside Readonly<Record<K, V>> is converted recursively',
|
|
394
|
+
source: dedent`
|
|
395
|
+
type Foo = Readonly<Record<string, number[]>>
|
|
396
|
+
`,
|
|
397
|
+
expected: dedent`
|
|
398
|
+
type Foo = Readonly<Record<string, readonly number[]>>
|
|
399
|
+
`,
|
|
400
|
+
options,
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: 'In type literal member',
|
|
404
|
+
source: dedent`
|
|
405
|
+
type Foo = { a: Record<string, number> }
|
|
406
|
+
`,
|
|
407
|
+
expected: dedent`
|
|
408
|
+
type Foo = Readonly<{ a: Readonly<Record<string, number>> }>
|
|
409
|
+
`,
|
|
410
|
+
options,
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
name: 'DeepReadonly<Record<K, V>> is unchanged',
|
|
414
|
+
source: dedent`
|
|
415
|
+
type Foo = DeepReadonly<Record<string, number[]>>
|
|
416
|
+
`,
|
|
417
|
+
expected: dedent`
|
|
418
|
+
type Foo = DeepReadonly<Record<string, number[]>>
|
|
419
|
+
`,
|
|
420
|
+
options,
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
name: 'DeepReadonly<ReadonlyRecord<K, V>> -> DeepReadonly<Record<K, V>>',
|
|
424
|
+
source: dedent`
|
|
425
|
+
type Foo = DeepReadonly<ReadonlyRecord<string, number>>
|
|
426
|
+
`,
|
|
427
|
+
expected: dedent`
|
|
428
|
+
type Foo = DeepReadonly<Record<string, number>>
|
|
429
|
+
`,
|
|
430
|
+
options,
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
name: 'ReadonlyRecord<K, V> under indexed access -> Record<K, V>',
|
|
434
|
+
source: dedent`
|
|
435
|
+
type Foo = ReadonlyRecord<string, number>[string]
|
|
436
|
+
`,
|
|
437
|
+
expected: dedent`
|
|
438
|
+
type Foo = Record<string, number>[string]
|
|
439
|
+
`,
|
|
440
|
+
options,
|
|
441
|
+
},
|
|
442
|
+
])('$name', testFn);
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
|
|
211
446
|
describe('Normalize `Readonly` wrappers', () => {
|
|
212
447
|
test.each([
|
|
213
448
|
{
|