mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-06 15:24:55 +08:00
[c] More robust enum extraction, assign self to local vars for easier debugging.
This commit is contained in:
parent
fc238bc9b7
commit
2c83fe0252
3
.gitignore
vendored
3
.gitignore
vendored
@ -246,6 +246,3 @@ docs/spine-runtimes-types.md
|
||||
spine-c/codegen/dist
|
||||
tests/output
|
||||
spine-c/.cache
|
||||
spine-libgdx/.classpath
|
||||
spine-libgdx/.factorypath
|
||||
spine-libgdx/.project
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
FixNamespaceComments: false
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AlignOperands: DontAlign
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
@ -31,11 +36,19 @@ BraceWrapping:
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
PenaltyBreakBeforeFirstCallParameter: 200
|
||||
PenaltyBreakAssignment: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
ColumnLimit: 120
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
ContinuationIndentWidth: 4
|
||||
DerivePointerAlignment: false
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
|
||||
@ -2,38 +2,292 @@
|
||||
set -e
|
||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||
|
||||
trap "cleanup" ERR
|
||||
# Default: format all languages
|
||||
FORMAT_JAVA=true
|
||||
FORMAT_TS=true
|
||||
FORMAT_CPP=true
|
||||
FORMAT_CSHARP=true
|
||||
FORMAT_HAXE=true
|
||||
FORMAT_DART=true
|
||||
FORMAT_SWIFT=true
|
||||
|
||||
setup() {
|
||||
cp $dir/.clang-format $dir/..
|
||||
cp $dir/build.gradle $dir/..
|
||||
cp $dir/settings.gradle $dir/..
|
||||
cp $dir/.editorconfig $dir/../spine-csharp
|
||||
cp $dir/.editorconfig $dir/../spine-monogame
|
||||
cp $dir/.editorconfig $dir/../spine-unity
|
||||
# Parse command line arguments
|
||||
show_help() {
|
||||
echo "Spine Runtimes Code Formatter"
|
||||
echo ""
|
||||
echo "Usage: ./format.sh [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --help, -h Show this help message"
|
||||
echo " java Format only Java files"
|
||||
echo " ts Format only TypeScript files"
|
||||
echo " cpp Format only C/C++ files"
|
||||
echo " csharp Format only C# files"
|
||||
echo " haxe Format only Haxe files"
|
||||
echo " dart Format only Dart files"
|
||||
echo " swift Format only Swift files"
|
||||
echo ""
|
||||
echo "If no language flags are specified, all languages will be formatted."
|
||||
echo "Multiple language flags can be combined, e.g.: ./format.sh java ts"
|
||||
echo ""
|
||||
echo "Tools used:"
|
||||
echo " Java: Spotless with Eclipse formatter"
|
||||
echo " TypeScript: Biome"
|
||||
echo " C/C++: clang-format"
|
||||
echo " C#: dotnet-format"
|
||||
echo " Haxe: haxe formatter"
|
||||
echo " Dart: dart format"
|
||||
echo " Swift: swift-format"
|
||||
exit 0
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm $dir/../.clang-format
|
||||
rm $dir/../build.gradle
|
||||
rm $dir/../settings.gradle
|
||||
rm $dir/../spine-csharp/.editorconfig
|
||||
rm $dir/../spine-monogame/.editorconfig
|
||||
rm $dir/../spine-unity/.editorconfig
|
||||
}
|
||||
|
||||
# copy Gradle, dotnet-format, and clang-format config to root
|
||||
setup
|
||||
|
||||
# Execute spotless and dotnet-format
|
||||
pushd $dir/..
|
||||
./formatters/gradlew spotlessApply
|
||||
if [ "$1" != "skipdotnet" ] ; then
|
||||
dotnet-format spine-csharp/spine-csharp.sln
|
||||
dotnet-format -f spine-monogame
|
||||
dotnet-format -f spine-unity
|
||||
# If any language flags are specified, disable all by default
|
||||
if [[ "$*" == *"java"* ]] || [[ "$*" == *"ts"* ]] || [[ "$*" == *"cpp"* ]] || [[ "$*" == *"csharp"* ]] || [[ "$*" == *"haxe"* ]] || [[ "$*" == *"dart"* ]] || [[ "$*" == *"swift"* ]]; then
|
||||
FORMAT_JAVA=false
|
||||
FORMAT_TS=false
|
||||
FORMAT_CPP=false
|
||||
FORMAT_CSHARP=false
|
||||
FORMAT_HAXE=false
|
||||
FORMAT_DART=false
|
||||
FORMAT_SWIFT=false
|
||||
fi
|
||||
popd
|
||||
|
||||
# Delete Gradle, dotnet-format, and clang-format config files in root
|
||||
cleanup
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--help|-h)
|
||||
show_help
|
||||
;;
|
||||
java)
|
||||
FORMAT_JAVA=true
|
||||
shift
|
||||
;;
|
||||
ts)
|
||||
FORMAT_TS=true
|
||||
shift
|
||||
;;
|
||||
cpp)
|
||||
FORMAT_CPP=true
|
||||
shift
|
||||
;;
|
||||
csharp)
|
||||
FORMAT_CSHARP=true
|
||||
shift
|
||||
;;
|
||||
haxe)
|
||||
FORMAT_HAXE=true
|
||||
shift
|
||||
;;
|
||||
dart)
|
||||
FORMAT_DART=true
|
||||
shift
|
||||
;;
|
||||
swift)
|
||||
FORMAT_SWIFT=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
echo "Use --help for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Stay in formatters directory and use relative paths
|
||||
# cd $dir/..
|
||||
|
||||
# Format C/C++ files with clang-format
|
||||
if [ "$FORMAT_CPP" = true ]; then
|
||||
echo "Formatting C/C++ files..."
|
||||
if [ ! -f "$dir/.clang-format" ]; then
|
||||
echo "Error: .clang-format not found in formatters directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Define C/C++ source directories - be specific to avoid engine sources
|
||||
cpp_dirs=(
|
||||
# spine-cpp
|
||||
"../spine-cpp/include/spine"
|
||||
"../spine-cpp/src/spine"
|
||||
"../spine-cpp/spine-cpp-lite"
|
||||
"../spine-cpp/tests"
|
||||
|
||||
# spine-c
|
||||
"../spine-c/include"
|
||||
"../spine-c/src"
|
||||
"../spine-c/src/generated"
|
||||
"../spine-c/tests"
|
||||
|
||||
# spine-godot
|
||||
"../spine-godot/spine_godot"
|
||||
|
||||
# spine-ue
|
||||
"../spine-ue/Source/SpineUE"
|
||||
"../spine-ue/Plugins/SpinePlugin/Source/SpinePlugin/Public"
|
||||
"../spine-ue/Plugins/SpinePlugin/Source/SpinePlugin/Private"
|
||||
"../spine-ue/Plugins/SpinePlugin/Source/SpineEditorPlugin/Public"
|
||||
"../spine-ue/Plugins/SpinePlugin/Source/SpineEditorPlugin/Private"
|
||||
|
||||
# spine-glfw
|
||||
"../spine-glfw/src"
|
||||
"../spine-glfw/example"
|
||||
|
||||
# spine-sdl
|
||||
"../spine-sdl/src"
|
||||
"../spine-sdl/example"
|
||||
|
||||
# spine-sfml
|
||||
"../spine-sfml/c/src/spine"
|
||||
"../spine-sfml/c/example"
|
||||
"../spine-sfml/cpp/src/spine"
|
||||
"../spine-sfml/cpp/example"
|
||||
|
||||
# spine-cocos2dx
|
||||
"../spine-cocos2dx/spine-cocos2dx/src/spine"
|
||||
"../spine-cocos2dx/example/Classes"
|
||||
|
||||
# spine-ios
|
||||
"../spine-ios/Sources/SpineCppLite"
|
||||
"../spine-ios/Sources/SpineCppLite/include"
|
||||
"../spine-ios/Sources/SpineShadersStructs"
|
||||
"../spine-ios/Example/Spine iOS Example"
|
||||
|
||||
# spine-flutter
|
||||
"../spine-flutter/ios/Classes"
|
||||
"../spine-flutter/macos/Classes"
|
||||
"../spine-flutter/src"
|
||||
)
|
||||
|
||||
# Collect all C/C++ files from specified directories
|
||||
files=()
|
||||
for cpp_dir in "${cpp_dirs[@]}"; do
|
||||
if [ -d "$cpp_dir" ]; then
|
||||
while IFS= read -r -d '' file; do
|
||||
files+=("$file")
|
||||
done < <(find "$cpp_dir" \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) \
|
||||
-not -path "*/.*" \
|
||||
-not -path "*/build/*" \
|
||||
-not -path "*/cmake-build-*/*" \
|
||||
-not -path "*/third_party/*" \
|
||||
-not -path "*/external/*" \
|
||||
-not -type l \
|
||||
-print0)
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Found ${#files[@]} C/C++ files to format"
|
||||
|
||||
# Format each file with progress
|
||||
count=0
|
||||
errors=0
|
||||
for file in "${files[@]}"; do
|
||||
count=$((count + 1))
|
||||
# Show progress every 10 files or for the last file
|
||||
if [ $((count % 10)) -eq 0 ] || [ $count -eq ${#files[@]} ]; then
|
||||
printf "\r[$count/${#files[@]}] Formatting: %-80s" "$(basename "$file")"
|
||||
fi
|
||||
|
||||
# Format the file and capture any errors
|
||||
if ! clang-format -i -style=file:"$dir/.clang-format" "$file" 2>/dev/null; then
|
||||
printf "\nError formatting: $file\n"
|
||||
errors=$((errors + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Clear the progress line and show completion
|
||||
printf "\r%-100s\r" " "
|
||||
|
||||
if [ $errors -gt 0 ]; then
|
||||
echo "Completed with $errors errors"
|
||||
fi
|
||||
|
||||
echo "C/C++ formatting complete"
|
||||
fi
|
||||
|
||||
# Format Java files with Spotless (keeping this for Eclipse formatter)
|
||||
if [ "$FORMAT_JAVA" = true ]; then
|
||||
echo "Formatting Java files..."
|
||||
./formatters/gradlew -p formatters spotlessJavaApply --quiet
|
||||
fi
|
||||
|
||||
# Format C# files with dotnet-format
|
||||
if [ "$FORMAT_CSHARP" = true ]; then
|
||||
echo "Formatting C# files..."
|
||||
if command -v dotnet-format &> /dev/null; then
|
||||
# Copy .editorconfig to C# directories
|
||||
cp .editorconfig ../spine-csharp/ 2>/dev/null || true
|
||||
cp .editorconfig ../spine-monogame/ 2>/dev/null || true
|
||||
cp .editorconfig ../spine-unity/ 2>/dev/null || true
|
||||
|
||||
dotnet-format ../spine-csharp/spine-csharp.sln || true
|
||||
dotnet-format -f ../spine-monogame || true
|
||||
dotnet-format -f ../spine-unity || true
|
||||
|
||||
# Clean up .editorconfig files
|
||||
rm -f ../spine-csharp/.editorconfig
|
||||
rm -f ../spine-monogame/.editorconfig
|
||||
rm -f ../spine-unity/.editorconfig
|
||||
else
|
||||
echo "Warning: dotnet-format not found. Skipping C# formatting."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Format TypeScript files with Biome
|
||||
if [ "$FORMAT_TS" = true ]; then
|
||||
echo "Formatting TypeScript files..."
|
||||
# Check if biome.json files match
|
||||
if ! cmp -s ../spine-ts/biome.json ../tests/biome.json; then
|
||||
echo -e "\033[1;31mERROR: spine-ts/biome.json and tests/biome.json differ!\033[0m"
|
||||
echo -e "\033[1;31mPlease sync them to ensure consistent formatting.\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Format TypeScript files
|
||||
cd ../spine-ts && npx biome format --write . && cd ../formatters
|
||||
cd ../tests && npx biome format --write --config-path ../spine-ts . && cd ../formatters
|
||||
fi
|
||||
|
||||
# Format Dart files
|
||||
if [ "$FORMAT_DART" = true ]; then
|
||||
echo "Formatting Dart files..."
|
||||
if command -v dart &> /dev/null; then
|
||||
find .. -name "*.dart" \
|
||||
-not -path "*/.*" \
|
||||
-not -path "*/node_modules/*" \
|
||||
-not -path "*/build/*" \
|
||||
-exec dart format {} +
|
||||
else
|
||||
echo "Warning: dart not found. Skipping Dart formatting."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Format Haxe files
|
||||
if [ "$FORMAT_HAXE" = true ]; then
|
||||
echo "Formatting Haxe files..."
|
||||
if command -v haxelib &> /dev/null && haxelib list formatter &> /dev/null; then
|
||||
find .. -name "*.hx" \
|
||||
-not -path "*/.*" \
|
||||
-not -path "*/node_modules/*" \
|
||||
-not -path "*/build/*" \
|
||||
| xargs haxelib run formatter -s
|
||||
else
|
||||
echo "Warning: haxe formatter not found. Install with: haxelib install formatter"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Format Swift files
|
||||
if [ "$FORMAT_SWIFT" = true ]; then
|
||||
echo "Formatting Swift files..."
|
||||
if command -v swift-format &> /dev/null; then
|
||||
find .. -name "*.swift" \
|
||||
-not -path "*/.*" \
|
||||
-not -path "*/build/*" \
|
||||
-not -path "*/DerivedData/*" \
|
||||
| xargs swift-format -i
|
||||
else
|
||||
echo "Warning: swift-format not found. Install from https://github.com/apple/swift-format"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Formatting complete!"
|
||||
@ -33,6 +33,9 @@ fi
|
||||
# Run codegen if requested
|
||||
if [ "$1" = "codegen" ]; then
|
||||
npx tsx codegen/src/index.ts
|
||||
# Format the generated C++ files
|
||||
echo "Formatting generated C++ files..."
|
||||
../formatters/format.sh cpp
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -307,11 +307,13 @@ export function generateFieldAccessors(type: ClassOrStruct, knownTypeNames: Set<
|
||||
}
|
||||
|
||||
function generateFieldGetterBody(field: Field, cppTypeName: string, knownTypeNames: Set<string>): string {
|
||||
const fieldAccess = `((${cppTypeName}*)self)->${field.name}`;
|
||||
// Use local variable to avoid cast->field line breaks
|
||||
const setup = `${cppTypeName} *_self = (${cppTypeName} *) self;`;
|
||||
const fieldAccess = `_self->${field.name}`;
|
||||
|
||||
// Handle String fields
|
||||
if (field.type === 'String' || field.type === 'const String' || field.type === 'const String&') {
|
||||
return `return ${fieldAccess}.buffer();`;
|
||||
return `${setup}\n\treturn ${fieldAccess}.buffer();`;
|
||||
}
|
||||
|
||||
// Handle reference types
|
||||
@ -320,10 +322,10 @@ function generateFieldGetterBody(field: Field, cppTypeName: string, knownTypeNam
|
||||
const cType = toCTypeName(baseType, knownTypeNames);
|
||||
|
||||
if (isPrimitive(baseType)) {
|
||||
return `return ${fieldAccess};`;
|
||||
return `${setup}\n\treturn ${fieldAccess};`;
|
||||
}
|
||||
|
||||
return `return (${cType})&${fieldAccess};`;
|
||||
return `${setup}\n\treturn (${cType})&${fieldAccess};`;
|
||||
}
|
||||
|
||||
// Handle pointer types
|
||||
@ -331,35 +333,37 @@ function generateFieldGetterBody(field: Field, cppTypeName: string, knownTypeNam
|
||||
const baseType = field.type.slice(0, -1).trim();
|
||||
|
||||
if (isPrimitive(baseType)) {
|
||||
return `return ${fieldAccess};`;
|
||||
return `${setup}\n\treturn ${fieldAccess};`;
|
||||
}
|
||||
|
||||
const cType = toCTypeName(field.type, knownTypeNames);
|
||||
return `return (${cType})${fieldAccess};`;
|
||||
return `${setup}\n\treturn (${cType})${fieldAccess};`;
|
||||
}
|
||||
|
||||
// Handle enum types
|
||||
if (knownTypeNames.has(field.type)) {
|
||||
const cType = toCTypeName(field.type, knownTypeNames);
|
||||
return `return (${cType})${fieldAccess};`;
|
||||
return `${setup}\n\treturn (${cType})${fieldAccess};`;
|
||||
}
|
||||
|
||||
// Handle primitive types
|
||||
if (isPrimitive(field.type)) {
|
||||
return `return ${fieldAccess};`;
|
||||
return `${setup}\n\treturn ${fieldAccess};`;
|
||||
}
|
||||
|
||||
// Handle non-primitive value types (need to return address)
|
||||
const cType = toCTypeName(field.type, knownTypeNames);
|
||||
return `return (${cType})&${fieldAccess};`;
|
||||
return `${setup}\n\treturn (${cType})&${fieldAccess};`;
|
||||
}
|
||||
|
||||
function generateFieldSetterBody(field: Field, cppTypeName: string, knownTypeNames: Set<string>): string {
|
||||
const fieldAccess = `((${cppTypeName}*)self)->${field.name}`;
|
||||
// Use local variable to avoid cast->field line breaks
|
||||
const setup = `${cppTypeName} *_self = (${cppTypeName} *) self;`;
|
||||
const fieldAccess = `_self->${field.name}`;
|
||||
|
||||
// Handle String fields
|
||||
if (field.type === 'String') {
|
||||
return `${fieldAccess} = String(value);`;
|
||||
return `${setup}\n\t${fieldAccess} = String(value);`;
|
||||
}
|
||||
|
||||
// Handle Array types
|
||||
@ -367,23 +371,23 @@ function generateFieldSetterBody(field: Field, cppTypeName: string, knownTypeNam
|
||||
const arrayMatch = field.type.match(/^Array<(.+?)>$/);
|
||||
if (arrayMatch) {
|
||||
const elementType = arrayMatch[1];
|
||||
return `${fieldAccess} = *((Array<${elementType}>*)value);`;
|
||||
return `${setup}\n\t${fieldAccess} = *((Array<${elementType}>*)value);`;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle enum types
|
||||
if (knownTypeNames.has(field.type)) {
|
||||
return `${fieldAccess} = (${field.type})value;`;
|
||||
return `${setup}\n\t${fieldAccess} = (${field.type})value;`;
|
||||
}
|
||||
|
||||
// Handle pointer types (cast back from opaque type)
|
||||
if (field.type.endsWith('*') && !isPrimitive(field.type)) {
|
||||
const baseType = field.type.slice(0, -1).trim();
|
||||
return `${fieldAccess} = (${baseType}*)value;`;
|
||||
return `${setup}\n\t${fieldAccess} = (${baseType}*)value;`;
|
||||
}
|
||||
|
||||
// Handle everything else
|
||||
return `${fieldAccess} = value;`;
|
||||
return `${setup}\n\t${fieldAccess} = value;`;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -677,16 +681,20 @@ function generateMethod(type: ClassOrStruct, method: Method, cTypeName: string,
|
||||
|
||||
// Generate method body
|
||||
let methodCall: string;
|
||||
let body: string;
|
||||
|
||||
if (method.isStatic) {
|
||||
methodCall = `${cppTypeName}::${method.name}(${buildCppArgs(method.parameters || [], cParams, knownTypeNames)})`;
|
||||
} else if (method.fromSupertype) {
|
||||
// For inherited methods that may be hidden by derived class methods with same name,
|
||||
// explicitly call the base class version
|
||||
methodCall = `((${method.fromSupertype}*)(${cppTypeName}*)self)->${method.name}(${buildCppArgs(method.parameters || [], cParams.slice(1), knownTypeNames)})`;
|
||||
body = generateReturnStatement(method.returnType, methodCall, knownTypeNames);
|
||||
} else {
|
||||
methodCall = `((${cppTypeName}*)self)->${method.name}(${buildCppArgs(method.parameters || [], cParams.slice(1), knownTypeNames)})`;
|
||||
// Use local variable to avoid cast->method line breaks
|
||||
const instanceVar = method.fromSupertype ?
|
||||
`${method.fromSupertype} *_self = (${method.fromSupertype} *) (${cppTypeName} *) self;` :
|
||||
`${cppTypeName} *_self = (${cppTypeName} *) self;`;
|
||||
methodCall = `_self->${method.name}(${buildCppArgs(method.parameters || [], cParams.slice(1), knownTypeNames)})`;
|
||||
const returnStatement = generateReturnStatement(method.returnType, methodCall, knownTypeNames);
|
||||
body = `${instanceVar}\n\t${returnStatement}`;
|
||||
}
|
||||
const body = generateReturnStatement(method.returnType, methodCall, knownTypeNames);
|
||||
|
||||
return {
|
||||
name: cMethodName,
|
||||
@ -843,17 +851,19 @@ function generateArrayMethod(cTypeName: string, method: Method, cppElementType:
|
||||
}
|
||||
|
||||
function generateArrayMethodBody(method: Method, cppElementType: string, cElementType: string, knownTypeNames: Set<string>): string {
|
||||
const self = `((Array<${cppElementType}>*)array)->`;
|
||||
// Use local variable to avoid cast->method line breaks
|
||||
const setup = `Array<${cppElementType}> *_array = (Array<${cppElementType}> *) array;`;
|
||||
|
||||
// Build method call arguments using shared function
|
||||
const cppArgs = method.parameters ?
|
||||
buildCppArgs(method.parameters, convertParameters(method.parameters, knownTypeNames), knownTypeNames) :
|
||||
'';
|
||||
|
||||
const methodCall = `${self}${method.name}(${cppArgs})`;
|
||||
const methodCall = `_array->${method.name}(${cppArgs})`;
|
||||
|
||||
// Use shared return value handling
|
||||
return generateReturnStatement(method.returnType, methodCall, knownTypeNames, cppElementType, cElementType);
|
||||
const returnStatement = generateReturnStatement(method.returnType, methodCall, knownTypeNames, cppElementType, cElementType);
|
||||
return `${setup}\n\t${returnStatement}`;
|
||||
}
|
||||
|
||||
function isMethodExcluded(typeName: string, method: Method, exclusions: Exclusion[]): boolean {
|
||||
|
||||
@ -16,30 +16,47 @@ function extractEnumValueFromSource(
|
||||
): string | null | undefined {
|
||||
if (!enumConstNode.loc) return undefined;
|
||||
|
||||
const line = sourceLines[enumConstNode.loc.line - 1];
|
||||
if (!line) return undefined;
|
||||
|
||||
// Find enum name and check for '='
|
||||
const nameMatch = line.match(new RegExp(`\\b${enumConstNode.name}\\b`));
|
||||
if (!nameMatch) return undefined;
|
||||
|
||||
const afterName = line.substring(nameMatch.index! + enumConstNode.name.length);
|
||||
const equalIndex = afterName.indexOf('=');
|
||||
if (equalIndex === -1) return null; // No explicit value
|
||||
|
||||
// Extract value expression
|
||||
let valueText = afterName.substring(equalIndex + 1);
|
||||
|
||||
// Handle multi-line values
|
||||
let currentLine = enumConstNode.loc.line;
|
||||
while (currentLine < sourceLines.length && !valueText.match(/[,}]/)) {
|
||||
valueText += '\n' + sourceLines[currentLine++];
|
||||
let startLine = enumConstNode.loc.line - 1;
|
||||
|
||||
// Build a multi-line buffer starting from the enum constant
|
||||
let buffer = '';
|
||||
let foundName = false;
|
||||
|
||||
// Look for the enum constant name across multiple lines
|
||||
for (let i = startLine; i < sourceLines.length && i < startLine + 5; i++) {
|
||||
const line = sourceLines[i];
|
||||
if (!line) continue;
|
||||
|
||||
buffer += line + '\n';
|
||||
|
||||
// Check if we found the enum constant name
|
||||
if (!foundName && line.match(new RegExp(`\\b${enumConstNode.name}\\b`))) {
|
||||
foundName = true;
|
||||
}
|
||||
|
||||
// If we found a comma or closing brace, we have the complete enum entry
|
||||
if (foundName && (line.includes(',') || line.includes('}'))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract up to comma or brace
|
||||
const endMatch = valueText.match(/^(.*?)([,}])/s);
|
||||
if (endMatch) valueText = endMatch[1];
|
||||
|
||||
|
||||
if (!foundName) return undefined;
|
||||
|
||||
// Extract the part after the enum name
|
||||
const nameMatch = buffer.match(new RegExp(`\\b${enumConstNode.name}\\b\\s*([^,}]*)[,}]?`));
|
||||
if (!nameMatch) return undefined;
|
||||
|
||||
const afterName = nameMatch[1];
|
||||
|
||||
// Check if there's an assignment
|
||||
if (!afterName.includes('=')) return null; // No explicit value
|
||||
|
||||
// Extract the value after '='
|
||||
const equalMatch = afterName.match(/=\s*(.+)/);
|
||||
if (!equalMatch) return null;
|
||||
|
||||
let valueText = equalMatch[1];
|
||||
|
||||
// Clean up
|
||||
return valueText
|
||||
.replace(/\/\/.*$/gm, '') // Remove single-line comments
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user