ts-codemod-lib 2.2.1 → 2.2.3
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/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 +742 -834
- 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/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.map +1 -1
- package/dist/functions/functions/is-conditional-type-distribution-guard.mjs +9 -33
- package/dist/functions/functions/is-conditional-type-distribution-guard.mjs.map +1 -1
- 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/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/package.json +40 -29
- 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 +64 -35
- package/src/functions/ast-transformers/convert-to-readonly.test.mts +67 -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/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":";;;;;;;AAUA,MAAM,gBAAA,GAAmB,iBAAA;AAElB,MAAM,wBAAA,GAA2B,CACtC,OAAA,KACuB;AACvB,EAAA,MAAM,iBAAiB,IAAA,CAAK,MAAA;AAAA,IAC1B,SAAS,cAAA,IAAkB,CAAC,MAAA,EAAQ,OAAA,EAAS,SAAS,OAAO;AAAA,GAC/D;AAEA,EAAA,MAAM,eAAA,GAA2D;AAAA,IAC/D,UAAA,EAAY,SAAS,UAAA,IAAc,qBAAA;AAAA,IACnC,eAAA,EAAiB,cAAA;AAAA,IAEjB,YAAY,OAAA,EAAS,KAAA,KAAU,IAAA,GAAO,OAAA,CAAQ,QAAQ,MAAM;AAAA,IAAC,CAAA;AAAA,IAC7D,WAAA,EACE,OAAA,EAAS,KAAA,KAAU,IAAA,GACf,yBAAA,GACA,CAAC,IAAA,EAAM,WAAA,KAAgB,IAAA,CAAK,eAAA,CAAgB,WAAW;AAAA,GAC/D;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,SAAA,EAAW,CAAC,SAAA,KAAc;AACxB,MAAA,KAAA,MAAW,QAAQ,SAAA,CAAU,oBAAA;AAAA,QAC3B,IAAI,UAAA,CAAW;AAAA,OACjB,EAAG;AACD,QAAA,aAAA;AAAA,UACE,IAAA;AAAA,UACA;AAAA,YACE,mBAAA,EAAqB,KAAA;AAAA,YACrB,6BAAA,EAA+B;AAAA,WACjC;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAAA,GACF;AACF;AA+CA,MAAM,aAAA,GAAgB,CACpB,IAAA,EACA,OAAA,EACA,OAAA,KACS;AACT,EAAA,IAAI,IAAA,CAAK,cAAa,EAAG;AACvB,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,UAAA,CAAW,KAAK,WAAA,EAAY,EAAG,KAAK,OAAA,EAAQ,EAAG,EAAE,OAAA,EAAS,CAAA;AAElE,EAAA,IAAI,yBAAA,CAA0B,IAAA,EAAM,gBAAgB,CAAA,EAAG;AACrD,IAAA,OAAA,CAAQ,WAAW,sCAAsC,CAAA;AAEzD,IAAA;AAAA,EACF;AAEA,EAAA,IACE,QAAQ,UAAA,KAAe,qBAAA,IACvB,IAAI,IAAA,CAAK,gBAAA,CAAiB,IAAI,CAAA,EAC9B;AACA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,mBAAmB,CAAA,EAAG;AACnD,IAAA,MAAM,QAAA,GAAW,KAAK,OAAA,EAAQ;AAG9B,IAAA,IAAI,OAAA,CAAQ,gBAAgB,IAAA,CAAK,CAAC,MAAM,QAAA,CAAS,UAAA,CAAW,CAAC,CAAC,CAAA,EAAG;AAG/D,MAAA,OAAA,CAAQ,WAAW,gDAAgD,CAAA;AAEnE,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,iBAAA,GAAoB,KAAK,oBAAA,EAAqB;AAEpD,IAAA,IACE,iBAAA,KAAsB,MAAA,IACtB,yBAAA,CAA0B,iBAAA,EAAmB,gBAAgB,CAAA,EAC7D;AACA,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,KAAK,cAAA,EAAe;AAExC,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,uBAAA,GAA0B,IAAA,CAC7B,oBAAA,EAAqB,EACpB,0BAAA,EAA2B,CAC5B,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAA,EAAS,CAAA;AAEzB,IAAA,IACE,4BAA4B,MAAA,IAC5B,GAAA,CAAI,eAAA,CAAgB,uBAAA,EAAyB,CAAC,CAAA,EAC9C;AACA,MAAA,aAAA;AAAA,QACE,WAAA;AAAA,QACA;AAAA,UACE,6BAAA,EAA+B,uBAAA,CAAwB,CAAC,CAAA,KAAM,OAAA;AAAA,UAC9D,mBAAA,EAAqB;AAAA,SACvB;AAAA,QACA;AAAA,OACF;AAEA,MAAA;AAAA,IACF;AAAA,EAaF;AAGA,EAAA,IAAI,GAAA,CAAI,KAAK,cAAA,CAAe,IAAI,KAAK,CAAC,aAAA,CAAc,IAAI,CAAA,EAAG;AACzD,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,yBAAA,CAA0B,IAAI,CAAA,EAAG;AAC5C,IAAA,aAAA,CAAc,IAAA,CAAK,aAAA,EAAc,EAAG,OAAA,EAAS,OAAO,CAAA;AAEpD,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,qBAAA,CAAsB,IAAI,CAAA,EAAG;AACxC,IAAA,aAAA,CAAc,IAAA,CAAK,aAAA,EAAc,EAAG,OAAA,EAAS,OAAO,CAAA;AAEpD,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,oBAAA,CAAqB,IAAI,CAAA,EAAG;AACvC,IAAA,MAAM,WAAA,GAAc,KAAK,cAAA,EAAe;AAExC,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,aAAA,CAAc,WAAA,EAAa,SAAS,OAAO,CAAA;AAAA,IAC7C;AAEA,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,eAAA,CAAgB,IAAI,CAAA,EAAG;AAClC,IAAA,MAAM,IAAA,GAAO,KAAK,OAAA,EAAQ;AAE1B,IAAA,aAAA,CAAc,IAAA,EAAM,SAAS,OAAO,CAAA;AAEpC,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,eAAA,CAAgB,IAAI,CAAA,EAAG;AAClC,IAAA,aAAA,CAAc,IAAA,CAAK,aAAA,EAAc,EAAG,OAAA,EAAS,OAAO,CAAA;AAEpD,IAAA;AAAA,EACF;AAEA,EAAA,IACE,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,6BAA6B,CAAA;AAAA,EACxD,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,cAAc,CAAA;AAAA,EACzC,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,aAAa,CAAA;AAAA,EACxC,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,aAAa,CAAA;AAAA,EACxC,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,WAAW,CAAA;AAAA,EACtC,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,EACvC;AACA,IAAA,IACE,CAAC,OAAA,CAAQ,6BAAA,IACT,CAAC,QAAQ,mBAAA,EACT;AACA,MAAA,OAAA,CAAQ,YAAY,IAAA,EAAM,CAAA,EAAG,IAAA,CAAK,OAAA,EAAS,CAAA,SAAA,CAAW,CAAA;AAAA,IACxD;AAEA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,kBAAkB,CAAA,EAAG;AAClD,IAAA,IAAI,CAAC,QAAQ,mBAAA,EAAqB;AAChC,MAAA,OAAA,CAAQ,YAAY,IAAA,EAAM,CAAA,EAAG,IAAA,CAAK,OAAA,EAAS,CAAA,SAAA,CAAW,CAAA;AAAA,IACxD;AAEA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,wBAAA,CAAyB,IAAI,CAAA,EAAG;AAC3C,IAAA,KAAA,MAAW,EAAA,IAAM,IAAA,CAAK,WAAA,EAAY,EAAG;AACnC,MAAA,aAAA;AAAA,QACE,EAAA;AAAA,QACA;AAAA,UACE,mBAAA,EAAqB,IAAA;AAAA;AAAA,UACrB,6BAAA,EAA+B;AAAA,SACjC;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,QAAQ,mBAAA,EAAqB;AAChC,MAAA,OAAA,CAAQ,YAAY,IAAA,EAAM,CAAA,EAAG,IAAA,CAAK,OAAA,EAAS,CAAA,SAAA,CAAW,CAAA;AAAA,IACxD;AAEA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,yBAAA,CAA0B,IAAI,CAAA,EAAG;AAC5C,IAAA,KAAA,MAAW,EAAA,IAAM,IAAA,CAAK,aAAA,EAAc,EAAG;AACrC,MAAA,aAAA;AAAA,QACE,EAAA;AAAA,QACA;AAAA,UACE,mBAAA,EAAqB,IAAA;AAAA;AAAA,UACrB,6BAAA,EAA+B;AAAA,SACjC;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,QAAQ,mBAAA,EAAqB;AAChC,MAAA,OAAA,CAAQ,YAAY,IAAA,EAAM,CAAA,EAAG,IAAA,CAAK,OAAA,EAAS,CAAA,SAAA,CAAW,CAAA;AAAA,IACxD;AAEA,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,aAAA,CAAc,IAAI,CAAA,EAAG;AACvB,IAAA,IAAI,QAAQ,6BAAA,EAA+B;AAGzC,MAAA,aAAA;AAAA,QACE,KAAK,aAAA,EAAc;AAAA,QACnB;AAAA,UACE,mBAAA,EAAqB,KAAA;AAAA,UACrB,6BAAA,EAA+B;AAAA,SACjC;AAAA,QACA;AAAA,OACF;AAEA,MAAA,OAAA,CAAQ,WAAA;AAAA,QACN,IAAA;AAAA;AAAA,QAEA,IAAA,CAAK,aAAA,EAAc,CAAE,OAAA;AAAQ,OAC/B;AAEA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,QAAQ,mBAAA,EAAqB;AAC/B,MAAA,aAAA;AAAA,QACE,KAAK,aAAA,EAAc;AAAA,QACnB;AAAA,UACE,mBAAA,EAAqB,IAAA;AAAA,UACrB,6BAAA,EAA+B;AAAA,SACjC;AAAA,QACA;AAAA,OACF;AAEA,MAAA,OAAA,CAAQ,WAAA;AAAA,QACN,IAAA;AAAA;AAAA,QAEA,IAAA,CAAK,aAAA,EAAc,CAAE,OAAA;AAAQ,OAC/B;AAEA,MAAA;AAAA,IACF;AAEA,IAAA,aAAA;AAAA,MACE,KAAK,aAAA,EAAc;AAAA,MACnB;AAAA,QACE,mBAAA,EAAqB,IAAA;AAAA,QACrB,6BAAA,EAA+B;AAAA,OACjC;AAAA,MACA;AAAA,KACF;AAEA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,uBAAA,CAAwB,IAAI,CAAA,EAAG;AAE1C,IAAA,aAAA;AAAA,MACE,KAAK,WAAA,EAAY;AAAA,MACjB;AAAA,QACE,+BAA+B,OAAA,CAAQ,6BAAA;AAAA,QACvC,mBAAA,EAAqB;AAAA,OACvB;AAAA,MACA;AAAA,KACF;AAEA,IAAA,aAAA;AAAA,MACE,KAAK,YAAA,EAAa;AAAA,MAClB;AAAA,QACE,+BAA+B,OAAA,CAAQ,6BAAA;AAAA,QACvC,mBAAA,EAAqB;AAAA,OACvB;AAAA,MACA;AAAA,KACF;AAAA,EAGF;AACF,CAAA;;;;"}
|
|
@@ -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;AAsB7E,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItD,eAAO,MAAM,4BAA4B,
|
|
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"}
|