diff --git a/spine-c-new/codegen/src/exclusions.ts b/spine-c-new/codegen/src/exclusions.ts index 1cfe525c9..9b7e1e035 100644 --- a/spine-c-new/codegen/src/exclusions.ts +++ b/spine-c-new/codegen/src/exclusions.ts @@ -1,17 +1,40 @@ import * as fs from 'fs'; import { Exclusion } from './types'; +/** + * Loads exclusions from a text file. + * + * File format: + * - Lines starting with # are comments + * - Empty lines are ignored + * - Type exclusions: "type: TypeName" + * - Method exclusions: "method: TypeName::methodName [const]" + * + * Examples: + * ``` + * # Exclude entire types + * type: SkeletonClipping + * type: Triangulator + * + * # Exclude specific methods + * method: AnimationState::setListener + * method: AnimationState::addListener + * + * # Exclude only const version of a method + * method: BoneData::getSetupPose const + * ``` + */ export function loadExclusions(filePath: string): Exclusion[] { const content = fs.readFileSync(filePath, 'utf8'); const lines = content.split('\n'); const exclusions: Exclusion[] = []; - + for (const line of lines) { const trimmed = line.trim(); - + // Skip empty lines and comments if (!trimmed || trimmed.startsWith('#')) continue; - + // Parse type exclusion const typeMatch = trimmed.match(/^type:\s*(.+)$/); if (typeMatch) { @@ -21,27 +44,24 @@ export function loadExclusions(filePath: string): Exclusion[] { }); continue; } - + // Parse method exclusion with optional const specification // Format: method: Type::method or method: Type::method const const methodMatch = trimmed.match(/^method:\s*(.+?)::(.+?)(\s+const)?$/); if (methodMatch) { const methodName = methodMatch[2].trim(); const isConst = !!methodMatch[3]; - + exclusions.push({ kind: 'method', typeName: methodMatch[1].trim(), methodName: methodName, - isConst: isConst + isConst: isConst || undefined }); - - if (isConst) { - console.log(`Parsed const exclusion: ${methodMatch[1].trim()}::${methodName} const`); - } + } } - + return exclusions; } @@ -49,13 +69,12 @@ export function isTypeExcluded(typeName: string, exclusions: Exclusion[]): boole return exclusions.some(ex => ex.kind === 'type' && ex.typeName === typeName); } -export function isMethodExcluded(typeName: string, methodName: string, exclusions: Exclusion[], returnType?: string): boolean { - // Determine if method is const by looking at return type - const isConstMethod = returnType ? returnType.includes('const ') && returnType.includes('&') : false; - +export function isMethodExcluded(typeName: string, methodName: string, exclusions: Exclusion[], method?: { isConst?: boolean }): boolean { + const isConstMethod = method?.isConst || false; + const result = exclusions.some(ex => { - if (ex.kind === 'method' && - ex.typeName === typeName && + if (ex.kind === 'method' && + ex.typeName === typeName && ex.methodName === methodName) { // If exclusion doesn't specify const, it matches all if (ex.isConst === undefined) return true; @@ -64,6 +83,6 @@ export function isMethodExcluded(typeName: string, methodName: string, exclusion } return false; }); - + return result; } \ No newline at end of file diff --git a/spine-c-new/codegen/src/generators/method-generator.ts b/spine-c-new/codegen/src/generators/method-generator.ts index 590f500b4..acc4b08cd 100644 --- a/spine-c-new/codegen/src/generators/method-generator.ts +++ b/spine-c-new/codegen/src/generators/method-generator.ts @@ -14,7 +14,7 @@ export class MethodGenerator { const methods = type.members.filter(m => m.kind === 'method' && !m.isStatic && - !isMethodExcluded(type.name, m.name, this.exclusions, m.returnType) + !isMethodExcluded(type.name, m.name, this.exclusions, m) ); // Check for const/non-const method pairs diff --git a/spine-c-new/codegen/src/index.ts b/spine-c-new/codegen/src/index.ts index abf0d267a..eeb281dcc 100644 --- a/spine-c-new/codegen/src/index.ts +++ b/spine-c-new/codegen/src/index.ts @@ -40,10 +40,9 @@ function checkConstNonConstConflicts(classes: Type[], exclusions: Exclusion[]): const methodGroups = new Map(); for (const method of allMethods) { // Skip if this specific const/non-const version is excluded - if (isMethodExcluded(type.name, method.name, exclusions, method.returnType)) { + if (isMethodExcluded(type.name, method.name, exclusions, method)) { if (method.name === 'getSetupPose') { - const isConstMethod = method.returnType && method.returnType.includes('const ') && method.returnType.includes('&'); - console.log(`Skipping excluded method: ${type.name}::${method.name}${isConstMethod ? ' const' : ''}`); + console.log(`Skipping excluded method: ${type.name}::${method.name}${method.isConst ? ' const' : ''}`); } continue; } diff --git a/spine-c-new/codegen/src/types.ts b/spine-c-new/codegen/src/types.ts index 97e29ad5f..2edb2d99d 100644 --- a/spine-c-new/codegen/src/types.ts +++ b/spine-c-new/codegen/src/types.ts @@ -41,12 +41,17 @@ export interface SpineTypes { [header: string]: Type[]; } -export interface Exclusion { - kind: 'type' | 'method'; - typeName: string; - methodName?: string; - isConst?: boolean; // For excluding specifically const or non-const versions -} +export type Exclusion = + | { + kind: 'type'; + typeName: string; + } + | { + kind: 'method'; + typeName: string; + methodName: string; + isConst?: boolean; // Whether the method is const (e.g., void foo() const), NOT whether return type is const + }; export function toSnakeCase(name: string): string { // Handle acronyms and consecutive capitals