Fix exclusions.ts: discriminated union type, correct const method handling

This commit is contained in:
Mario Zechner 2025-07-08 23:38:43 +02:00
parent 4fd23d3abe
commit 0a33247f44
4 changed files with 51 additions and 28 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -40,10 +40,9 @@ function checkConstNonConstConflicts(classes: Type[], exclusions: Exclusion[]):
const methodGroups = new Map<string, Member[]>();
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;
}

View File

@ -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