@ts-for-gir/cli 4.0.0-beta.34 → 4.0.0-beta.35

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/bin/ts-for-gir CHANGED
@@ -12723,15 +12723,27 @@ var GirModule = class _GirModule {
12723
12723
  const clazzes = Array.from(this.members.values()).filter(
12724
12724
  (m) => m instanceof IntrospectedBaseClass
12725
12725
  );
12726
- const res = clazzes.map((m) => [
12726
+ for (const clazz of clazzes) {
12727
+ if (name.startsWith(clazz.name)) {
12728
+ const potentialCallbackName = name.slice(clazz.name.length);
12729
+ const callback = clazz.callbacks.find((c) => c.name === potentialCallbackName);
12730
+ if (callback) {
12731
+ return [clazz.name, callback.name];
12732
+ }
12733
+ }
12734
+ }
12735
+ const allMatches = clazzes.map((m) => [
12727
12736
  m,
12728
12737
  m.callbacks.find((c) => c.name === name || c.resolve_names.includes(name))
12729
- ]).find((r) => r[1] != null);
12730
- if (res) {
12731
- return [res[0].name, res[1].name];
12732
- } else {
12738
+ ]).filter((r) => r[1] != null);
12739
+ if (allMatches.length === 0) {
12733
12740
  return [null, name];
12734
12741
  }
12742
+ if (allMatches.length > 1) {
12743
+ this.log.warn(`Found multiple matches for ${name}: ${allMatches.map((m) => m[0].name).join(", ")}`);
12744
+ }
12745
+ const res = allMatches[0];
12746
+ return [res[0].name, res[1].name];
12735
12747
  }
12736
12748
  /**
12737
12749
  * This is an internal method to add TypeScript <reference>
@@ -16284,6 +16296,10 @@ function detectConflictType(ns, c, element, thisType) {
16284
16296
  if (fieldConflict) return fieldConflict;
16285
16297
  const propertyConflict = checkPropertyConflicts(ns, c, element, thisType);
16286
16298
  if (propertyConflict) return propertyConflict;
16299
+ if (element instanceof IntrospectedVirtualClassFunction) {
16300
+ const vfuncConflict = checkVfuncSignatureConflicts(ns, c, element, thisType);
16301
+ if (vfuncConflict) return vfuncConflict;
16302
+ }
16287
16303
  return checkFunctionNameConflicts(ns, c, element, thisType);
16288
16304
  }
16289
16305
  function checkFieldConflicts(c, element) {
@@ -16337,14 +16353,84 @@ function checkFunctionNameConflicts(ns, c, element, thisType) {
16337
16353
  })
16338
16354
  );
16339
16355
  }
16356
+ function checkVfuncSignatureConflicts(ns, c, element, thisType) {
16357
+ if (!(c instanceof IntrospectedInterface)) {
16358
+ return void 0;
16359
+ }
16360
+ return c.findParentMap((resolved_parent) => {
16361
+ const parentVirtualMethods = resolved_parent.members.filter(
16362
+ (m) => m instanceof IntrospectedVirtualClassFunction && m.name === element.name
16363
+ );
16364
+ for (const parentMethod of parentVirtualMethods) {
16365
+ if (isConflictingFunction(ns, thisType, element, resolved_parent.getType(), parentMethod)) {
16366
+ return 6 /* VFUNC_SIGNATURE_CONFLICT */;
16367
+ }
16368
+ }
16369
+ if (resolved_parent instanceof IntrospectedInterface) {
16370
+ const parentInterfaceVirtualMethods = resolved_parent.members.filter(
16371
+ (m) => m instanceof IntrospectedVirtualClassFunction && m.name === element.name
16372
+ );
16373
+ for (const parentMethod of parentInterfaceVirtualMethods) {
16374
+ if (isConflictingFunction(ns, thisType, element, resolved_parent.getType(), parentMethod)) {
16375
+ return 6 /* VFUNC_SIGNATURE_CONFLICT */;
16376
+ }
16377
+ }
16378
+ }
16379
+ return void 0;
16380
+ });
16381
+ }
16340
16382
  function createConflictElement(element, conflictType) {
16341
16383
  if (element instanceof IntrospectedField || element instanceof IntrospectedProperty) {
16342
16384
  return element.copy({
16343
16385
  type: new TypeConflict(element.type, conflictType)
16344
16386
  });
16345
16387
  }
16388
+ if (conflictType === 6 /* VFUNC_SIGNATURE_CONFLICT */ && element instanceof IntrospectedVirtualClassFunction) {
16389
+ return element;
16390
+ }
16346
16391
  return null;
16347
16392
  }
