ts-codemod-lib 2.2.0 → 2.2.2
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/dist/cmd/append-as-const.mjs +51 -48
- package/dist/cmd/append-as-const.mjs.map +1 -1
- package/dist/cmd/convert-interface-to-type.mjs +51 -48
- package/dist/cmd/convert-interface-to-type.mjs.map +1 -1
- package/dist/cmd/convert-to-readonly.mjs +51 -48
- package/dist/cmd/convert-to-readonly.mjs.map +1 -1
- package/dist/cmd/replace-any-with-unknown.mjs +51 -48
- package/dist/cmd/replace-any-with-unknown.mjs.map +1 -1
- package/dist/cmd/replace-record-with-unknown-record.mjs +51 -48
- package/dist/cmd/replace-record-with-unknown-record.mjs.map +1 -1
- package/dist/cmd/run-transformer-cli.d.mts.map +1 -1
- package/dist/cmd/run-transformer-cli.mjs +138 -127
- package/dist/cmd/run-transformer-cli.mjs.map +1 -1
- package/dist/entry-point.mjs +1 -0
- package/dist/entry-point.mjs.map +1 -1
- package/dist/functions/ast-transformers/append-as-const.d.mts.map +1 -1
- package/dist/functions/ast-transformers/append-as-const.mjs +205 -191
- package/dist/functions/ast-transformers/append-as-const.mjs.map +1 -1
- package/dist/functions/ast-transformers/convert-interface-to-type.mjs +62 -82
- package/dist/functions/ast-transformers/convert-interface-to-type.mjs.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.d.mts.map +1 -1
- package/dist/functions/ast-transformers/convert-to-readonly.mjs +743 -828
- package/dist/functions/ast-transformers/convert-to-readonly.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/compare-union-types.d.mts.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/compare-union-types.mjs +2 -14
- package/dist/functions/ast-transformers/readonly-transformer-helpers/compare-union-types.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/constants.d.mts +2 -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 +8 -8
- package/dist/functions/ast-transformers/readonly-transformer-helpers/constants.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/group-union-types.d.mts.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/group-union-types.mjs +51 -62
- package/dist/functions/ast-transformers/readonly-transformer-helpers/group-union-types.mjs.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/readonly-context.d.mts +12 -12
- package/dist/functions/ast-transformers/readonly-transformer-helpers/readonly-context.d.mts.map +1 -1
- package/dist/functions/ast-transformers/readonly-transformer-helpers/readonly-context.mjs +16 -14
- package/dist/functions/ast-transformers/readonly-transformer-helpers/readonly-context.mjs.map +1 -1
- package/dist/functions/ast-transformers/replace-any-with-unknown.mjs +25 -27
- package/dist/functions/ast-transformers/replace-any-with-unknown.mjs.map +1 -1
- package/dist/functions/ast-transformers/replace-record-with-unknown-record.mjs +149 -208
- package/dist/functions/ast-transformers/replace-record-with-unknown-record.mjs.map +1 -1
- package/dist/functions/ast-transformers/transform-source-code.d.mts.map +1 -1
- package/dist/functions/ast-transformers/transform-source-code.mjs +70 -72
- package/dist/functions/ast-transformers/transform-source-code.mjs.map +1 -1
- package/dist/functions/constants/ignore-comment-text.d.mts +2 -2
- package/dist/functions/constants/ignore-comment-text.d.mts.map +1 -1
- package/dist/functions/constants/ignore-comment-text.mjs +8 -8
- package/dist/functions/constants/ignore-comment-text.mjs.map +1 -1
- package/dist/functions/functions/has-disable-next-line-comment.d.mts.map +1 -1
- package/dist/functions/functions/has-disable-next-line-comment.mjs +33 -65
- package/dist/functions/functions/has-disable-next-line-comment.mjs.map +1 -1
- package/dist/functions/functions/index.d.mts +1 -0
- package/dist/functions/functions/index.d.mts.map +1 -1
- package/dist/functions/functions/index.mjs +1 -0
- package/dist/functions/functions/index.mjs.map +1 -1
- package/dist/functions/functions/is-as-const-node.d.mts +1 -1
- package/dist/functions/functions/is-as-const-node.d.mts.map +1 -1
- package/dist/functions/functions/is-as-const-node.mjs +15 -23
- package/dist/functions/functions/is-as-const-node.mjs.map +1 -1
- package/dist/functions/functions/is-atomic-type-node.d.mts.map +1 -1
- package/dist/functions/functions/is-atomic-type-node.mjs +22 -36
- package/dist/functions/functions/is-atomic-type-node.mjs.map +1 -1
- package/dist/functions/functions/is-conditional-type-distribution-guard.d.mts +23 -0
- package/dist/functions/functions/is-conditional-type-distribution-guard.d.mts.map +1 -0
- package/dist/functions/functions/is-conditional-type-distribution-guard.mjs +16 -0
- package/dist/functions/functions/is-conditional-type-distribution-guard.mjs.map +1 -0
- package/dist/functions/functions/is-readonly-node.d.mts.map +1 -1
- package/dist/functions/functions/is-readonly-node.mjs +11 -21
- package/dist/functions/functions/is-readonly-node.mjs.map +1 -1
- package/dist/functions/functions/is-spread-parameter-node.d.mts.map +1 -1
- package/dist/functions/functions/is-spread-parameter-node.mjs +2 -4
- package/dist/functions/functions/is-spread-parameter-node.mjs.map +1 -1
- package/dist/functions/functions/remove-parentheses.d.mts.map +1 -1
- package/dist/functions/functions/remove-parentheses.mjs +1 -4
- package/dist/functions/functions/remove-parentheses.mjs.map +1 -1
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.d.mts.map +1 -1
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.mjs +7 -24
- package/dist/functions/functions/should-avoid-parentheses-for-readonly.mjs.map +1 -1
- package/dist/functions/functions/unwrap-readonly.d.mts.map +1 -1
- package/dist/functions/functions/unwrap-readonly.mjs +1 -3
- package/dist/functions/functions/unwrap-readonly.mjs.map +1 -1
- package/dist/functions/functions/wrap-with-parentheses.d.mts.map +1 -1
- package/dist/functions/functions/wrap-with-parentheses.mjs +26 -51
- package/dist/functions/functions/wrap-with-parentheses.mjs.map +1 -1
- package/dist/functions/index.mjs +1 -0
- package/dist/functions/index.mjs.map +1 -1
- package/dist/functions/utils/replace-with-debug.d.mts.map +1 -1
- package/dist/functions/utils/replace-with-debug.mjs +2 -2
- package/dist/functions/utils/replace-with-debug.mjs.map +1 -1
- package/dist/index.mjs +1 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +32 -31
- package/src/cmd/append-as-const.mts +3 -3
- package/src/cmd/convert-interface-to-type.mts +3 -3
- package/src/cmd/convert-to-readonly.mts +3 -3
- package/src/cmd/replace-any-with-unknown.mts +3 -3
- package/src/cmd/replace-record-with-unknown-record.mts +3 -3
- package/src/cmd/run-transformer-cli.mts +21 -17
- package/src/functions/ast-transformers/convert-interface-to-type.mts +1 -1
- package/src/functions/ast-transformers/convert-to-readonly.mts +77 -37
- package/src/functions/ast-transformers/convert-to-readonly.test.mts +117 -1
- package/src/functions/ast-transformers/readonly-transformer-helpers/readonly-context.mts +6 -6
- package/src/functions/ast-transformers/replace-record-with-unknown-record.mts +4 -4
- package/src/functions/functions/has-disable-next-line-comment.mts +5 -5
- package/src/functions/functions/index.mts +1 -0
- package/src/functions/functions/is-conditional-type-distribution-guard.mts +45 -0
- package/src/functions/functions/wrap-with-parentheses.mts +17 -23
|
@@ -5,200 +5,214 @@ import { isAsConstNode } from '../functions/is-as-const-node.mjs';
|
|
|
5
5
|
import '../functions/is-atomic-type-node.mjs';
|
|
6
6
|
import { replaceNodeWithDebugPrint } from '../utils/replace-with-debug.mjs';
|
|
7
7
|
|
|
8
|
-
const TRANSFORMER_NAME =
|
|
8
|
+
const TRANSFORMER_NAME = "append-as-const";
|
|
9
9
|
const appendAsConstTransformer = (options) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
const transformNode = (node, context, options) => {
|
|
32
|
-
if (node.wasForgotten()) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
options.debugPrint(node.getKindName(), node.getText(), { context });
|
|
36
|
-
if (hasDisableNextLineComment(node, TRANSFORMER_NAME)) {
|
|
37
|
-
options.debugPrint('skipped by disable-next-line comment');
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (options.applyLevel === 'avoidInFunctionArgs' &&
|
|
41
|
-
tsm.Node.isCallExpression(node)) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (node.isKind(tsm.SyntaxKind.VariableDeclaration)) {
|
|
45
|
-
const nodeName = node.getName();
|
|
46
|
-
// check for ignorePrefix
|
|
47
|
-
if (options.ignoredPrefixes.some((p) => nodeName.startsWith(p))) {
|
|
48
|
-
// Skip conversion for variable declarations with ignored prefixes
|
|
49
|
-
// Example: const mut_foo: string[] = []; -> remains as is, without appending `as const`
|
|
50
|
-
options.debugPrint('skipped variable declaration by ignorePrefixes');
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const variableStatement = node.getVariableStatement();
|
|
54
|
-
if (variableStatement !== undefined &&
|
|
55
|
-
hasDisableNextLineComment(variableStatement, TRANSFORMER_NAME)) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const initializer = node.getInitializer();
|
|
59
|
-
if (initializer === undefined) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
const declarationKindKeywords = node
|
|
63
|
-
.getVariableStatement()
|
|
64
|
-
?.getDeclarationKindKeywords()
|
|
65
|
-
.map((k) => k.getText());
|
|
66
|
-
if (declarationKindKeywords !== undefined &&
|
|
67
|
-
Arr.isArrayOfLength(declarationKindKeywords, 1)) {
|
|
68
|
-
transformNode(initializer, {
|
|
69
|
-
isDirectUnderConstInitializer: declarationKindKeywords[0] === 'const',
|
|
70
|
-
isUnderConstContext: false,
|
|
71
|
-
}, options);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
// const [a, b] = ...;
|
|
75
|
-
// TODO: Support ignoredPrefixes in ArrayBindingPattern
|
|
76
|
-
// if (ts.isArrayBindingPattern(nodeName)) {
|
|
77
|
-
// // for (const [i, el] of nodeName.elements.entries())
|
|
78
|
-
// }
|
|
79
|
-
// const { x, y } = ...;
|
|
80
|
-
// TODO: Support ignoredPrefixes in ObjectBindingPattern
|
|
81
|
-
// if (ts.isObjectBindingPattern(nodeName)) {
|
|
82
|
-
// // for (const [i, el] of nodeName.elements.entries())
|
|
83
|
-
// }
|
|
84
|
-
}
|
|
85
|
-
// Skip already type asserted nodes
|
|
86
|
-
if (tsm.Node.isAsExpression(node) && !isAsConstNode(node)) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
// pass by ([(X)] -> X)
|
|
90
|
-
if (tsm.Node.isParenthesizedExpression(node)) {
|
|
91
|
-
transformNode(node.getExpression(), context, options);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
// pass by ([X satisfies ...] -> X)
|
|
95
|
-
if (tsm.Node.isSatisfiesExpression(node)) {
|
|
96
|
-
transformNode(node.getExpression(), context, options);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
// pass by property initializer ([key: value] -> value)
|
|
100
|
-
if (tsm.Node.isPropertyAssignment(node)) {
|
|
101
|
-
const initializer = node.getInitializer();
|
|
102
|
-
if (initializer !== undefined) {
|
|
103
|
-
transformNode(initializer, context, options);
|
|
104
|
-
}
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
// pass by arrow function body ([() => X] -> X)
|
|
108
|
-
if (tsm.Node.isArrowFunction(node)) {
|
|
109
|
-
const body = node.getBody();
|
|
110
|
-
transformNode(body, context, options);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
// pass by spread element ([...X] -> X)
|
|
114
|
-
if (tsm.Node.isSpreadElement(node)) {
|
|
115
|
-
transformNode(node.getExpression(), context, options);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
if (node.isKind(tsm.SyntaxKind.NoSubstitutionTemplateLiteral) || // `abc`
|
|
119
|
-
node.isKind(tsm.SyntaxKind.NumericLiteral) || // 123
|
|
120
|
-
node.isKind(tsm.SyntaxKind.BigIntLiteral) || // 123n
|
|
121
|
-
node.isKind(tsm.SyntaxKind.StringLiteral) || // 'abc'
|
|
122
|
-
node.isKind(tsm.SyntaxKind.TrueKeyword) || // true
|
|
123
|
-
node.isKind(tsm.SyntaxKind.FalseKeyword) // false
|
|
124
|
-
) {
|
|
125
|
-
if (!context.isDirectUnderConstInitializer &&
|
|
126
|
-
!context.isUnderConstContext) {
|
|
127
|
-
options.replaceNode(node, `${node.getText()} as const`);
|
|
128
|
-
}
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
if (node.isKind(tsm.SyntaxKind.TemplateExpression)) {
|
|
132
|
-
if (!context.isUnderConstContext) {
|
|
133
|
-
options.replaceNode(node, `${node.getText()} as const`);
|
|
134
|
-
}
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
if (tsm.Node.isArrayLiteralExpression(node)) {
|
|
138
|
-
for (const el of node.getElements()) {
|
|
139
|
-
transformNode(el, {
|
|
140
|
-
isUnderConstContext: true, // [...] as const
|
|
141
|
-
isDirectUnderConstInitializer: false,
|
|
142
|
-
}, options);
|
|
143
|
-
}
|
|
144
|
-
if (!context.isUnderConstContext) {
|
|
145
|
-
options.replaceNode(node, `${node.getText()} as const`);
|
|
146
|
-
}
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
if (tsm.Node.isObjectLiteralExpression(node)) {
|
|
150
|
-
for (const el of node.getProperties()) {
|
|
151
|
-
transformNode(el, {
|
|
152
|
-
isUnderConstContext: true, // {...} as const
|
|
153
|
-
isDirectUnderConstInitializer: false,
|
|
154
|
-
}, options);
|
|
155
|
-
}
|
|
156
|
-
if (!context.isUnderConstContext) {
|
|
157
|
-
options.replaceNode(node, `${node.getText()} as const`);
|
|
158
|
-
}
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
// `as const` node
|
|
162
|
-
if (isAsConstNode(node)) {
|
|
163
|
-
if (context.isDirectUnderConstInitializer) {
|
|
164
|
-
// In const variable declarations, remove `as const` first and then re-append it later if needed
|
|
165
|
-
transformNode(node.getExpression(), {
|
|
166
|
-
isUnderConstContext: false,
|
|
167
|
-
isDirectUnderConstInitializer: true,
|
|
168
|
-
}, options);
|
|
169
|
-
options.replaceNode(node,
|
|
170
|
-
// The expression may be marked "as const"
|
|
171
|
-
node.getExpression().getText()); // remove `as const`
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (context.isUnderConstContext) {
|
|
175
|
-
transformNode(node.getExpression(), {
|
|
176
|
-
isUnderConstContext: true,
|
|
177
|
-
isDirectUnderConstInitializer: false,
|
|
178
|
-
}, options);
|
|
179
|
-
options.replaceNode(node,
|
|
180
|
-
// The expression may be marked "as const"
|
|
181
|
-
node.getExpression().getText()); // remove `as const`
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
transformNode(node.getExpression(), {
|
|
185
|
-
isUnderConstContext: true,
|
|
186
|
-
isDirectUnderConstInitializer: false,
|
|
187
|
-
}, options);
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
if (tsm.Node.isConditionalExpression(node)) {
|
|
191
|
-
// For conditional expressions, traverse both branches in a non-const context
|
|
192
|
-
transformNode(node.getWhenTrue(), {
|
|
193
|
-
isDirectUnderConstInitializer: context.isDirectUnderConstInitializer,
|
|
194
|
-
isUnderConstContext: false,
|
|
195
|
-
}, options);
|
|
196
|
-
transformNode(node.getWhenFalse(), {
|
|
197
|
-
isDirectUnderConstInitializer: context.isDirectUnderConstInitializer,
|
|
10
|
+
const ignorePrefixes = ISet.create(
|
|
11
|
+
options?.ignorePrefixes ?? ["mut_", "#mut_", "_mut_", "draft"]
|
|
12
|
+
);
|
|
13
|
+
const optionsInternal = {
|
|
14
|
+
applyLevel: options?.applyLevel ?? "avoidInFunctionArgs",
|
|
15
|
+
ignoredPrefixes: ignorePrefixes,
|
|
16
|
+
debugPrint: options?.debug === true ? console.debug : () => {
|
|
17
|
+
},
|
|
18
|
+
replaceNode: options?.debug === true ? replaceNodeWithDebugPrint : (node, newNodeText) => node.replaceWithText(newNodeText)
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
name: TRANSFORMER_NAME,
|
|
22
|
+
transform: (sourceAst) => {
|
|
23
|
+
for (const node of sourceAst.getDescendantsOfKind(
|
|
24
|
+
tsm.SyntaxKind.VariableDeclaration
|
|
25
|
+
)) {
|
|
26
|
+
transformNode(
|
|
27
|
+
node,
|
|
28
|
+
{
|
|
198
29
|
isUnderConstContext: false,
|
|
199
|
-
|
|
200
|
-
|
|
30
|
+
isDirectUnderConstInitializer: false
|
|
31
|
+
},
|
|
32
|
+
optionsInternal
|
|
33
|
+
);
|
|
34
|
+
}
|
|
201
35
|
}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const transformNode = (node, context, options) => {
|
|
39
|
+
if (node.wasForgotten()) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
options.debugPrint(node.getKindName(), node.getText(), { context });
|
|
43
|
+
if (hasDisableNextLineComment(node, TRANSFORMER_NAME)) {
|
|
44
|
+
options.debugPrint("skipped by disable-next-line comment");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (options.applyLevel === "avoidInFunctionArgs" && tsm.Node.isCallExpression(node)) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (node.isKind(tsm.SyntaxKind.VariableDeclaration)) {
|
|
51
|
+
const nodeName = node.getName();
|
|
52
|
+
if (options.ignoredPrefixes.some((p) => nodeName.startsWith(p))) {
|
|
53
|
+
options.debugPrint("skipped variable declaration by ignorePrefixes");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const variableStatement = node.getVariableStatement();
|
|
57
|
+
if (variableStatement !== void 0 && hasDisableNextLineComment(variableStatement, TRANSFORMER_NAME)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const initializer = node.getInitializer();
|
|
61
|
+
if (initializer === void 0) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const declarationKindKeywords = node.getVariableStatement()?.getDeclarationKindKeywords().map((k) => k.getText());
|
|
65
|
+
if (declarationKindKeywords !== void 0 && Arr.isArrayOfLength(declarationKindKeywords, 1)) {
|
|
66
|
+
transformNode(
|
|
67
|
+
initializer,
|
|
68
|
+
{
|
|
69
|
+
isDirectUnderConstInitializer: declarationKindKeywords[0] === "const",
|
|
70
|
+
isUnderConstContext: false
|
|
71
|
+
},
|
|
72
|
+
options
|
|
73
|
+
);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (tsm.Node.isAsExpression(node) && !isAsConstNode(node)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (tsm.Node.isParenthesizedExpression(node)) {
|
|
81
|
+
transformNode(node.getExpression(), context, options);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (tsm.Node.isSatisfiesExpression(node)) {
|
|
85
|
+
transformNode(node.getExpression(), context, options);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (tsm.Node.isPropertyAssignment(node)) {
|
|
89
|
+
const initializer = node.getInitializer();
|
|
90
|
+
if (initializer !== void 0) {
|
|
91
|
+
transformNode(initializer, context, options);
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (tsm.Node.isArrowFunction(node)) {
|
|
96
|
+
const body = node.getBody();
|
|
97
|
+
transformNode(body, context, options);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (tsm.Node.isSpreadElement(node)) {
|
|
101
|
+
transformNode(node.getExpression(), context, options);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (node.isKind(tsm.SyntaxKind.NoSubstitutionTemplateLiteral) || // `abc`
|
|
105
|
+
node.isKind(tsm.SyntaxKind.NumericLiteral) || // 123
|
|
106
|
+
node.isKind(tsm.SyntaxKind.BigIntLiteral) || // 123n
|
|
107
|
+
node.isKind(tsm.SyntaxKind.StringLiteral) || // 'abc'
|
|
108
|
+
node.isKind(tsm.SyntaxKind.TrueKeyword) || // true
|
|
109
|
+
node.isKind(tsm.SyntaxKind.FalseKeyword)) {
|
|
110
|
+
if (!context.isDirectUnderConstInitializer && !context.isUnderConstContext) {
|
|
111
|
+
options.replaceNode(node, `${node.getText()} as const`);
|
|
112
|
+
}
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (node.isKind(tsm.SyntaxKind.TemplateExpression)) {
|
|
116
|
+
if (!context.isUnderConstContext) {
|
|
117
|
+
options.replaceNode(node, `${node.getText()} as const`);
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
if (tsm.Node.isArrayLiteralExpression(node)) {
|
|
122
|
+
for (const el of node.getElements()) {
|
|
123
|
+
transformNode(
|
|
124
|
+
el,
|
|
125
|
+
{
|
|
126
|
+
isUnderConstContext: true,
|
|
127
|
+
// [...] as const
|
|
128
|
+
isDirectUnderConstInitializer: false
|
|
129
|
+
},
|
|
130
|
+
options
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (!context.isUnderConstContext) {
|
|
134
|
+
options.replaceNode(node, `${node.getText()} as const`);
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (tsm.Node.isObjectLiteralExpression(node)) {
|
|
139
|
+
for (const el of node.getProperties()) {
|
|
140
|
+
transformNode(
|
|
141
|
+
el,
|
|
142
|
+
{
|
|
143
|
+
isUnderConstContext: true,
|
|
144
|
+
// {...} as const
|
|
145
|
+
isDirectUnderConstInitializer: false
|
|
146
|
+
},
|
|
147
|
+
options
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
if (!context.isUnderConstContext) {
|
|
151
|
+
options.replaceNode(node, `${node.getText()} as const`);
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
if (isAsConstNode(node)) {
|
|
156
|
+
if (context.isDirectUnderConstInitializer) {
|
|
157
|
+
transformNode(
|
|
158
|
+
node.getExpression(),
|
|
159
|
+
{
|
|
160
|
+
isUnderConstContext: false,
|
|
161
|
+
isDirectUnderConstInitializer: true
|
|
162
|
+
},
|
|
163
|
+
options
|
|
164
|
+
);
|
|
165
|
+
options.replaceNode(
|
|
166
|
+
node,
|
|
167
|
+
// The expression may be marked "as const"
|
|
168
|
+
node.getExpression().getText()
|
|
169
|
+
);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (context.isUnderConstContext) {
|
|
173
|
+
transformNode(
|
|
174
|
+
node.getExpression(),
|
|
175
|
+
{
|
|
176
|
+
isUnderConstContext: true,
|
|
177
|
+
isDirectUnderConstInitializer: false
|
|
178
|
+
},
|
|
179
|
+
options
|
|
180
|
+
);
|
|
181
|
+
options.replaceNode(
|
|
182
|
+
node,
|
|
183
|
+
// The expression may be marked "as const"
|
|
184
|
+
node.getExpression().getText()
|
|
185
|
+
);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
transformNode(
|
|
189
|
+
node.getExpression(),
|
|
190
|
+
{
|
|
191
|
+
isUnderConstContext: true,
|
|
192
|
+
isDirectUnderConstInitializer: false
|
|
193
|
+
},
|
|
194
|
+
options
|
|
195
|
+
);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (tsm.Node.isConditionalExpression(node)) {
|
|
199
|
+
transformNode(
|
|
200
|
+
node.getWhenTrue(),
|
|
201
|
+
{
|
|
202
|
+
isDirectUnderConstInitializer: context.isDirectUnderConstInitializer,
|
|
203
|
+
isUnderConstContext: false
|
|
204
|
+
},
|
|
205
|
+
options
|
|
206
|
+
);
|
|
207
|
+
transformNode(
|
|
208
|
+
node.getWhenFalse(),
|
|
209
|
+
{
|
|
210
|
+
isDirectUnderConstInitializer: context.isDirectUnderConstInitializer,
|
|
211
|
+
isUnderConstContext: false
|
|
212
|
+
},
|
|
213
|
+
options
|
|
214
|
+
);
|
|
215
|
+
}
|
|
202
216
|
};
|
|
203
217
|
|
|
204
218
|
export { appendAsConstTransformer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"append-as-const.mjs","sources":["../../../src/functions/ast-transformers/append-as-const.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"append-as-const.mjs","sources":["../../../src/functions/ast-transformers/append-as-const.mts"],"sourcesContent":["import { Arr, ISet } from 'ts-data-forge';\nimport * as tsm from 'ts-morph';\nimport { type DeepReadonly } from 'ts-type-forge';\nimport {\n hasDisableNextLineComment,\n isAsConstNode,\n} from '../functions/index.mjs';\nimport { replaceNodeWithDebugPrint } from '../utils/index.mjs';\nimport { type TsMorphTransformer } from './types.mjs';\n\nconst TRANSFORMER_NAME = 'append-as-const';\n\nexport const appendAsConstTransformer = (\n options?: AppendAsConstTransformerOptions,\n): TsMorphTransformer => {\n const ignorePrefixes = ISet.create(\n options?.ignorePrefixes ?? ['mut_', '#mut_', '_mut_', 'draft'],\n );\n\n const optionsInternal: AppendAsConstTransformerOptionsInternal = {\n applyLevel: options?.applyLevel ?? 'avoidInFunctionArgs',\n ignoredPrefixes: ignorePrefixes,\n\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.getDescendantsOfKind(\n tsm.SyntaxKind.VariableDeclaration,\n )) {\n transformNode(\n node,\n {\n isUnderConstContext: false,\n isDirectUnderConstInitializer: false,\n },\n optionsInternal,\n );\n }\n },\n };\n};\n\nexport type AppendAsConstTransformerOptions = DeepReadonly<{\n /**\n * @default \"avoidInFunctionArgs\"\n */\n applyLevel?: 'all' | 'avoidInFunctionArgs';\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 // TODO\n // ignoreConstTypeParameter?: boolean;\n\n debug?: boolean;\n}>;\n\ntype AppendAsConstTransformerOptionsInternal = DeepReadonly<{\n applyLevel: 'all' | 'avoidInFunctionArgs';\n ignoredPrefixes: ISet<string>;\n\n debugPrint: (...args: readonly unknown[]) => void;\n replaceNode: (node: tsm.Node, newNodeText: string) => void;\n}>;\n\ntype AsConstContext = Readonly<{\n /**\n * Whether the current node is under an `as const` context.\n *\n * (e.g. `[1, 2, {x: 3}] as const` --> `isUnderConstContext` is true for `[1, 2, {x: 3}]` and its children `{x: 3}`)\n */\n isUnderConstContext: boolean;\n\n /**\n * Whether the current node is directly under a `const` variable initializer.\n *\n * (e.g. `const foo = [1, 2, 3];` --> `isDirectUnderConstInitializer` is true for `[1, 2, 3]`)\n */\n isDirectUnderConstInitializer: boolean;\n}>;\n\nconst transformNode = (\n node: tsm.Node,\n context: AsConstContext,\n options: AppendAsConstTransformerOptionsInternal,\n): void => {\n if (node.wasForgotten()) {\n return;\n }\n\n options.debugPrint(node.getKindName(), node.getText(), { context });\n\n if (hasDisableNextLineComment(node, TRANSFORMER_NAME)) {\n options.debugPrint('skipped by disable-next-line comment');\n\n return;\n }\n\n if (\n options.applyLevel === 'avoidInFunctionArgs' &&\n tsm.Node.isCallExpression(node)\n ) {\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.VariableDeclaration)) {\n const nodeName = node.getName();\n\n // check for ignorePrefix\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 const variableStatement = node.getVariableStatement();\n\n if (\n variableStatement !== undefined &&\n hasDisableNextLineComment(variableStatement, TRANSFORMER_NAME)\n ) {\n return;\n }\n\n const initializer = node.getInitializer();\n\n if (initializer === undefined) {\n return;\n }\n\n const declarationKindKeywords = node\n .getVariableStatement()\n ?.getDeclarationKindKeywords()\n .map((k) => k.getText());\n\n if (\n declarationKindKeywords !== undefined &&\n Arr.isArrayOfLength(declarationKindKeywords, 1)\n ) {\n transformNode(\n initializer,\n {\n isDirectUnderConstInitializer: declarationKindKeywords[0] === 'const',\n isUnderConstContext: false,\n },\n options,\n );\n\n return;\n }\n\n // const [a, b] = ...;\n // TODO: Support ignoredPrefixes in ArrayBindingPattern\n // if (ts.isArrayBindingPattern(nodeName)) {\n // // for (const [i, el] of nodeName.elements.entries())\n // }\n\n // const { x, y } = ...;\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 already type asserted nodes\n if (tsm.Node.isAsExpression(node) && !isAsConstNode(node)) {\n return;\n }\n\n // pass by ([(X)] -> X)\n if (tsm.Node.isParenthesizedExpression(node)) {\n transformNode(node.getExpression(), context, options);\n\n return;\n }\n\n // pass by ([X satisfies ...] -> X)\n if (tsm.Node.isSatisfiesExpression(node)) {\n transformNode(node.getExpression(), context, options);\n\n return;\n }\n\n // pass by property initializer ([key: value] -> value)\n if (tsm.Node.isPropertyAssignment(node)) {\n const initializer = node.getInitializer();\n\n if (initializer !== undefined) {\n transformNode(initializer, context, options);\n }\n\n return;\n }\n\n // pass by arrow function body ([() => X] -> X)\n if (tsm.Node.isArrowFunction(node)) {\n const body = node.getBody();\n\n transformNode(body, context, options);\n\n return;\n }\n\n // pass by spread element ([...X] -> X)\n if (tsm.Node.isSpreadElement(node)) {\n transformNode(node.getExpression(), context, options);\n\n return;\n }\n\n if (\n node.isKind(tsm.SyntaxKind.NoSubstitutionTemplateLiteral) || // `abc`\n node.isKind(tsm.SyntaxKind.NumericLiteral) || // 123\n node.isKind(tsm.SyntaxKind.BigIntLiteral) || // 123n\n node.isKind(tsm.SyntaxKind.StringLiteral) || // 'abc'\n node.isKind(tsm.SyntaxKind.TrueKeyword) || // true\n node.isKind(tsm.SyntaxKind.FalseKeyword) // false\n ) {\n if (\n !context.isDirectUnderConstInitializer &&\n !context.isUnderConstContext\n ) {\n options.replaceNode(node, `${node.getText()} as const`);\n }\n\n return;\n }\n\n if (node.isKind(tsm.SyntaxKind.TemplateExpression)) {\n if (!context.isUnderConstContext) {\n options.replaceNode(node, `${node.getText()} as const`);\n }\n\n return;\n }\n\n if (tsm.Node.isArrayLiteralExpression(node)) {\n for (const el of node.getElements()) {\n transformNode(\n el,\n {\n isUnderConstContext: true, // [...] as const\n isDirectUnderConstInitializer: false,\n },\n options,\n );\n }\n\n if (!context.isUnderConstContext) {\n options.replaceNode(node, `${node.getText()} as const`);\n }\n\n return;\n }\n\n if (tsm.Node.isObjectLiteralExpression(node)) {\n for (const el of node.getProperties()) {\n transformNode(\n el,\n {\n isUnderConstContext: true, // {...} as const\n isDirectUnderConstInitializer: false,\n },\n options,\n );\n }\n\n if (!context.isUnderConstContext) {\n options.replaceNode(node, `${node.getText()} as const`);\n }\n\n return;\n }\n\n // `as const` node\n if (isAsConstNode(node)) {\n if (context.isDirectUnderConstInitializer) {\n // In const variable declarations, remove `as const` first and then re-append it later if needed\n\n transformNode(\n node.getExpression(),\n {\n isUnderConstContext: false,\n isDirectUnderConstInitializer: true,\n },\n options,\n );\n\n options.replaceNode(\n node,\n // The expression may be marked \"as const\"\n node.getExpression().getText(),\n ); // remove `as const`\n\n return;\n }\n\n if (context.isUnderConstContext) {\n transformNode(\n node.getExpression(),\n {\n isUnderConstContext: true,\n isDirectUnderConstInitializer: false,\n },\n options,\n );\n\n options.replaceNode(\n node,\n // The expression may be marked \"as const\"\n node.getExpression().getText(),\n ); // remove `as const`\n\n return;\n }\n\n transformNode(\n node.getExpression(),\n {\n isUnderConstContext: true,\n isDirectUnderConstInitializer: false,\n },\n options,\n );\n\n return;\n }\n\n if (tsm.Node.isConditionalExpression(node)) {\n // For conditional expressions, traverse both branches in a non-const context\n transformNode(\n node.getWhenTrue(),\n {\n isDirectUnderConstInitializer: context.isDirectUnderConstInitializer,\n isUnderConstContext: false,\n },\n options,\n );\n\n transformNode(\n node.getWhenFalse(),\n {\n isDirectUnderConstInitializer: context.isDirectUnderConstInitializer,\n isUnderConstContext: false,\n },\n options,\n );\n\n // return;\n }\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -3,90 +3,70 @@ import { hasDisableNextLineComment } from '../functions/has-disable-next-line-co
|
|
|
3
3
|
import 'ts-morph';
|
|
4
4
|
import '../functions/is-atomic-type-node.mjs';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types -- ts-morph uses mutable types */
|
|
8
|
-
const TRANSFORMER_NAME = 'convert-interface-to-type';
|
|
9
|
-
/**
|
|
10
|
-
* interface による型定義を type による型定義に変換する。
|
|
11
|
-
* @typescript-eslint/consistent-type-definitions: ["error", "type"] と同等の動作
|
|
12
|
-
*/
|
|
6
|
+
const TRANSFORMER_NAME = "convert-interface-to-type";
|
|
13
7
|
const convertInterfaceToTypeTransformer = () => ({
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
convertInterfaceToType(interfaceDecl);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
const convertInterfaceToType = (interfaceDecl) => {
|
|
26
|
-
const interfaceName = interfaceDecl.getName();
|
|
27
|
-
const typeParameters = interfaceDecl.getTypeParameters();
|
|
28
|
-
const extendsExpressions = interfaceDecl.getExtends();
|
|
29
|
-
const members = interfaceDecl.getMembers();
|
|
30
|
-
// Build type parameters string
|
|
31
|
-
const typeParamsStr = Arr.isNonEmpty(typeParameters)
|
|
32
|
-
? `<${typeParameters.map((tp) => tp.getText()).join(', ')}>`
|
|
33
|
-
: '';
|
|
34
|
-
// Build type literal from members
|
|
35
|
-
const mut_typeBody = (() => {
|
|
36
|
-
if (Arr.isArrayOfLength(extendsExpressions, 0)) {
|
|
37
|
-
// No extends: simple type literal
|
|
38
|
-
return buildTypeLiteral(members);
|
|
39
|
-
}
|
|
40
|
-
if (Arr.isArrayOfLength(members, 0)) {
|
|
41
|
-
// Only extends, no own members: union of extended types
|
|
42
|
-
const extendedTypes = extendsExpressions.map((ext) => ext.getText());
|
|
43
|
-
return Arr.isArrayOfLength(extendedTypes, 1)
|
|
44
|
-
? extendedTypes[0]
|
|
45
|
-
: extendedTypes.join(' & ');
|
|
46
|
-
}
|
|
47
|
-
// Both extends and own members: intersection
|
|
48
|
-
const extendedTypesWithMembers = extendsExpressions.map((ext) => ext.getText());
|
|
49
|
-
const ownType = buildTypeLiteral(members);
|
|
50
|
-
return [...extendedTypesWithMembers, ownType].join(' & ');
|
|
51
|
-
})();
|
|
52
|
-
// Get export keyword
|
|
53
|
-
const isExported = interfaceDecl.isExported();
|
|
54
|
-
const exportKeyword = isExported ? 'export ' : '';
|
|
55
|
-
// Get leading comments (including JSDoc)
|
|
56
|
-
const leadingComments = interfaceDecl.getLeadingCommentRanges();
|
|
57
|
-
const commentTexts = leadingComments
|
|
58
|
-
.map((range) => range.getText())
|
|
59
|
-
.join('\n');
|
|
60
|
-
const jsDocText = commentTexts.length > 0 ? `${commentTexts}\n` : '';
|
|
61
|
-
// Replace interface with type alias
|
|
62
|
-
const typeAliasText = `${jsDocText}${exportKeyword}type ${interfaceName}${typeParamsStr} = ${mut_typeBody};`;
|
|
63
|
-
interfaceDecl.replaceWithText(typeAliasText);
|
|
64
|
-
};
|
|
65
|
-
const buildTypeLiteral = (members) => {
|
|
66
|
-
if (Arr.isArrayOfLength(members, 0)) {
|
|
67
|
-
return 'Record<string, never>';
|
|
68
|
-
}
|
|
69
|
-
const memberTexts = members.map((member) => {
|
|
70
|
-
// Preserve comments
|
|
71
|
-
const leadingComments = member
|
|
72
|
-
.getLeadingCommentRanges()
|
|
73
|
-
.map((range) => range.getText())
|
|
74
|
-
.join('\n');
|
|
75
|
-
const memberText = member.getText();
|
|
76
|
-
return leadingComments.length > 0
|
|
77
|
-
? `${leadingComments}\n${memberText}`
|
|
78
|
-
: memberText;
|
|
79
|
-
});
|
|
80
|
-
return `{\n ${memberTexts.join('\n ')}\n}`;
|
|
81
|
-
};
|
|
82
|
-
// Process top-level interface declarations
|
|
83
|
-
processInterfaces(sourceAst);
|
|
84
|
-
// Process interfaces inside namespaces/modules
|
|
85
|
-
const namespaces = sourceAst.getModules();
|
|
86
|
-
for (const namespace of namespaces) {
|
|
87
|
-
processInterfaces(namespace);
|
|
8
|
+
name: TRANSFORMER_NAME,
|
|
9
|
+
transform: (sourceAst) => {
|
|
10
|
+
const processInterfaces = (container) => {
|
|
11
|
+
const interfaces = container.getInterfaces();
|
|
12
|
+
for (const interfaceDecl of interfaces) {
|
|
13
|
+
if (hasDisableNextLineComment(interfaceDecl, TRANSFORMER_NAME)) {
|
|
14
|
+
continue;
|
|
88
15
|
}
|
|
89
|
-
|
|
16
|
+
convertInterfaceToType(interfaceDecl);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const convertInterfaceToType = (interfaceDecl) => {
|
|
20
|
+
const interfaceName = interfaceDecl.getName();
|
|
21
|
+
const typeParameters = interfaceDecl.getTypeParameters();
|
|
22
|
+
const extendsExpressions = interfaceDecl.getExtends();
|
|
23
|
+
const members = interfaceDecl.getMembers();
|
|
24
|
+
const typeParamsStr = Arr.isNonEmpty(typeParameters) ? `<${typeParameters.map((tp) => tp.getText()).join(", ")}>` : "";
|
|
25
|
+
const mut_typeBody = (() => {
|
|
26
|
+
if (Arr.isArrayOfLength(extendsExpressions, 0)) {
|
|
27
|
+
return buildTypeLiteral(members);
|
|
28
|
+
}
|
|
29
|
+
if (Arr.isArrayOfLength(members, 0)) {
|
|
30
|
+
const extendedTypes = extendsExpressions.map(
|
|
31
|
+
(ext) => ext.getText()
|
|
32
|
+
);
|
|
33
|
+
return Arr.isArrayOfLength(extendedTypes, 1) ? extendedTypes[0] : extendedTypes.join(" & ");
|
|
34
|
+
}
|
|
35
|
+
const extendedTypesWithMembers = extendsExpressions.map(
|
|
36
|
+
(ext) => ext.getText()
|
|
37
|
+
);
|
|
38
|
+
const ownType = buildTypeLiteral(members);
|
|
39
|
+
return Arr.toPushed(extendedTypesWithMembers, ownType).join(" & ");
|
|
40
|
+
})();
|
|
41
|
+
const isExported = interfaceDecl.isExported();
|
|
42
|
+
const exportKeyword = isExported ? "export " : "";
|
|
43
|
+
const leadingComments = interfaceDecl.getLeadingCommentRanges();
|
|
44
|
+
const commentTexts = leadingComments.map((range) => range.getText()).join("\n");
|
|
45
|
+
const jsDocText = commentTexts.length > 0 ? `${commentTexts}
|
|
46
|
+
` : "";
|
|
47
|
+
const typeAliasText = `${jsDocText}${exportKeyword}type ${interfaceName}${typeParamsStr} = ${mut_typeBody};`;
|
|
48
|
+
interfaceDecl.replaceWithText(typeAliasText);
|
|
49
|
+
};
|
|
50
|
+
const buildTypeLiteral = (members) => {
|
|
51
|
+
if (Arr.isArrayOfLength(members, 0)) {
|
|
52
|
+
return "Record<string, never>";
|
|
53
|
+
}
|
|
54
|
+
const memberTexts = members.map((member) => {
|
|
55
|
+
const leadingComments = member.getLeadingCommentRanges().map((range) => range.getText()).join("\n");
|
|
56
|
+
const memberText = member.getText();
|
|
57
|
+
return leadingComments.length > 0 ? `${leadingComments}
|
|
58
|
+
${memberText}` : memberText;
|
|
59
|
+
});
|
|
60
|
+
return `{
|
|
61
|
+
${memberTexts.join("\n ")}
|
|
62
|
+
}`;
|
|
63
|
+
};
|
|
64
|
+
processInterfaces(sourceAst);
|
|
65
|
+
const namespaces = sourceAst.getModules();
|
|
66
|
+
for (const namespace of namespaces) {
|
|
67
|
+
processInterfaces(namespace);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
90
70
|
});
|
|
91
71
|
|
|
92
72
|
export { convertInterfaceToTypeTransformer };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert-interface-to-type.mjs","sources":["../../../src/functions/ast-transformers/convert-interface-to-type.mts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"convert-interface-to-type.mjs","sources":["../../../src/functions/ast-transformers/convert-interface-to-type.mts"],"sourcesContent":["/* eslint-disable unicorn/consistent-function-scoping -- helper functions are kept inside for clarity */\n/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types -- ts-morph uses mutable types */\nimport { Arr } from 'ts-data-forge';\nimport type * as tsm from 'ts-morph';\nimport { hasDisableNextLineComment } from '../functions/index.mjs';\nimport { type TsMorphTransformer } from './types.mjs';\n\nconst TRANSFORMER_NAME = 'convert-interface-to-type';\n\n/**\n * interface による型定義を type による型定義に変換する。\n * @typescript-eslint/consistent-type-definitions: [\"error\", \"type\"] と同等の動作\n */\nexport const convertInterfaceToTypeTransformer = (): TsMorphTransformer =>\n ({\n name: TRANSFORMER_NAME,\n transform: (sourceAst) => {\n const processInterfaces = (\n container: tsm.SourceFile | tsm.ModuleDeclaration,\n ): void => {\n const interfaces = container.getInterfaces();\n\n for (const interfaceDecl of interfaces) {\n if (hasDisableNextLineComment(interfaceDecl, TRANSFORMER_NAME)) {\n continue;\n }\n\n convertInterfaceToType(interfaceDecl);\n }\n };\n\n const convertInterfaceToType = (\n interfaceDecl: tsm.InterfaceDeclaration,\n ): void => {\n const interfaceName = interfaceDecl.getName();\n\n const typeParameters = interfaceDecl.getTypeParameters();\n\n const extendsExpressions = interfaceDecl.getExtends();\n\n const members = interfaceDecl.getMembers();\n\n // Build type parameters string\n const typeParamsStr = Arr.isNonEmpty(typeParameters)\n ? `<${typeParameters.map((tp) => tp.getText()).join(', ')}>`\n : '';\n\n // Build type literal from members\n const mut_typeBody: string = (() => {\n if (Arr.isArrayOfLength(extendsExpressions, 0)) {\n // No extends: simple type literal\n return buildTypeLiteral(members);\n }\n\n if (Arr.isArrayOfLength(members, 0)) {\n // Only extends, no own members: union of extended types\n const extendedTypes = extendsExpressions.map((ext) =>\n ext.getText(),\n );\n\n return Arr.isArrayOfLength(extendedTypes, 1)\n ? extendedTypes[0]\n : extendedTypes.join(' & ');\n }\n\n // Both extends and own members: intersection\n const extendedTypesWithMembers = extendsExpressions.map((ext) =>\n ext.getText(),\n );\n\n const ownType = buildTypeLiteral(members);\n\n return Arr.toPushed(extendedTypesWithMembers, ownType).join(' & ');\n })();\n\n // Get export keyword\n const isExported = interfaceDecl.isExported();\n\n const exportKeyword = isExported ? 'export ' : '';\n\n // Get leading comments (including JSDoc)\n const leadingComments = interfaceDecl.getLeadingCommentRanges();\n\n const commentTexts = leadingComments\n .map((range) => range.getText())\n .join('\\n');\n\n const jsDocText = commentTexts.length > 0 ? `${commentTexts}\\n` : '';\n\n // Replace interface with type alias\n const typeAliasText =\n `${jsDocText}${exportKeyword}type ${interfaceName}${typeParamsStr} = ${mut_typeBody};` as const;\n\n interfaceDecl.replaceWithText(typeAliasText);\n };\n\n const buildTypeLiteral = (\n members: readonly tsm.TypeElementTypes[],\n ): string => {\n if (Arr.isArrayOfLength(members, 0)) {\n return 'Record<string, never>';\n }\n\n const memberTexts = members.map((member) => {\n // Preserve comments\n const leadingComments = member\n .getLeadingCommentRanges()\n .map((range) => range.getText())\n .join('\\n');\n\n const memberText = member.getText();\n\n return leadingComments.length > 0\n ? `${leadingComments}\\n${memberText}`\n : memberText;\n });\n\n return `{\\n ${memberTexts.join('\\n ')}\\n}`;\n };\n\n // Process top-level interface declarations\n processInterfaces(sourceAst);\n\n // Process interfaces inside namespaces/modules\n const namespaces = sourceAst.getModules();\n\n for (const namespace of namespaces) {\n processInterfaces(namespace);\n }\n },\n }) as const;\n"],"names":[],"mappings":"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"}
|
|
@@ -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,EAAE,KAAK,YAAY,EAA6B,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"convert-to-readonly.d.mts","sourceRoot":"","sources":["../../../src/functions/ast-transformers/convert-to-readonly.mts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,YAAY,EAA6B,MAAM,eAAe,CAAC;AAsB7E,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItD,eAAO,MAAM,4BAA4B,aAC7B,0BAA0B,KACnC,kBAuCF,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,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC,CAAC"}
|