@gtkx/gir 0.5.2 → 0.6.0

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": "@gtkx/gir",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "description": "GObject Introspection file parser for GTKX",
5
5
  "keywords": [
6
6
  "gtk",
package/src/parser.ts CHANGED
@@ -57,8 +57,9 @@ const ARRAY_ELEMENT_PATHS = new Set<string>([
57
57
  const extractDoc = (node: Record<string, unknown>): string | undefined => {
58
58
  const doc = node.doc as Record<string, unknown> | undefined;
59
59
  if (!doc) return undefined;
60
- const text = doc["#text"] as string | undefined;
61
- return text?.trim();
60
+ const text = doc["#text"];
61
+ if (typeof text !== "string") return undefined;
62
+ return text.trim();
62
63
  };
63
64
 
64
65
  const ensureArray = (value: unknown): Record<string, unknown>[] =>
package/src/types.ts CHANGED
@@ -398,14 +398,17 @@ export interface RegisteredType {
398
398
  glibTypeName?: string;
399
399
  }
400
400
 
401
- const CLASS_RENAMES = new Map<string, string>([
402
- ["Error", "GError"],
403
- ["Object", "GObject"],
404
- ]);
401
+ const CLASS_RENAMES = new Map<string, string>([["Error", "GError"]]);
405
402
 
406
- const normalizeTypeName = (name: string): string => {
403
+ const normalizeTypeName = (name: string, namespace: string): string => {
407
404
  const pascalName = toPascalCase(name);
408
- return CLASS_RENAMES.get(pascalName) ?? pascalName;
405
+ if (CLASS_RENAMES.has(pascalName)) {
406
+ return CLASS_RENAMES.get(pascalName) as string;
407
+ }
408
+ if (pascalName === "Object") {
409
+ return namespace === "GObject" ? "GObject" : `${namespace}Object`;
410
+ }
411
+ return pascalName;
409
412
  };
410
413
 
411
414
  /**
@@ -421,7 +424,7 @@ export class TypeRegistry {
421
424
  * @param name - The class name
422
425
  */
423
426
  registerType(namespace: string, name: string): void {
424
- const transformedName = normalizeTypeName(name);
427
+ const transformedName = normalizeTypeName(name, namespace);
425
428
  this.types.set(`${namespace}.${name}`, {
426
429
  kind: "class",
427
430
  name,
@@ -436,7 +439,7 @@ export class TypeRegistry {
436
439
  * @param name - The interface name
437
440
  */
438
441
  registerInterface(namespace: string, name: string): void {
439
- const transformedName = normalizeTypeName(name);
442
+ const transformedName = normalizeTypeName(name, namespace);
440
443
  this.types.set(`${namespace}.${name}`, {
441
444
  kind: "class",
442
445
  name,
@@ -467,7 +470,7 @@ export class TypeRegistry {
467
470
  * @param glibTypeName - Optional GLib type name for boxed type handling
468
471
  */
469
472
  registerRecord(namespace: string, name: string, glibTypeName?: string): void {
470
- const transformedName = normalizeTypeName(name);
473
+ const transformedName = normalizeTypeName(name, namespace);
471
474
  this.types.set(`${namespace}.${name}`, {
472
475
  kind: "record",
473
476
  name,
@@ -503,15 +506,28 @@ export class TypeRegistry {
503
506
 
504
507
  /**
505
508
  * Resolves a type name within a namespace context.
509
+ * First tries the current namespace, then searches all namespaces.
506
510
  * @param name - The type name (may or may not be qualified)
507
- * @param currentNamespace - The namespace to use if name is not qualified
511
+ * @param currentNamespace - The namespace to try first if name is not qualified
508
512
  * @returns The registered type or undefined if not found
509
513
  */
510
514
  resolveInNamespace(name: string, currentNamespace: string): RegisteredType | undefined {
511
515
  if (name.includes(".")) {
512
516
  return this.resolve(name);
513
517
  }
514
- return this.resolve(`${currentNamespace}.${name}`);
518
+
519
+ const inCurrent = this.resolve(`${currentNamespace}.${name}`);
520
+ if (inCurrent) {
521
+ return inCurrent;
522
+ }
523
+
524
+ for (const type of this.types.values()) {
525
+ if (type.name === name || type.transformedName === name) {
526
+ return type;
527
+ }
528
+ }
529
+
530
+ return undefined;
515
531
  }
516
532
 
517
533
  /**
@@ -845,6 +861,65 @@ export class TypeMapper {
845
861
  return basicType;
846
862
  }
847
863
 
864
+ if (this.typeRegistry && this.currentNamespace && !girType.name.includes(".")) {
865
+ const registered = this.typeRegistry.resolveInNamespace(girType.name, this.currentNamespace);
866
+ if (registered) {
867
+ const isExternal = registered.namespace !== this.currentNamespace;
868
+ const qualifiedName = isExternal
869
+ ? `${registered.namespace}.${registered.transformedName}`
870
+ : registered.transformedName;
871
+ const externalType: ExternalTypeUsage | undefined = isExternal
872
+ ? {
873
+ namespace: registered.namespace,
874
+ name: registered.name,
875
+ transformedName: registered.transformedName,
876
+ kind: registered.kind,
877
+ }
878
+ : undefined;
879
+ if (isExternal) {
880
+ this.onExternalTypeUsed?.(externalType as ExternalTypeUsage);
881
+ } else if (registered.kind === "class" || registered.kind === "interface") {
882
+ this.onSameNamespaceClassUsed?.(registered.transformedName, registered.name);
883
+ } else if (registered.kind === "enum") {
884
+ this.onEnumUsed?.(registered.transformedName);
885
+ } else if (registered.kind === "record") {
886
+ this.onRecordUsed?.(registered.transformedName);
887
+ }
888
+
889
+ if (registered.kind === "enum") {
890
+ return {
891
+ ts: qualifiedName,
892
+ ffi: { type: "int", size: 32, unsigned: false },
893
+ externalType,
894
+ };
895
+ }
896
+
897
+ if (registered.kind === "record") {
898
+ return {
899
+ ts: qualifiedName,
900
+ ffi: {
901
+ type: "boxed",
902
+ borrowed: isReturn,
903
+ innerType: registered.glibTypeName ?? registered.transformedName,
904
+ },
905
+ externalType,
906
+ kind: registered.kind,
907
+ };
908
+ }
909
+
910
+ if (registered.kind === "callback") {
911
+ return POINTER_TYPE;
912
+ }
913
+
914
+ return {
915
+ ts: qualifiedName,
916
+ ffi: { type: "gobject", borrowed: isReturn },
917
+ externalType,
918
+ kind: registered.kind,
919
+ };
920
+ }
921
+ }
922
+
848
923
  if (this.enumNames.has(girType.name)) {
849
924
  const transformedName = this.enumTransforms.get(girType.name) ?? girType.name;
850
925
  this.onEnumUsed?.(transformedName);
@@ -1056,7 +1131,7 @@ export class TypeMapper {
1056
1131
  };
1057
1132
  }
1058
1133
 
1059
- if (param.type.name === "GLib.DestroyNotify") {
1134
+ if (param.type.name === "GLib.DestroyNotify" || param.type.name === "DestroyNotify") {
1060
1135
  return {
1061
1136
  ts: "() => void",
1062
1137
  ffi: {
@@ -1066,7 +1141,7 @@ export class TypeMapper {
1066
1141
  };
1067
1142
  }
1068
1143
 
1069
- if (param.type.name === "GLib.SourceFunc") {
1144
+ if (param.type.name === "GLib.SourceFunc" || param.type.name === "SourceFunc") {
1070
1145
  return {
1071
1146
  ts: "() => boolean",
1072
1147
  ffi: {