16393
+ function hasVfuncSignatureConflicts(ns, interfaceClass) {
16394
+ const thisType = interfaceClass.getType();
16395
+ const virtualMethods = interfaceClass.members.filter(
16396
+ (m) => m instanceof IntrospectedVirtualClassFunction
16397
+ );
16398
+ if (virtualMethods.length === 0) {
16399
+ return false;
16400
+ }
16401
+ for (const vmethod of virtualMethods) {
16402
+ const conflictType = checkVfuncSignatureConflicts(ns, interfaceClass, vmethod, thisType);
16403
+ if (conflictType === 6 /* VFUNC_SIGNATURE_CONFLICT */) {
16404
+ return true;
16405
+ }
16406
+ }
16407
+ const hasParentWithVirtualMethods = interfaceClass.someParent((parent) => {
16408
+ if (!(parent instanceof IntrospectedInterface)) {
16409
+ return false;
16410
+ }
16411
+ const parentHasVirtualMethods = parent.members.some((m) => m instanceof IntrospectedVirtualClassFunction);
16412
+ if (!parentHasVirtualMethods) {
16413
+ return false;
16414
+ }
16415
+ for (const vmethod of virtualMethods) {
16416
+ const parentVirtualMethods = parent.members.filter(
16417
+ (m) => m instanceof IntrospectedVirtualClassFunction && m.name === vmethod.name
16418
+ );
16419
+ for (const parentMethod of parentVirtualMethods) {
16420
+ const ourReturn = vmethod.return();
16421
+ const parentReturn = parentMethod.return();
16422
+ if (!ourReturn.equals(parentReturn)) {
16423
+ return true;
16424
+ }
16425
+ if (isConflictingFunction(ns, thisType, vmethod, parent.getType(), parentMethod)) {
16426
+ return true;
16427
+ }
16428
+ }
16429
+ }
16430
+ return false;
16431
+ });
16432
+ return hasParentWithVirtualMethods;
16433
+ }
16348
16434
 
16349
16435
  // ../lib/src/utils/generation.ts
