Skip to content

Commit 1b64a2a

Browse files
author
brett-bonner_infodesk
committed
fix(generator): surface the migration note on mixed classes; docs example corrections (review round 1)
- The migration note now renders whenever instance members were omitted, not only when the class ends up empty — a surviving @staticmethod no longer hides that instance API vanished. New discriminating test. - docs/examples: replace the invalid module-level import of Counter's most_common with statistics.median, a real top-level function. - getting-started/llms: numeric output comments match JS interpolation (5.86, not 5.860). - transport.test: cover all three removed methods in the protocol-guard rejection test, not just instantiate.
1 parent 566ba2d commit 1b64a2a

6 files changed

Lines changed: 63 additions & 26 deletions

File tree

docs/examples/index.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ console.log(await sin(pi / 4));
5959

6060
## Value-returning APIs
6161

62-
v0.9 generated wrappers do not keep live Python class instances. Expose an operation as a
63-
value-returning module function instead:
62+
v0.9 generated wrappers do not keep live Python class instances. Expose an
63+
operation as a value-returning module function instead:
6464

6565
```ts
66-
import { most_common } from './generated/collections.generated.js';
66+
import { median } from './generated/statistics.generated.js';
6767

68-
console.log(await most_common([1, 2, 2], 1));
68+
console.log(await median([1, 2, 2])); // 2
6969
```
7070

7171
## More Docs

docs/guide/getting-started.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ async function demo() {
212212
const sum = await add(3.14159, 2.71828, 3);
213213
const product = await multiply(sum, 2, 3);
214214

215-
console.log(`Sum: ${sum}`); // Sum: 5.860
216-
console.log(`Product: ${product}`); // Product: 11.720
215+
console.log(`Sum: ${sum}`); // Sum: 5.86
216+
console.log(`Product: ${product}`); // Product: 11.72
217217
}
218218
```
219219

docs/public/llms-full.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ async function demo() {
271271
const sum = await add(3.14159, 2.71828, 3);
272272
const product = await multiply(sum, 2, 3);
273273

274-
console.log(`Sum: ${sum}`); // Sum: 5.860
275-
console.log(`Product: ${product}`); // Product: 11.720
274+
console.log(`Sum: ${sum}`); // Sum: 5.86
275+
console.log(`Product: ${product}`); // Product: 11.72
276276
}
277277
```
278278

@@ -3463,9 +3463,9 @@ v0.9 generated wrappers do not keep live Python class instances. Expose an opera
34633463
value-returning module function instead:
34643464

34653465
```ts
3466-
import { most_common } from './generated/collections.generated.js';
3466+
import { median } from './generated/statistics.generated.js';
34673467

3468-
console.log(await most_common([1, 2, 2], 1));
3468+
console.log(await median([1, 2, 2])); // 2
34693469
```
34703470

34713471
## More Docs

src/core/generator.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -798,13 +798,11 @@ ${callPrelude}${guards} return ${callExpr};
798798
// The constructor counts: a class whose only member was __init__ loses
799799
// create(), so it needs the migration note as much as one with methods.
800800
const omittedInstanceMembers =
801-
cls.methods.some(
802-
method => method.methodKind !== 'class' && method.methodKind !== 'static'
803-
) || (cls.accessors?.length ?? 0) > 0;
804-
const migrationNote =
805-
methodBodies.length === 0 && omittedInstanceMembers
806-
? ' // NOTE: Instance members are not generated in v0.9; migrate this API to value-returning module functions.\n'
807-
: '';
801+
cls.methods.some(method => method.methodKind !== 'class' && method.methodKind !== 'static') ||
802+
(cls.accessors?.length ?? 0) > 0;
803+
const migrationNote = omittedInstanceMembers
804+
? ' // NOTE: Instance members are not generated in v0.9; migrate this API to value-returning module functions.\n'
805+
: '';
808806
const ts = `${jsdoc}export class ${cname}${classTypeParamDecl} {
809807
${migrationNote}${methodsSection}
810808
}

test/generator.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,42 @@ describe('CodeGenerator', () => {
13581358
expect(code.declaration).not.toContain('get petName');
13591359
});
13601360

1361+
it('keeps the migration note when static methods survive but instance methods are dropped', () => {
1362+
const method = (name: string, methodKind?: string) => ({
1363+
name,
1364+
signature: {
1365+
parameters: [],
1366+
returnType: { kind: 'primitive', name: 'int' },
1367+
isAsync: false,
1368+
isGenerator: false,
1369+
},
1370+
docstring: undefined,
1371+
decorators: [],
1372+
isAsync: false,
1373+
isGenerator: false,
1374+
...(methodKind ? { methodKind } : {}),
1375+
returnType: { kind: 'primitive', name: 'int' },
1376+
parameters: [],
1377+
});
1378+
1379+
const code = gen.generateClassWrapper(
1380+
{
1381+
name: 'Mixed',
1382+
bases: [],
1383+
methods: [method('helper', 'static'), method('compute')],
1384+
properties: [],
1385+
docstring: undefined,
1386+
decorators: [],
1387+
} as any,
1388+
'mixed_mod'
1389+
);
1390+
1391+
expect(code.typescript).toContain('static async helper');
1392+
expect(code.typescript).not.toContain('compute(');
1393+
expect(code.typescript).toContain('Instance members are not generated in v0.9');
1394+
expect(code.declaration).toContain('Instance members are not generated in v0.9');
1395+
});
1396+
13611397
it('emits the same empty class for implicit and explicit instance methods', () => {
13621398
const base = {
13631399
name: 'Widget',

test/transport.test.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -239,15 +239,18 @@ describe('Transport Interface', () => {
239239
expect(isProtocolMessage(msg)).toBe(true);
240240
});
241241

242-
it('rejects removed instance protocol messages', () => {
243-
const msg = {
244-
id: 1,
245-
protocol: PROTOCOL_ID,
246-
method: 'instantiate',
247-
params: { module: 'mymodule', className: 'MyClass', args: [] },
248-
};
249-
expect(isProtocolMessage(msg)).toBe(false);
250-
});
242+
it.each(['instantiate', 'call_method', 'dispose_instance'])(
243+
'rejects removed instance protocol message: %s',
244+
method => {
245+
const msg = {
246+
id: 1,
247+
protocol: PROTOCOL_ID,
248+
method,
249+
params: { module: 'mymodule', className: 'MyClass', args: [] },
250+
};
251+
expect(isProtocolMessage(msg)).toBe(false);
252+
}
253+
);
251254

252255
it('returns false for null', () => {
253256
expect(isProtocolMessage(null)).toBe(false);

0 commit comments

Comments
 (0)