mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +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
|
spine-c/codegen/dist
|
||||||
tests/output
|
tests/output
|
||||||
spine-c/.cache
|
spine-c/.cache
|
||||||
spine-libgdx/.classpath
|
|
||||||
spine-libgdx/.factorypath
|
|
||||||
spine-libgdx/.project
|
|
||||||
|
|||||||
@ -1,20 +1,25 @@
|
|||||||
# Generated from CLion C/C++ Code Style settings
|
# Generated from CLion C/C++ Code Style settings
|
||||||
BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
AccessModifierOffset: -4
|
AccessModifierOffset: -4
|
||||||
|
FixNamespaceComments: false
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: None
|
AlignConsecutiveAssignments: None
|
||||||
AlignOperands: Align
|
AlignOperands: DontAlign
|
||||||
AllowAllArgumentsOnNextLine: false
|
AllowAllArgumentsOnNextLine: true
|
||||||
AllowAllConstructorInitializersOnNextLine: false
|
AllowAllConstructorInitializersOnNextLine: false
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
AllowShortBlocksOnASingleLine: Always
|
AllowShortBlocksOnASingleLine: Always
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: All
|
AllowShortFunctionsOnASingleLine: All
|
||||||
AllowShortIfStatementsOnASingleLine: Always
|
AllowShortIfStatementsOnASingleLine: Always
|
||||||
AllowShortLambdasOnASingleLine: All
|
AllowShortLambdasOnASingleLine: All
|
||||||
AllowShortLoopsOnASingleLine: true
|
AllowShortLoopsOnASingleLine: true
|
||||||
AlwaysBreakAfterReturnType: None
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
AlwaysBreakTemplateDeclarations: Yes
|
AlwaysBreakTemplateDeclarations: Yes
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
BreakBeforeBraces: Custom
|
BreakBeforeBraces: Custom
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterCaseLabel: false
|
AfterCaseLabel: false
|
||||||
@ -31,11 +36,19 @@ BraceWrapping:
|
|||||||
SplitEmptyRecord: true
|
SplitEmptyRecord: true
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 200
|
||||||
|
PenaltyBreakAssignment: 1000
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 1000000
|
||||||
BreakConstructorInitializers: BeforeColon
|
BreakConstructorInitializers: BeforeColon
|
||||||
BreakInheritanceList: BeforeColon
|
BreakInheritanceList: BeforeColon
|
||||||
ColumnLimit: 0
|
ColumnLimit: 120
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ContinuationIndentWidth: 8
|
ContinuationIndentWidth: 4
|
||||||
|
DerivePointerAlignment: false
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
IndentPPDirectives: None
|
IndentPPDirectives: None
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
|
|||||||
@ -2,38 +2,292 @@
|
|||||||
set -e
|
set -e
|
||||||
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
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() {
|
# Parse command line arguments
|
||||||
cp $dir/.clang-format $dir/..
|
show_help() {
|
||||||
cp $dir/build.gradle $dir/..
|
echo "Spine Runtimes Code Formatter"
|
||||||
cp $dir/settings.gradle $dir/..
|
echo ""
|
||||||
cp $dir/.editorconfig $dir/../spine-csharp
|
echo "Usage: ./format.sh [options]"
|
||||||
cp $dir/.editorconfig $dir/../spine-monogame
|
echo ""
|
||||||
cp $dir/.editorconfig $dir/../spine-unity
|
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() {
|
# If any language flags are specified, disable all by default
|
||||||
rm $dir/../.clang-format
|
if [[ "$*" == *"java"* ]] || [[ "$*" == *"ts"* ]] || [[ "$*" == *"cpp"* ]] || [[ "$*" == *"csharp"* ]] || [[ "$*" == *"haxe"* ]] || [[ "$*" == *"dart"* ]] || [[ "$*" == *"swift"* ]]; then
|
||||||
rm $dir/../build.gradle
|
FORMAT_JAVA=false
|
||||||
rm $dir/../settings.gradle
|
FORMAT_TS=false
|
||||||
rm $dir/../spine-csharp/.editorconfig
|
FORMAT_CPP=false
|
||||||
rm $dir/../spine-monogame/.editorconfig
|
FORMAT_CSHARP=false
|
||||||
rm $dir/../spine-unity/.editorconfig
|
FORMAT_HAXE=false
|
||||||
}
|
FORMAT_DART=false
|
||||||
|
FORMAT_SWIFT=false
|
||||||
# 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
|
|
||||||
fi
|
fi
|
||||||
popd
|
|
||||||
|
|
||||||
# Delete Gradle, dotnet-format, and clang-format config files in root
|
# Parse arguments
|
||||||
cleanup
|
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
|
# Run codegen if requested
|
||||||
if [ "$1" = "codegen" ]; then
|
if [ "$1" = "codegen" ]; then
|
||||||
npx tsx codegen/src/index.ts
|
npx tsx codegen/src/index.ts
|
||||||
|
# Format the generated C++ files
|
||||||
|
echo "Formatting generated C++ files..."
|
||||||
|
../formatters/format.sh cpp
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
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 {
|
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
|
// Handle String fields
|
||||||
if (field.type === 'String' || field.type === 'const String' || field.type === 'const String&') {
|
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
|
// Handle reference types
|
||||||
@ -320,10 +322,10 @@ function generateFieldGetterBody(field: Field, cppTypeName: string, knownTypeNam
|
|||||||
const cType = toCTypeName(baseType, knownTypeNames);
|
const cType = toCTypeName(baseType, knownTypeNames);
|
||||||
|
|
||||||
if (isPrimitive(baseType)) {
|
if (isPrimitive(baseType)) {
|
||||||
return `return ${fieldAccess};`;
|
return `${setup}\n\treturn ${fieldAccess};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `return (${cType})&${fieldAccess};`;
|
return `${setup}\n\treturn (${cType})&${fieldAccess};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle pointer types
|
// Handle pointer types
|
||||||
@ -331,35 +333,37 @@ function generateFieldGetterBody(field: Field, cppTypeName: string, knownTypeNam
|
|||||||
const baseType = field.type.slice(0, -1).trim();
|
const baseType = field.type.slice(0, -1).trim();
|
||||||
|
|
||||||
if (isPrimitive(baseType)) {
|
if (isPrimitive(baseType)) {
|
||||||
return `return ${fieldAccess};`;
|
return `${setup}\n\treturn ${fieldAccess};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cType = toCTypeName(field.type, knownTypeNames);
|
const cType = toCTypeName(field.type, knownTypeNames);
|
||||||
return `return (${cType})${fieldAccess};`;
|
return `${setup}\n\treturn (${cType})${fieldAccess};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle enum types
|
// Handle enum types
|
||||||
if (knownTypeNames.has(field.type)) {
|
if (knownTypeNames.has(field.type)) {
|
||||||
const cType = toCTypeName(field.type, knownTypeNames);
|
const cType = toCTypeName(field.type, knownTypeNames);
|
||||||
return `return (${cType})${fieldAccess};`;
|
return `${setup}\n\treturn (${cType})${fieldAccess};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle primitive types
|
// Handle primitive types
|
||||||
if (isPrimitive(field.type)) {
|
if (isPrimitive(field.type)) {
|
||||||
return `return ${fieldAccess};`;
|
return `${setup}\n\treturn ${fieldAccess};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle non-primitive value types (need to return address)
|
// Handle non-primitive value types (need to return address)
|
||||||
const cType = toCTypeName(field.type, knownTypeNames);
|
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 {
|
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
|
// Handle String fields
|
||||||
if (field.type === 'String') {
|
if (field.type === 'String') {
|
||||||
return `${fieldAccess} = String(value);`;
|
return `${setup}\n\t${fieldAccess} = String(value);`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Array types
|
// Handle Array types
|
||||||
@ -367,23 +371,23 @@ function generateFieldSetterBody(field: Field, cppTypeName: string, knownTypeNam
|
|||||||
const arrayMatch = field.type.match(/^Array<(.+?)>$/);
|
const arrayMatch = field.type.match(/^Array<(.+?)>$/);
|
||||||
if (arrayMatch) {
|
if (arrayMatch) {
|
||||||
const elementType = arrayMatch[1];
|
const elementType = arrayMatch[1];
|
||||||
return `${fieldAccess} = *((Array<${elementType}>*)value);`;
|
return `${setup}\n\t${fieldAccess} = *((Array<${elementType}>*)value);`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle enum types
|
// Handle enum types
|
||||||
if (knownTypeNames.has(field.type)) {
|
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)
|
// Handle pointer types (cast back from opaque type)
|
||||||
if (field.type.endsWith('*') && !isPrimitive(field.type)) {
|
if (field.type.endsWith('*') && !isPrimitive(field.type)) {
|
||||||
const baseType = field.type.slice(0, -1).trim();
|
const baseType = field.type.slice(0, -1).trim();
|
||||||
return `${fieldAccess} = (${baseType}*)value;`;
|
return `${setup}\n\t${fieldAccess} = (${baseType}*)value;`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle everything else
|
// 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
|
// Generate method body
|
||||||
let methodCall: string;
|
let methodCall: string;
|
||||||
|
let body: string;
|
||||||
|
|
||||||
if (method.isStatic) {
|
if (method.isStatic) {
|
||||||
methodCall = `${cppTypeName}::${method.name}(${buildCppArgs(method.parameters || [], cParams, knownTypeNames)})`;
|
methodCall = `${cppTypeName}::${method.name}(${buildCppArgs(method.parameters || [], cParams, knownTypeNames)})`;
|
||||||
} else if (method.fromSupertype) {
|
body = generateReturnStatement(method.returnType, methodCall, knownTypeNames);
|
||||||
// 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)})`;
|
|
||||||
} else {
|
} 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 {
|
return {
|
||||||
name: cMethodName,
|
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 {
|
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
|
// Build method call arguments using shared function
|
||||||
const cppArgs = method.parameters ?
|
const cppArgs = method.parameters ?
|
||||||
buildCppArgs(method.parameters, convertParameters(method.parameters, knownTypeNames), knownTypeNames) :
|
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
|
// 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 {
|
function isMethodExcluded(typeName: string, method: Method, exclusions: Exclusion[]): boolean {
|
||||||
|
|||||||
@ -16,30 +16,47 @@ function extractEnumValueFromSource(
|
|||||||
): string | null | undefined {
|
): string | null | undefined {
|
||||||
if (!enumConstNode.loc) return undefined;
|
if (!enumConstNode.loc) return undefined;
|
||||||
|
|
||||||
const line = sourceLines[enumConstNode.loc.line - 1];
|
let startLine = enumConstNode.loc.line - 1;
|
||||||
if (!line) return undefined;
|
|
||||||
|
// Build a multi-line buffer starting from the enum constant
|
||||||
// Find enum name and check for '='
|
let buffer = '';
|
||||||
const nameMatch = line.match(new RegExp(`\\b${enumConstNode.name}\\b`));
|
let foundName = false;
|
||||||
if (!nameMatch) return undefined;
|
|
||||||
|
// Look for the enum constant name across multiple lines
|
||||||
const afterName = line.substring(nameMatch.index! + enumConstNode.name.length);
|
for (let i = startLine; i < sourceLines.length && i < startLine + 5; i++) {
|
||||||
const equalIndex = afterName.indexOf('=');
|
const line = sourceLines[i];
|
||||||
if (equalIndex === -1) return null; // No explicit value
|
if (!line) continue;
|
||||||
|
|
||||||
// Extract value expression
|
buffer += line + '\n';
|
||||||
let valueText = afterName.substring(equalIndex + 1);
|
|
||||||
|
// Check if we found the enum constant name
|
||||||
// Handle multi-line values
|
if (!foundName && line.match(new RegExp(`\\b${enumConstNode.name}\\b`))) {
|
||||||
let currentLine = enumConstNode.loc.line;
|
foundName = true;
|
||||||
while (currentLine < sourceLines.length && !valueText.match(/[,}]/)) {
|
}
|
||||||
valueText += '\n' + sourceLines[currentLine++];
|
|
||||||
|
// 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
|
if (!foundName) return undefined;
|
||||||
const endMatch = valueText.match(/^(.*?)([,}])/s);
|
|
||||||
if (endMatch) valueText = endMatch[1];
|
// 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
|
// Clean up
|
||||||
return valueText
|
return valueText
|
||||||
.replace(/\/\/.*$/gm, '') // Remove single-line comments
|
.replace(/\/\/.*$/gm, '') // Remove single-line comments
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user