16350
16436
  function generateMemberName(tsVar) {
@@ -18326,7 +18412,8 @@ var ModuleGenerator = class _ModuleGenerator extends FormatGenerator {
18326
18412
  const isGObject = node.someParent((p) => p.namespace.namespace === "GObject" && p.name === "Object");
18327
18413
  const functions = filterFunctionConflict(node.namespace, node, node.members, []);
18328
18414
  const hasStaticFunctions = functions.some((f) => f instanceof IntrospectedStaticClassFunction);
18329
- const hasNamespace = isGObject || hasStaticFunctions || node.callbacks.length > 0;
18415
+ const hasVirtualMethods = node.members.some((m) => m instanceof IntrospectedVirtualClassFunction);
18416
+ const hasNamespace = isGObject || hasStaticFunctions || node.callbacks.length > 0 || hasVirtualMethods;
18330
18417
  return [
18331
18418
  ...this.generateClassNamespaces(node),
18332
18419
  ...hasNamespace ? this.generateInterfaceNamespace(node) : [],
@@ -19012,6 +19099,76 @@ constructor(properties?: Partial<${girClass.name}.ConstructorProps>, ...args: an
19012
19099
  );
19013
19100
  return def;
19014
19101
  }
19102
+ /**
19103
+ * Generate virtual methods with overloads for interfaces that have conflicting signatures.
19104
+ * This is used when an interface can't inherit from Interface namespace due to signature conflicts.
19105
+ * @param girInterface The interface to generate virtual methods for
19106
+ * @param indentCount Indentation level
19107
+ */
19108
+ generateVirtualMethodOverloads(girInterface, indentCount = 1) {
19109
+ const def = [];
19110
+ const indent = generateIndent(indentCount);
19111
+ const virtualMethods = girInterface.members.filter(
19112
+ (m) => m instanceof IntrospectedVirtualClassFunction
19113
+ );
19114
+ if (virtualMethods.length === 0) {
19115
+ return def;
19116
+ }
19117
+ def.push("");
19118
+ def.push(`${indent}// Virtual methods - generated with overloads due to conflicts`);
19119
+ def.push("");
19120
+ const methodsByName = /* @__PURE__ */ new Map();
19121
+ for (const vmethod of virtualMethods) {
19122
+ const methods = methodsByName.get(vmethod.name) || [];
19123
+ methods.push(vmethod);
19124
+ methodsByName.set(vmethod.name, methods);
19125
+ }
19126
+ for (const [methodName, methods] of methodsByName) {
19127
+ const parentMethods = [];
19128
+ girInterface.someParent((parent) => {
19129
+ const parentVirtualMethods = parent.members.filter(
19130
+ (m) => m instanceof IntrospectedVirtualClassFunction && m.name === methodName
19131
+ );
19132
+ parentMethods.push(...parentVirtualMethods);
19133
+ return false;
19134
+ });
19135
+ const allMethods = [...methods, ...parentMethods];
19136
+ const uniqueSignatures = /* @__PURE__ */ new Map();
19137
+ for (const method of allMethods) {
19138
+ const signature = this.generateMethodSignature(method);
19139
+ if (!uniqueSignatures.has(signature)) {
19140
+ uniqueSignatures.set(signature, method);
19141
+ }
19142
+ }
19143
+ for (const method of uniqueSignatures.values()) {
19144
+ const methodDef = method.asString(this);
19145
+ if (methodDef.length > 0 && !methodDef[0].includes("@ignore")) {
19146
+ const docLines = [];
19147
+ if (method.doc) {
19148
+ docLines.push(...this.addGirDocComment(method.doc, [], indentCount));
19149
+ }
19150
+ if (docLines.length > 0) {
19151
+ const lastLine = docLines[docLines.length - 1];
19152
+ docLines[docLines.length - 1] = lastLine.replace(" */", ` * @ignore
19153
+ ${indent} */`);
19154
+ } else {
19155
+ docLines.push(`${indent}/** @ignore */`);
19156
+ }
19157
+ def.push(...docLines);
19158
+ }
19159
+ def.push(...methodDef);
19160
+ }
19161
+ }
19162
+ return def;
19163
+ }
19164
+ /**
19165
+ * Generate a signature string for a virtual method (used for deduplication)
19166
+ */
19167
+ generateMethodSignature(method) {
19168
+ const params = method.parameters.map((p) => `${p.name}:${p.type.print(this.namespace, this.config)}`).join(",");
19169
+ const returnType = method.return().print(this.namespace, this.config);
19170
+ return `${method.name}(${params}):${returnType}`;
19171
+ }
19015
19172
  generateClassSignalInterfaces(girClass, indentCount = 0) {
19016
19173
  const def = [];
19017
19174
  const _tsSignals = girClass.signals;
@@ -19155,6 +19312,9 @@ constructor(properties?: Partial<${girClass.name}.ConstructorProps>, ...args: an
19155
19312
  if (girClass instanceof IntrospectedClass) {
19156
19313
  bodyDef.push(...this.generateClassSignalInterfaces(girClass, indentCount + 1));
19157
19314
  }
19315
+ if (girClass instanceof IntrospectedInterface) {
19316
+ bodyDef.push(...this.generateVirtualInterface(girClass, indentCount + 1));
19317
+ }
19158
19318
  bodyDef.push(...this.generateClassCallbacks(girClass));
19159
19319
  bodyDef.push(...this.generateConstructPropsInterface(girClass, indentCount + 1));
19160
19320
  if (!bodyDef.length) {
@@ -19185,6 +19345,20 @@ constructor(properties?: Partial<${girClass.name}.ConstructorProps>, ...args: an
19185
19345
  ...superType ? [superType.node.getType().print(this.namespace, this.config)] : [],
19186
19346
  ..."implements" in resolution ? resolution.implements().map((i) => i.node.getType().print(this.namespace, this.config)) : []
19187
19347
  ];
19348
+ let shouldGenerateVirtualMethodOverloads = false;
19349
+ if (girClass instanceof IntrospectedInterface) {
19350
+ const hasVirtualMethods = girClass.members.some((m) => m instanceof IntrospectedVirtualClassFunction);
19351
+ if (hasVirtualMethods) {
19352
+ const hasConflicts = hasVfuncSignatureConflicts(this.namespace, girClass);
19353
+ if (hasConflicts) {
19354
+ shouldGenerateVirtualMethodOverloads = true;
19355
+ } else {
19356
+ const typeNames = girClass.generics.map((g) => g.type.identifier).filter((name) => name && name.length > 0);
19357
+ const genericTypeNames = typeNames.length > 0 ? `<${typeNames.join(", ")}>` : "";
19358
+ implementationNames.push(`${girClass.name}.Interface${genericTypeNames}`);
19359
+ }
19360
+ }
19361
+ }
19188
19362
  const ext = implementationNames.length ? ` extends ${implementationNames.join(", ")}` : "";
19189
19363
  const interfaceHead = `${girClass.name}${genericParameters}${ext}`;
19190
19364
  def.push(this.generateExport("interface", interfaceHead, "{"));
@@ -19196,11 +19370,68 @@ ${girClass.__ts__indexSignature}
19196
19370
  def.push(...this.generateClassProperties(girClass));
19197
19371
  def.push(...this.generateClassMemberFields(girClass));
19198
19372
  def.push(...this.generateClassMethods(girClass));
19199
- def.push(...this.generateClassVirtualMethods(girClass));
19373
+ if (!(girClass instanceof IntrospectedInterface) || shouldGenerateVirtualMethodOverloads) {
19374
+ if (shouldGenerateVirtualMethodOverloads && girClass instanceof IntrospectedInterface) {
19375
+ def.push(...this.generateVirtualMethodOverloads(girClass));
19376
+ } else {
19377
+ def.push(...this.generateClassVirtualMethods(girClass));
19378
+ }
19379
+ }
19200
19380
  def.push("}");
19201
19381
  def.push("");
19202
19382
  return def;
19203
19383
  }
19384
+ /**
19385
+ * Generates a virtual-methods-only interface for proper GObject interface implementation.
19386
+ * This interface contains only the virtual methods (vfunc_*) that need to be implemented
19387
+ * when creating a class that implements a GObject interface.
19388
+ */
19389
+ generateVirtualInterface(girClass, indentCount = 1) {
19390
+ const def = [];
19391
+ if (!girClass) return def;
19392
+ const indent = generateIndent(indentCount);
19393
+ const virtualMethods = girClass.members.filter(
19394
+ (m) => m instanceof IntrospectedVirtualClassFunction
19395
+ );
19396
+ if (virtualMethods.length === 0) {
19397
+ return def;
19398
+ }
19399
+ const resolution = girClass.resolveParents();
19400
+ const parentInterfaces = [];
19401
+ const parentResolution = resolution.extends();
19402
+ if (parentResolution && parentResolution.node instanceof IntrospectedInterface) {
19403
+ const parentInterface = parentResolution.node;
19404
+ const parentTypeIdentifier = parentResolution.identifier.resolveIdentifier(this.namespace, this.config)?.print(this.namespace, this.config);
19405
+ const parentHasVirtualMethods = parentInterface.members.some(
19406
+ (m) => m instanceof IntrospectedVirtualClassFunction
19407
+ );
19408
+ if (parentTypeIdentifier && parentHasVirtualMethods) {
19409
+ parentInterfaces.push(`${parentTypeIdentifier}.Interface`);
19410
+ }
19411
+ }
19412
+ let extendsClause = "";
19413
+ if (parentInterfaces.length > 0) {
19414
+ extendsClause = ` extends ${parentInterfaces.join(", ")}`;
19415
+ }
19416
+ const genericParameters = this.generateGenericParameters(girClass.generics);
19417
+ def.push(`${indent}/**`);
19418
+ def.push(`${indent} * Interface for implementing ${girClass.name}.`);
19419
+ def.push(`${indent} * Contains only the virtual methods that need to be implemented.`);
19420
+ def.push(`${indent} */`);
19421
+ def.push(`${indent}interface Interface${genericParameters}${extendsClause} {`);
19422
+ if (virtualMethods.length > 0) {
19423
+ def.push(
19424
+ ...this.generateFunctions(
19425
+ filterFunctionConflict(girClass.namespace, girClass, virtualMethods, []),
19426
+ indentCount + 1,
19427
+ "Virtual methods"
19428
+ )
19429
+ );
19430
+ }
19431
+ def.push(`${indent}}`);
19432
+ def.push("");
19433
+ return def;
19434
+ }
19204
19435
  extends(node) {
19205
19436
  const { namespace: ns, options: options2 } = this;
19206
19437
  if (node.superType) {
@@ -2,15 +2,15 @@
2
2
 
3
3
  /**
4
4
  * CLI Wrapper for TypeScript Execution
5
- *
5
+ *
6
6
  * This wrapper is required to execute our CLI tool with the necessary Node.js parameters.
7
- * Due to "type": "module" specified in package.json, Node.js only accepts .js files
7
+ * Due to "type": "module" specified in package.json, Node.js only accepts .js files
8
8
  * and rejects .ts or .sh files directly. This wrapper bridges that gap by:
9
- *
9
+ *
10
10
  * 1. Providing a .js entry point that Node.js can execute
11
11
  * 2. Spawning the actual TypeScript file with experimental Node.js flags
12
12
  * 3. Enabling TypeScript execution without compilation step
13
- *
13
+ *
14
14
  * The experimental flags used:
15
15
  * - --experimental-specifier-resolution=node: Enables Node.js-style module resolution
16
16
  * - --experimental-strip-types: Strips TypeScript types during execution
@@ -18,26 +18,26 @@
18
18
  * - --no-warnings: Suppresses experimental feature warnings
19
19
  */
20
20
 
21
- import { spawn } from 'node:child_process';
22
- import { fileURLToPath } from 'node:url';
23
- import { dirname, resolve } from 'node:path';
21
+ import { spawn } from "node:child_process";
22
+ import { dirname, resolve } from "node:path";
23
+ import { fileURLToPath } from "node:url";
24
24
 
25
25
  // Get the current file's directory in ES module context
26
26
  const __filename = fileURLToPath(import.meta.url);
27
27
  const __dirname = dirname(__filename);
28
28
 
29
29
  // Resolve the path to the actual TypeScript CLI entry point
30
- const tsPath = resolve(__dirname, '../src/start.ts');
30
+ const tsPath = resolve(__dirname, "../src/start.ts");
31
31
 
32
32
  // Configure Node.js arguments for TypeScript execution
33
33
  const nodeArgs = [
34
- '--experimental-specifier-resolution=node',
35
- '--experimental-strip-types',
36
- '--experimental-transform-types',
37
- '--no-warnings',
38
- tsPath,
39
- ...process.argv.slice(2), // Forward all CLI arguments to the TypeScript file
34
+ "--experimental-specifier-resolution=node",
35
+ "--experimental-strip-types",
36
+ "--experimental-transform-types",
37
+ "--no-warnings",
38
+ tsPath,
39
+ ...process.argv.slice(2), // Forward all CLI arguments to the TypeScript file
40
40
  ];
41
41
 
42
42
  // Spawn the Node.js process with TypeScript support and inherit stdio
43
- spawn('node', nodeArgs, { stdio: 'inherit' });
43
+ spawn("node", nodeArgs, { stdio: "inherit" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ts-for-gir/cli",
3
- "version": "4.0.0-beta.34",
3
+ "version": "4.0.0-beta.35",
4
4
  "description": "TypeScript type definition generator for GObject introspection GIR files",
5
5
  "main": "src/index.ts",
6
6
  "module": "src/index.ts",
@@ -53,13 +53,13 @@
53
53
  ".": "./src/index.ts"
54
54
  },
55
55
  "devDependencies": {
56
- "@gi.ts/parser": "^4.0.0-beta.34",
57
- "@ts-for-gir/generator-base": "^4.0.0-beta.34",
58
- "@ts-for-gir/generator-html-doc": "^4.0.0-beta.34",
59
- "@ts-for-gir/generator-json": "^4.0.0-beta.34",
60
- "@ts-for-gir/generator-typescript": "^4.0.0-beta.34",
61
- "@ts-for-gir/lib": "^4.0.0-beta.34",
62
- "@ts-for-gir/reporter": "^4.0.0-beta.34",
56
+ "@gi.ts/parser": "^4.0.0-beta.35",
57
+ "@ts-for-gir/generator-base": "^4.0.0-beta.35",
58
+ "@ts-for-gir/generator-html-doc": "^4.0.0-beta.35",
59
+ "@ts-for-gir/generator-json": "^4.0.0-beta.35",
60
+ "@ts-for-gir/generator-typescript": "^4.0.0-beta.35",
61
+ "@ts-for-gir/lib": "^4.0.0-beta.35",
62
+ "@ts-for-gir/reporter": "^4.0.0-beta.35",
63
63
  "@types/ejs": "^3.1.5",
64
64
  "@types/inquirer": "^9.0.9",
65
65
  "@types/node": "^24.2.1",
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "@inquirer/prompts": "^7.8.2",
73
- "@ts-for-gir/templates": "^4.0.0-beta.34",
73
+ "@ts-for-gir/templates": "^4.0.0-beta.35",
74
74
  "colorette": "^2.0.20",
75
75
  "cosmiconfig": "^9.0.0",
76
76
  "ejs": "^3.1.10",