@kernlang/cli 3.1.9 → 3.3.4
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/cli.js +28 -16
- package/dist/cli.js.map +1 -1
- package/dist/commands/apply.d.ts +14 -0
- package/dist/commands/apply.js +167 -0
- package/dist/commands/apply.js.map +1 -0
- package/dist/commands/compile.js +59 -11
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/gaps.d.ts +1 -0
- package/dist/commands/gaps.js +178 -0
- package/dist/commands/gaps.js.map +1 -0
- package/dist/commands/migrate-class-body.d.ts +50 -0
- package/dist/commands/migrate-class-body.js +453 -0
- package/dist/commands/migrate-class-body.js.map +1 -0
- package/dist/commands/migrate.d.ts +80 -0
- package/dist/commands/migrate.js +586 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/review.d.ts +9 -0
- package/dist/commands/review.js +290 -26
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/transpile.js +12 -5
- package/dist/commands/transpile.js.map +1 -1
- package/dist/remote-repo.d.ts +21 -0
- package/dist/remote-repo.js +167 -0
- package/dist/remote-repo.js.map +1 -0
- package/dist/review-baseline.d.ts +27 -0
- package/dist/review-baseline.js +120 -0
- package/dist/review-baseline.js.map +1 -0
- package/dist/shared.d.ts +23 -2
- package/dist/shared.js +213 -39
- package/dist/shared.js.map +1 -1
- package/package.json +14 -13
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kern migrate class-body` — convert handler-escaped class expressions to
|
|
3
|
+
* first-class `class` nodes.
|
|
4
|
+
*
|
|
5
|
+
* Detects this shape:
|
|
6
|
+
*
|
|
7
|
+
* const name=AudioRecorder type=(any|object|unknown) [export=true]
|
|
8
|
+
* handler <<<
|
|
9
|
+
* class AudioRecorder [extends X] [implements Y] {
|
|
10
|
+
* private fd: T = init;
|
|
11
|
+
* ...
|
|
12
|
+
* constructor(...) { ... }
|
|
13
|
+
* foo(...) { ... }
|
|
14
|
+
* }
|
|
15
|
+
* >>>
|
|
16
|
+
*
|
|
17
|
+
* and rewrites it to a proper:
|
|
18
|
+
*
|
|
19
|
+
* class name=AudioRecorder [export=true] [extends=X] [implements=Y]
|
|
20
|
+
* field name=fd type=T private=true default={{ init }}
|
|
21
|
+
* constructor params="..."
|
|
22
|
+
* handler <<< ... >>>
|
|
23
|
+
* method name=foo params="..." returns=T
|
|
24
|
+
* handler <<< ... >>>
|
|
25
|
+
*
|
|
26
|
+
* This is NOT byte-equivalent: the original emits
|
|
27
|
+
* `export const X: any = class X { ... };` (class expression bound to const)
|
|
28
|
+
* whereas the rewrite emits
|
|
29
|
+
* `export class X { ... }` (class declaration)
|
|
30
|
+
*
|
|
31
|
+
* The two are behaviourally compatible at the call sites we care about
|
|
32
|
+
* (constructor, methods, imports) but differ in hoisting and in the
|
|
33
|
+
* value of `typeof X`. We only migrate when the original annotation was the
|
|
34
|
+
* throwaway `any`/`object`/`unknown` — i.e. no existing code relied on the
|
|
35
|
+
* type of the const, because the const had no useful type to begin with.
|
|
36
|
+
*/
|
|
37
|
+
import ts from 'typescript';
|
|
38
|
+
const PLACEHOLDER_TYPES = new Set(['any', 'object', 'unknown']);
|
|
39
|
+
/**
|
|
40
|
+
* Scan for `const ... handler <<< ... >>>` blocks. Unlike the
|
|
41
|
+
* literal-const matcher, class bodies are multi-line, so we capture the full
|
|
42
|
+
* range and let the TS parser validate shape.
|
|
43
|
+
*/
|
|
44
|
+
function findConstHandlerBlocks(lines) {
|
|
45
|
+
const blocks = [];
|
|
46
|
+
for (let i = 0; i < lines.length; i++) {
|
|
47
|
+
const headerMatch = lines[i].match(/^(\s*)const\s+(.*)$/);
|
|
48
|
+
if (!headerMatch)
|
|
49
|
+
continue;
|
|
50
|
+
const headerIndent = headerMatch[1];
|
|
51
|
+
const headerRest = headerMatch[2];
|
|
52
|
+
if (/\bvalue=/.test(headerRest))
|
|
53
|
+
continue;
|
|
54
|
+
if (!/\bname=/.test(headerRest))
|
|
55
|
+
continue;
|
|
56
|
+
if (/(?:^|\s)(?:#|\/\/)/.test(headerRest))
|
|
57
|
+
continue;
|
|
58
|
+
const openLine = lines[i + 1];
|
|
59
|
+
if (openLine === undefined)
|
|
60
|
+
continue;
|
|
61
|
+
const openMatch = openLine.match(/^(\s+)handler\s*<<<\s*$/);
|
|
62
|
+
if (!openMatch)
|
|
63
|
+
continue;
|
|
64
|
+
if (openMatch[1].length <= headerIndent.length)
|
|
65
|
+
continue;
|
|
66
|
+
const innerIndent = openMatch[1];
|
|
67
|
+
// Find the matching `>>>` at the same indent as `handler`.
|
|
68
|
+
let closeIdx = -1;
|
|
69
|
+
for (let j = i + 2; j < lines.length; j++) {
|
|
70
|
+
const closeMatch = lines[j].match(/^(\s+)>>>\s*$/);
|
|
71
|
+
if (closeMatch && closeMatch[1] === innerIndent) {
|
|
72
|
+
closeIdx = j;
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (closeIdx === -1)
|
|
77
|
+
continue;
|
|
78
|
+
const bodyLines = lines.slice(i + 2, closeIdx);
|
|
79
|
+
if (bodyLines.length === 0)
|
|
80
|
+
continue;
|
|
81
|
+
const firstBodyMatch = bodyLines[0].match(/^(\s+)/);
|
|
82
|
+
if (!firstBodyMatch)
|
|
83
|
+
continue;
|
|
84
|
+
const bodyIndent = firstBodyMatch[1];
|
|
85
|
+
if (bodyIndent.length <= innerIndent.length)
|
|
86
|
+
continue;
|
|
87
|
+
const dedentLen = bodyIndent.length;
|
|
88
|
+
const bodyText = bodyLines.map((l) => (l.length >= dedentLen ? l.slice(dedentLen) : l)).join('\n');
|
|
89
|
+
blocks.push({
|
|
90
|
+
block: {
|
|
91
|
+
startLine: i,
|
|
92
|
+
endLine: closeIdx,
|
|
93
|
+
headerIndent,
|
|
94
|
+
headerRest,
|
|
95
|
+
innerIndent,
|
|
96
|
+
bodyIndent,
|
|
97
|
+
bodyLines,
|
|
98
|
+
},
|
|
99
|
+
bodyText,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return blocks;
|
|
103
|
+
}
|
|
104
|
+
/** Extract `name=VALUE` from a header's prop string, respecting quoted values. */
|
|
105
|
+
function readProp(header, key) {
|
|
106
|
+
const re = new RegExp(`\\b${key}=("(?:[^"\\\\]|\\\\.)*"|\\S+)`);
|
|
107
|
+
const match = header.match(re);
|
|
108
|
+
if (!match)
|
|
109
|
+
return undefined;
|
|
110
|
+
const raw = match[1];
|
|
111
|
+
if (raw.startsWith('"'))
|
|
112
|
+
return raw.slice(1, -1).replace(/\\"/g, '"');
|
|
113
|
+
return raw;
|
|
114
|
+
}
|
|
115
|
+
/** True when a header carries `export=true` (default true if absent is false). */
|
|
116
|
+
function headerIsExported(header) {
|
|
117
|
+
const exp = readProp(header, 'export');
|
|
118
|
+
return exp === 'true';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Parse a handler body. Returns the ClassDeclaration if and only if the body
|
|
122
|
+
* is exactly one top-level class declaration whose name matches `expectedName`,
|
|
123
|
+
* with no other statements. Otherwise returns null.
|
|
124
|
+
*/
|
|
125
|
+
function extractSoleClass(bodyText, expectedName) {
|
|
126
|
+
const sourceFile = ts.createSourceFile('__class_body.ts', bodyText, ts.ScriptTarget.Latest, true);
|
|
127
|
+
const statements = sourceFile.statements;
|
|
128
|
+
if (statements.length !== 1)
|
|
129
|
+
return null;
|
|
130
|
+
const stmt = statements[0];
|
|
131
|
+
if (!ts.isClassDeclaration(stmt))
|
|
132
|
+
return null;
|
|
133
|
+
if (!stmt.name || stmt.name.getText(sourceFile) !== expectedName)
|
|
134
|
+
return null;
|
|
135
|
+
return stmt;
|
|
136
|
+
}
|
|
137
|
+
/** Extract getText helper bound to a synthesised source file. */
|
|
138
|
+
function binder(bodyText) {
|
|
139
|
+
const source = ts.createSourceFile('__class_body.ts', bodyText, ts.ScriptTarget.Latest, true);
|
|
140
|
+
return {
|
|
141
|
+
source,
|
|
142
|
+
text: (n) => (n ? n.getText(source) : ''),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function formatParams(params, text) {
|
|
146
|
+
return params
|
|
147
|
+
.map((p) => {
|
|
148
|
+
const name = text(p.name);
|
|
149
|
+
const type = p.type ? text(p.type) : '';
|
|
150
|
+
const optional = p.questionToken ? '?' : '';
|
|
151
|
+
const defaultVal = p.initializer ? `=${text(p.initializer)}` : '';
|
|
152
|
+
return type ? `${name}${optional}:${type}${defaultVal}` : `${name}${optional}${defaultVal}`;
|
|
153
|
+
})
|
|
154
|
+
.join(',');
|
|
155
|
+
}
|
|
156
|
+
function hasModifier(node, kind) {
|
|
157
|
+
const mods = ts.canHaveModifiers(node) ? ts.getModifiers(node) : undefined;
|
|
158
|
+
return mods?.some((m) => m.kind === kind) ?? false;
|
|
159
|
+
}
|
|
160
|
+
function quoteTypeIfNeeded(raw) {
|
|
161
|
+
if (raw === '')
|
|
162
|
+
return '';
|
|
163
|
+
return /\s/.test(raw) ? `"${raw.replace(/"/g, '\\"')}"` : raw;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Emit KERN lines for a single class member. Returns null when the member
|
|
167
|
+
* shape is unsupported (e.g. static block, getter/setter) — that causes the
|
|
168
|
+
* whole migration to abort for this const so nothing is silently dropped.
|
|
169
|
+
*/
|
|
170
|
+
/**
|
|
171
|
+
* Insert synthesised `this.x = x;` lines in the correct position:
|
|
172
|
+
* - If the body opens with `super(...)`, place the assigns immediately
|
|
173
|
+
* AFTER the first statement that contains the super call.
|
|
174
|
+
* - Otherwise, prepend to the top.
|
|
175
|
+
*
|
|
176
|
+
* A single super call can span multiple indented lines (a multi-line arg
|
|
177
|
+
* list). We detect the opening `super(` and advance past the matching `)`
|
|
178
|
+
* at paren-depth zero, treating that as the end of the super statement.
|
|
179
|
+
* This is a line-level heuristic — good enough for the shapes the migration
|
|
180
|
+
* actually accepts (TS already validated the class as syntactically clean).
|
|
181
|
+
*/
|
|
182
|
+
function spliceAssignsAfterSuper(body, assigns) {
|
|
183
|
+
if (assigns.length === 0)
|
|
184
|
+
return body;
|
|
185
|
+
if (body.length === 0)
|
|
186
|
+
return assigns;
|
|
187
|
+
// Find the first non-blank line that starts with `super(` (modulo
|
|
188
|
+
// leading whitespace).
|
|
189
|
+
let superStart = -1;
|
|
190
|
+
for (let i = 0; i < body.length; i++) {
|
|
191
|
+
const trimmed = body[i].trimStart();
|
|
192
|
+
if (trimmed === '')
|
|
193
|
+
continue;
|
|
194
|
+
if (/^super\s*\(/.test(trimmed)) {
|
|
195
|
+
superStart = i;
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
if (superStart === -1) {
|
|
200
|
+
return [...assigns, ...body];
|
|
201
|
+
}
|
|
202
|
+
// Advance through lines until paren depth returns to zero and the line
|
|
203
|
+
// looks terminated (ends with `;` or `)` at depth 0).
|
|
204
|
+
let depth = 0;
|
|
205
|
+
let end = superStart;
|
|
206
|
+
for (let i = superStart; i < body.length; i++) {
|
|
207
|
+
for (const ch of body[i]) {
|
|
208
|
+
if (ch === '(')
|
|
209
|
+
depth++;
|
|
210
|
+
else if (ch === ')')
|
|
211
|
+
depth--;
|
|
212
|
+
}
|
|
213
|
+
end = i;
|
|
214
|
+
if (depth <= 0)
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
return [...body.slice(0, end + 1), ...assigns, ...body.slice(end + 1)];
|
|
218
|
+
}
|
|
219
|
+
function emitMember(member, text, indent) {
|
|
220
|
+
if (ts.isPropertyDeclaration(member)) {
|
|
221
|
+
const rawType = member.type ? text(member.type) : '';
|
|
222
|
+
const rawInit = member.initializer ? text(member.initializer) : '';
|
|
223
|
+
const name = text(member.name);
|
|
224
|
+
const type = rawType ? quoteTypeIfNeeded(rawType) : '';
|
|
225
|
+
const priv = hasModifier(member, ts.SyntaxKind.PrivateKeyword) ? ' private=true' : '';
|
|
226
|
+
const readonly = hasModifier(member, ts.SyntaxKind.ReadonlyKeyword) ? ' readonly=true' : '';
|
|
227
|
+
const staticStr = hasModifier(member, ts.SyntaxKind.StaticKeyword) ? ' static=true' : '';
|
|
228
|
+
const init = rawInit ? ` default={{ ${rawInit} }}` : '';
|
|
229
|
+
return [`${indent}field name=${name}${type ? ` type=${type}` : ''}${priv}${staticStr}${readonly}${init}`];
|
|
230
|
+
}
|
|
231
|
+
if (ts.isConstructorDeclaration(member)) {
|
|
232
|
+
// Parameter-property shortcuts like `constructor(private x: T, readonly y: U)`
|
|
233
|
+
// implicitly declare fields. KERN params have no modifier slot, so we
|
|
234
|
+
// expand: each modified param becomes a sibling `field` line (inserted
|
|
235
|
+
// BEFORE the constructor) and the body gets a leading `this.x = x;`
|
|
236
|
+
// assignment. The constructor's visible param list keeps only the types.
|
|
237
|
+
const shortcutFields = [];
|
|
238
|
+
const assignLines = [];
|
|
239
|
+
for (const param of member.parameters) {
|
|
240
|
+
const paramMods = ts.canHaveModifiers(param) ? ts.getModifiers(param) : undefined;
|
|
241
|
+
const isPriv = paramMods?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword) ?? false;
|
|
242
|
+
const isPublic = paramMods?.some((m) => m.kind === ts.SyntaxKind.PublicKeyword) ?? false;
|
|
243
|
+
const isProtected = paramMods?.some((m) => m.kind === ts.SyntaxKind.ProtectedKeyword) ?? false;
|
|
244
|
+
const isReadonly = paramMods?.some((m) => m.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false;
|
|
245
|
+
if (!isPriv && !isPublic && !isProtected && !isReadonly)
|
|
246
|
+
continue;
|
|
247
|
+
// Protected is not a first-class KERN field modifier yet; fall back to
|
|
248
|
+
// plain (public-equivalent) to avoid silently dropping access-level
|
|
249
|
+
// intent on a rarer pattern.
|
|
250
|
+
const paramName = text(param.name);
|
|
251
|
+
let paramType = param.type ? text(param.type) : '';
|
|
252
|
+
// Optional parameter properties (`constructor(private x?: number)`)
|
|
253
|
+
// implicitly declare a field of type `T | undefined`. If we emit
|
|
254
|
+
// `field name=x type=number` the ctor assign `this.x = x;` would fail
|
|
255
|
+
// strictNullChecks (T | undefined → T). Widen the synthesised field
|
|
256
|
+
// type to include undefined so both sides stay consistent.
|
|
257
|
+
const isOptional = param.questionToken !== undefined;
|
|
258
|
+
if (isOptional && paramType) {
|
|
259
|
+
paramType = /[|&]/.test(paramType) ? `(${paramType}) | undefined` : `${paramType} | undefined`;
|
|
260
|
+
}
|
|
261
|
+
const privStr = isPriv ? ' private=true' : '';
|
|
262
|
+
const readStr = isReadonly ? ' readonly=true' : '';
|
|
263
|
+
const typeStr = paramType ? ` type=${quoteTypeIfNeeded(paramType)}` : '';
|
|
264
|
+
shortcutFields.push(`${indent}field name=${paramName}${typeStr}${privStr}${readStr}`);
|
|
265
|
+
assignLines.push(`this.${paramName} = ${paramName};`);
|
|
266
|
+
}
|
|
267
|
+
const params = formatParams(member.parameters, text);
|
|
268
|
+
const paramsStr = params ? ` params="${params}"` : '';
|
|
269
|
+
const lines = [...shortcutFields];
|
|
270
|
+
lines.push(`${indent}constructor${paramsStr}`);
|
|
271
|
+
const body = member.body;
|
|
272
|
+
const bodyText = body ? text(body).slice(1, -1) : '';
|
|
273
|
+
const trimmed = body ? dedentInteriorLines(bodyText) : '';
|
|
274
|
+
const originalLines = trimmed ? trimmed.split('\n') : [];
|
|
275
|
+
// TypeScript requires `super(...)` to be the FIRST statement in a derived
|
|
276
|
+
// class constructor before any `this.*` access. If the body opens with a
|
|
277
|
+
// super call, splice the synthesised assignments AFTER it; otherwise
|
|
278
|
+
// prepend at the top as usual.
|
|
279
|
+
const bodyLines = spliceAssignsAfterSuper(originalLines, assignLines);
|
|
280
|
+
if (bodyLines.length > 0) {
|
|
281
|
+
lines.push(`${indent} handler <<<`);
|
|
282
|
+
for (const line of bodyLines)
|
|
283
|
+
lines.push(`${indent} ${line}`);
|
|
284
|
+
lines.push(`${indent} >>>`);
|
|
285
|
+
}
|
|
286
|
+
return lines;
|
|
287
|
+
}
|
|
288
|
+
if (ts.isMethodDeclaration(member)) {
|
|
289
|
+
// Abstract methods have no body. The `method` schema has no abstract
|
|
290
|
+
// prop yet, and emitting a body-less method would drop the abstractness
|
|
291
|
+
// silently — bail so the class stays in its handler form for now.
|
|
292
|
+
if (hasModifier(member, ts.SyntaxKind.AbstractKeyword) || !member.body)
|
|
293
|
+
return null;
|
|
294
|
+
const params = formatParams(member.parameters, text);
|
|
295
|
+
const rawReturn = member.type ? text(member.type) : '';
|
|
296
|
+
const name = text(member.name);
|
|
297
|
+
const paramsStr = params ? ` params="${params}"` : '';
|
|
298
|
+
const returns = rawReturn ? quoteTypeIfNeeded(rawReturn) : '';
|
|
299
|
+
const returnsStr = returns ? ` returns=${returns}` : '';
|
|
300
|
+
const isAsync = hasModifier(member, ts.SyntaxKind.AsyncKeyword);
|
|
301
|
+
const isStatic = hasModifier(member, ts.SyntaxKind.StaticKeyword);
|
|
302
|
+
const isPriv = hasModifier(member, ts.SyntaxKind.PrivateKeyword);
|
|
303
|
+
const asyncStr = isAsync ? ' async=true' : '';
|
|
304
|
+
const staticStr = isStatic ? ' static=true' : '';
|
|
305
|
+
const privStr = isPriv ? ' private=true' : '';
|
|
306
|
+
const lines = [`${indent}method name=${name}${paramsStr}${returnsStr}${asyncStr}${staticStr}${privStr}`];
|
|
307
|
+
const body = member.body;
|
|
308
|
+
if (body) {
|
|
309
|
+
const bodyText = text(body).slice(1, -1);
|
|
310
|
+
const trimmed = dedentInteriorLines(bodyText);
|
|
311
|
+
lines.push(`${indent} handler <<<`);
|
|
312
|
+
for (const line of trimmed.split('\n'))
|
|
313
|
+
lines.push(`${indent} ${line}`);
|
|
314
|
+
lines.push(`${indent} >>>`);
|
|
315
|
+
}
|
|
316
|
+
return lines;
|
|
317
|
+
}
|
|
318
|
+
if (ts.isGetAccessorDeclaration(member)) {
|
|
319
|
+
if (!member.body)
|
|
320
|
+
return null;
|
|
321
|
+
const rawReturn = member.type ? text(member.type) : '';
|
|
322
|
+
const name = text(member.name);
|
|
323
|
+
const returns = rawReturn ? quoteTypeIfNeeded(rawReturn) : '';
|
|
324
|
+
const returnsStr = returns ? ` returns=${returns}` : '';
|
|
325
|
+
const isStatic = hasModifier(member, ts.SyntaxKind.StaticKeyword);
|
|
326
|
+
const isPriv = hasModifier(member, ts.SyntaxKind.PrivateKeyword);
|
|
327
|
+
const staticStr = isStatic ? ' static=true' : '';
|
|
328
|
+
const privStr = isPriv ? ' private=true' : '';
|
|
329
|
+
const lines = [`${indent}getter name=${name}${returnsStr}${privStr}${staticStr}`];
|
|
330
|
+
const bodyText = text(member.body).slice(1, -1);
|
|
331
|
+
const trimmed = dedentInteriorLines(bodyText);
|
|
332
|
+
lines.push(`${indent} handler <<<`);
|
|
333
|
+
for (const line of trimmed.split('\n'))
|
|
334
|
+
lines.push(`${indent} ${line}`);
|
|
335
|
+
lines.push(`${indent} >>>`);
|
|
336
|
+
return lines;
|
|
337
|
+
}
|
|
338
|
+
if (ts.isSetAccessorDeclaration(member)) {
|
|
339
|
+
if (!member.body)
|
|
340
|
+
return null;
|
|
341
|
+
const params = formatParams(member.parameters, text);
|
|
342
|
+
const name = text(member.name);
|
|
343
|
+
const paramsStr = params ? ` params="${params}"` : '';
|
|
344
|
+
const isStatic = hasModifier(member, ts.SyntaxKind.StaticKeyword);
|
|
345
|
+
const isPriv = hasModifier(member, ts.SyntaxKind.PrivateKeyword);
|
|
346
|
+
const staticStr = isStatic ? ' static=true' : '';
|
|
347
|
+
const privStr = isPriv ? ' private=true' : '';
|
|
348
|
+
const lines = [`${indent}setter name=${name}${paramsStr}${privStr}${staticStr}`];
|
|
349
|
+
const bodyText = text(member.body).slice(1, -1);
|
|
350
|
+
const trimmed = dedentInteriorLines(bodyText);
|
|
351
|
+
lines.push(`${indent} handler <<<`);
|
|
352
|
+
for (const line of trimmed.split('\n'))
|
|
353
|
+
lines.push(`${indent} ${line}`);
|
|
354
|
+
lines.push(`${indent} >>>`);
|
|
355
|
+
return lines;
|
|
356
|
+
}
|
|
357
|
+
// Static block / signature / index signature — bail.
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Strip the minimum leading indentation from every non-empty line, and trim
|
|
362
|
+
* a single leading/trailing empty line. Matches how kern compiles handler
|
|
363
|
+
* bodies back out (dedent helper in core/codegen/helpers.ts).
|
|
364
|
+
*/
|
|
365
|
+
function dedentInteriorLines(text) {
|
|
366
|
+
const lines = text.split('\n');
|
|
367
|
+
// Drop a single leading empty line from TS `{ \n ... \n }` formatting.
|
|
368
|
+
while (lines.length > 0 && lines[0].trim() === '')
|
|
369
|
+
lines.shift();
|
|
370
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === '')
|
|
371
|
+
lines.pop();
|
|
372
|
+
let min = Infinity;
|
|
373
|
+
for (const line of lines) {
|
|
374
|
+
if (line.trim() === '')
|
|
375
|
+
continue;
|
|
376
|
+
const leading = line.match(/^ */)?.[0].length ?? 0;
|
|
377
|
+
if (leading < min)
|
|
378
|
+
min = leading;
|
|
379
|
+
}
|
|
380
|
+
if (min === Infinity || min === 0)
|
|
381
|
+
return lines.join('\n');
|
|
382
|
+
return lines.map((l) => (l.trim() === '' ? '' : l.slice(min))).join('\n');
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Main entry: walk .kern source text, rewrite every
|
|
386
|
+
* `const ... handler <<< class X {...} >>>` block to a `class` node.
|
|
387
|
+
*/
|
|
388
|
+
export function rewriteClassBodies(source) {
|
|
389
|
+
const lines = source.split('\n');
|
|
390
|
+
const hits = [];
|
|
391
|
+
// Walk and collect replacements. Process in order, building the output in
|
|
392
|
+
// one pass to keep indent semantics stable.
|
|
393
|
+
const out = [];
|
|
394
|
+
let cursor = 0;
|
|
395
|
+
const blocks = findConstHandlerBlocks(lines);
|
|
396
|
+
for (const { block, bodyText } of blocks) {
|
|
397
|
+
const constName = readProp(block.headerRest, 'name');
|
|
398
|
+
const constType = readProp(block.headerRest, 'type');
|
|
399
|
+
if (!constName)
|
|
400
|
+
continue;
|
|
401
|
+
if (!constType || !PLACEHOLDER_TYPES.has(constType.trim()))
|
|
402
|
+
continue;
|
|
403
|
+
const cls = extractSoleClass(bodyText, constName);
|
|
404
|
+
if (!cls)
|
|
405
|
+
continue;
|
|
406
|
+
const { source: classSource, text } = binder(bodyText);
|
|
407
|
+
// Re-find the ClassDeclaration in the fresh binder so getText() uses the
|
|
408
|
+
// matching source file (extractSoleClass used a different file instance).
|
|
409
|
+
const clsStmt = classSource.statements.find((s) => ts.isClassDeclaration(s) && s.name?.getText(classSource) === constName);
|
|
410
|
+
if (!clsStmt)
|
|
411
|
+
continue;
|
|
412
|
+
const extendsClause = clsStmt.heritageClauses?.find((h) => h.token === ts.SyntaxKind.ExtendsKeyword);
|
|
413
|
+
const implementsClause = clsStmt.heritageClauses?.find((h) => h.token === ts.SyntaxKind.ImplementsKeyword);
|
|
414
|
+
const isAbstract = hasModifier(clsStmt, ts.SyntaxKind.AbstractKeyword);
|
|
415
|
+
const extendsStr = extendsClause
|
|
416
|
+
? ` extends=${extendsClause.types.map((t) => t.getText(classSource)).join(',')}`
|
|
417
|
+
: '';
|
|
418
|
+
const implementsStr = implementsClause
|
|
419
|
+
? ` implements=${implementsClause.types.map((t) => t.getText(classSource)).join(',')}`
|
|
420
|
+
: '';
|
|
421
|
+
const abstractStr = isAbstract ? ' abstract=true' : '';
|
|
422
|
+
const exportStr = headerIsExported(block.headerRest) ? ' export=true' : '';
|
|
423
|
+
const childIndent = `${block.headerIndent} `;
|
|
424
|
+
const memberLines = [];
|
|
425
|
+
let failed = false;
|
|
426
|
+
for (const member of clsStmt.members) {
|
|
427
|
+
const emitted = emitMember(member, text, childIndent);
|
|
428
|
+
if (emitted === null) {
|
|
429
|
+
failed = true;
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
memberLines.push(...emitted);
|
|
433
|
+
}
|
|
434
|
+
if (failed)
|
|
435
|
+
continue;
|
|
436
|
+
// Flush any lines before this block's start, then emit replacement.
|
|
437
|
+
while (cursor < block.startLine)
|
|
438
|
+
out.push(lines[cursor++]);
|
|
439
|
+
out.push(`${block.headerIndent}class name=${constName}${extendsStr}${implementsStr}${abstractStr}${exportStr}`);
|
|
440
|
+
out.push(...memberLines);
|
|
441
|
+
cursor = block.endLine + 1;
|
|
442
|
+
hits.push({
|
|
443
|
+
headerLine: block.startLine + 1,
|
|
444
|
+
literal: constName,
|
|
445
|
+
valueAttr: `class name=${constName} (${clsStmt.members.length} members)`,
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
// Flush remaining trailing lines.
|
|
449
|
+
while (cursor < lines.length)
|
|
450
|
+
out.push(lines[cursor++]);
|
|
451
|
+
return { hits, output: out.join('\n') };
|
|
452
|
+
}
|
|
453
|
+
//# sourceMappingURL=migrate-class-body.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate-class-body.js","sourceRoot":"","sources":["../../src/commands/migrate-class-body.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `kern migrate <migration> [dir]` - in-place migrations of .kern sources.
|
|
3
|
+
*
|
|
4
|
+
* `literal-const`
|
|
5
|
+
* Detects `const name=X ... handler <<< <single-line const expression> >>>`
|
|
6
|
+
* and rewrites to `const name=X ... value=...`. Primitive literals use the
|
|
7
|
+
* compact `value=42` form; strings and expressions use `value={{ ... }}` so
|
|
8
|
+
* generated TypeScript stays byte-equivalent to the original handler body.
|
|
9
|
+
*
|
|
10
|
+
* `fn-expr`
|
|
11
|
+
* Detects `fn name=X ... handler <<< <single-line function body> >>>` and
|
|
12
|
+
* rewrites to `fn name=X ... expr={{ ... }}`. The compiler emits the expr
|
|
13
|
+
* body verbatim inside the function, matching the original handler output.
|
|
14
|
+
*
|
|
15
|
+
* Dry-run by default; `--write` commits edits.
|
|
16
|
+
*/
|
|
17
|
+
import { type GapCategory, isInlineSafeExpression, isInlineSafeLiteral } from '@kernlang/core';
|
|
18
|
+
interface LiteralConstHit {
|
|
19
|
+
headerLine: number;
|
|
20
|
+
literal: string;
|
|
21
|
+
valueAttr: string;
|
|
22
|
+
}
|
|
23
|
+
interface LiteralConstResult {
|
|
24
|
+
hits: LiteralConstHit[];
|
|
25
|
+
output: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Line-based migration: matches the exact shape emitted by historical
|
|
29
|
+
* importers and by hand-written audiofacets files:
|
|
30
|
+
*
|
|
31
|
+
* const name=X type=T [more props] <- header, no trailing handler attr
|
|
32
|
+
* handler <<<
|
|
33
|
+
* <single literal line>
|
|
34
|
+
* >>>
|
|
35
|
+
*
|
|
36
|
+
* Indentation is tolerated (any whitespace), but the handler MUST be
|
|
37
|
+
* single-line content sandwiched by `<<<` and `>>>` with no other children.
|
|
38
|
+
* If the const header already contains `value=`, the handler is left alone.
|
|
39
|
+
*/
|
|
40
|
+
declare function rewriteLiteralConsts(source: string): LiteralConstResult;
|
|
41
|
+
/**
|
|
42
|
+
* Line-based migration for single-line `fn` handler bodies. Matches:
|
|
43
|
+
*
|
|
44
|
+
* [indent]fn name=X [props...] <- header, no handler= attr, no expr= attr
|
|
45
|
+
* [deeper] handler <<<
|
|
46
|
+
* [deeper] <single body line> <- preserved verbatim (incl. `return`, `;`)
|
|
47
|
+
* [deeper] >>>
|
|
48
|
+
*
|
|
49
|
+
* Rewrites to `fn name=X ... expr={{ <body> }}`. The codegen in
|
|
50
|
+
* generateFunction emits the expr verbatim inside the function body, so the
|
|
51
|
+
* compiled TypeScript is byte-identical to the handler form.
|
|
52
|
+
*
|
|
53
|
+
* Shares the same safety guards as rewriteLiteralConsts:
|
|
54
|
+
* - handler must be a child of the fn (strictly deeper indent),
|
|
55
|
+
* - no `}}` in the body (would close the expr block early),
|
|
56
|
+
* - header must not already carry expr= or handler=,
|
|
57
|
+
* - header must not contain an inline `#` or `//` comment,
|
|
58
|
+
* - body must not be empty after trim,
|
|
59
|
+
* - handler must have exactly ONE body line (no multi-line blocks).
|
|
60
|
+
*/
|
|
61
|
+
declare function rewriteFnExpr(source: string): LiteralConstResult;
|
|
62
|
+
export interface MigrationDef {
|
|
63
|
+
/** Canonical name — also the CLI subcommand. */
|
|
64
|
+
name: string;
|
|
65
|
+
/** Category this migration services. Today always `migratable`. */
|
|
66
|
+
category: GapCategory;
|
|
67
|
+
/** One-line description shown in help + `list` output. */
|
|
68
|
+
summary: string;
|
|
69
|
+
/** Pure rewriter — takes source, returns new source + per-hit breakdown. */
|
|
70
|
+
rewrite: (source: string) => LiteralConstResult;
|
|
71
|
+
}
|
|
72
|
+
export declare const MIGRATIONS: Record<string, MigrationDef>;
|
|
73
|
+
export declare function runMigrate(args: string[]): void;
|
|
74
|
+
export declare const __test__: {
|
|
75
|
+
isInlineSafeLiteral: typeof isInlineSafeLiteral;
|
|
76
|
+
isInlineSafeExpression: typeof isInlineSafeExpression;
|
|
77
|
+
rewriteLiteralConsts: typeof rewriteLiteralConsts;
|
|
78
|
+
rewriteFnExpr: typeof rewriteFnExpr;
|
|
79
|
+
};
|
|
80
|
+
export {};
|