@ts-for-gir/generator-json 4.0.0-beta.41 → 4.0.0-beta.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-for-gir/generator-json",
3
- "version": "4.0.0-beta.41",
3
+ "version": "4.0.0-beta.42",
4
4
  "description": "JSON generator for ts-for-gir",
5
5
  "main": "src/index.ts",
6
6
  "module": "src/index.ts",
@@ -36,17 +36,17 @@
36
36
  "json"
37
37
  ],
38
38
  "devDependencies": {
39
- "@ts-for-gir/tsconfig": "^4.0.0-beta.41",
39
+ "@ts-for-gir/tsconfig": "^4.0.0-beta.42",
40
40
  "@types/node": "^24.12.0",
41
41
  "typescript": "^5.9.3"
42
42
  },
43
43
  "dependencies": {
44
- "@gi.ts/parser": "^4.0.0-beta.41",
45
- "@ts-for-gir/generator-base": "^4.0.0-beta.41",
46
- "@ts-for-gir/generator-typescript": "^4.0.0-beta.41",
47
- "@ts-for-gir/gir-module-metadata": "^4.0.0-beta.41",
48
- "@ts-for-gir/lib": "^4.0.0-beta.41",
49
- "@ts-for-gir/reporter": "^4.0.0-beta.41",
44
+ "@gi.ts/parser": "^4.0.0-beta.42",
45
+ "@ts-for-gir/generator-base": "^4.0.0-beta.42",
46
+ "@ts-for-gir/generator-typescript": "^4.0.0-beta.42",
47
+ "@ts-for-gir/gir-module-metadata": "^4.0.0-beta.42",
48
+ "@ts-for-gir/lib": "^4.0.0-beta.42",
49
+ "@ts-for-gir/reporter": "^4.0.0-beta.42",
50
50
  "typedoc": "^0.28.17"
51
51
  }
52
52
  }
@@ -107,7 +107,7 @@ export interface GirNamespaceMetadata {
107
107
  cPrefixes: string[];
108
108
  libraryVersion: string;
109
109
  dependencies: Array<{ namespace: string; version: string }>;
110
- /** NPM package version (e.g. "4.20.3-4.0.0-beta.41") */
110
+ /** NPM package version (e.g. "4.20.3-4.0.0-beta.42") */
111
111
  packageVersion?: string;
112
112
  /** Human-readable display name, e.g. "GTK" */
113
113
  displayName?: string;
@@ -14,6 +14,7 @@ import {
14
14
  normalizePath,
15
15
  type OptionsReader,
16
16
  type ProjectReflection,
17
+ ReferenceReflection,
17
18
  ReflectionCategory,
18
19
  Serializer,
19
20
  TSConfigReader,
@@ -199,7 +200,7 @@ export class TypeDocPipeline {
199
200
  * converts each package separately, then merges them into one ProjectReflection.
200
201
  */
201
202
  async createCombinedTypeDocApp(): Promise<TypeDocAppResult> {
202
- return this.bootstrapAndConvert(
203
+ const result = await this.bootstrapAndConvert(
203
204
  {
204
205
  entryPoints: [join(this.tempDir, "*")],
205
206
  entryPointStrategy: "packages",
@@ -213,6 +214,8 @@ export class TypeDocPipeline {
213
214
  },
214
215
  [new TSConfigReader()],
215
216
  );
217
+ this.fixExportImportReferences(result.project);
218
+ return result;
216
219
  }
217
220
 
218
221
  /**
@@ -235,7 +238,9 @@ export class TypeDocPipeline {
235
238
  // Register deserializer for merge mode — restores GIR metadata from JSON
236
239
  app.deserializer.addDeserializer(new GirMetadataDeserializer());
237
240
 
238
- return this.convertApp(app, "merged documentation");
241
+ const result = await this.convertApp(app, "merged documentation");
242
+ this.fixExportImportReferences(result.project);
243
+ return result;
239
244
  }
240
245
 
241
246
  async cleanup(): Promise<void> {
@@ -488,6 +493,77 @@ export class TypeDocPipeline {
488
493
  return dotIdx > 0 ? name.slice(0, dotIdx) : name;
489
494
  }
490
495
 
496
+ /**
497
+ * Fix ReferenceReflection targets broken by TypeDoc's handling of
498
+ * `export import X = Y.Z` statements.
499
+ *
500
+ * TypeDoc may resolve all such re-exports within a namespace to the same
501
+ * target reflection (e.g. every Cairo enum points to Status). This method
502
+ * detects the mismatch and corrects each reference's internal target ID.
503
+ */
504
+ private fixExportImportReferences(project: ProjectReflection): void {
505
+ // Step 1: Identify targets that are shared by multiple references with
506
+ // different names — the specific bug pattern where TypeDoc resolves all
507
+ // `export import X = Y.Z` statements to the same target.
508
+ const refsByTargetId = new Map<number, ReferenceReflection[]>();
509
+ for (const r of Object.values(project.reflections)) {
510
+ if (!(r instanceof ReferenceReflection)) continue;
511
+ const target = r.tryGetTargetReflectionDeep();
512
+ if (!target) continue;
513
+ let list = refsByTargetId.get(target.id);
514
+ if (!list) {
515
+ list = [];
516
+ refsByTargetId.set(target.id, list);
517
+ }
518
+ list.push(r);
519
+ }
520
+
521
+ // Only consider targets where multiple differently-named references
522
+ // point to the same reflection — a single reference with a different
523
+ // name (e.g. `default → Gio`) is intentional, not a bug.
524
+ const brokenTargetIds = new Set<number>();
525
+ for (const [targetId, refs] of refsByTargetId) {
526
+ const distinctNames = new Set(refs.map((r) => r.name));
527
+ if (distinctNames.size > 1) {
528
+ brokenTargetIds.add(targetId);
529
+ }
530
+ }
531
+
532
+ if (brokenTargetIds.size === 0) return;
533
+
534
+ // Step 2: Build a lookup of non-reference reflections by name.
535
+ const nonRefByName = new Map<string, Array<{ id: number; kind: number }>>();
536
+ for (const refl of Object.values(project.reflections)) {
537
+ if (refl.isReference()) continue;
538
+ let list = nonRefByName.get(refl.name);
539
+ if (!list) {
540
+ list = [];
541
+ nonRefByName.set(refl.name, list);
542
+ }
543
+ list.push({ id: refl.id, kind: refl.kind });
544
+ }
545
+
546
+ // Step 3: Fix only the references pointing to broken (shared) targets.
547
+ for (const r of Object.values(project.reflections)) {
548
+ if (!(r instanceof ReferenceReflection)) continue;
549
+
550
+ const target = r.tryGetTargetReflectionDeep();
551
+ if (!target || target.name === r.name) continue;
552
+ if (!brokenTargetIds.has(target.id)) continue;
553
+
554
+ const candidates = nonRefByName.get(r.name);
555
+ if (!candidates?.length) continue;
556
+
557
+ // Prefer a candidate with the same kind as the (wrong) target.
558
+ // Fall back to the first candidate if kinds don't match.
559
+ const correctTarget = candidates.find((c) => c.kind === target.kind) ?? candidates[0];
560
+
561
+ // ReferenceReflection._target is private; direct assignment
562
+ // is the only way to fix the resolved ID after conversion.
563
+ (r as unknown as { _target: number })._target = correctTarget.id;
564
+ }
565
+ }
566
+
491
567
  /** Register GIR metadata serializer and namespace-level metadata on a TypeDoc app. */
492
568
  private registerGirMetadata(app: Application, module: GirModule): void {
493
569
  const index = buildGirLookupIndex(module);