diff --git a/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Generator.java b/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Generator.java index 097ff155..d372e657 100644 --- a/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Generator.java +++ b/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Generator.java @@ -3,15 +3,7 @@ import com.badlogic.gdx.jnigen.generator.parser.CommentParser; import com.badlogic.gdx.jnigen.generator.parser.EnumParser; import com.badlogic.gdx.jnigen.generator.parser.StackElementParser; -import com.badlogic.gdx.jnigen.generator.types.ClosureType; -import com.badlogic.gdx.jnigen.generator.types.FunctionSignature; -import com.badlogic.gdx.jnigen.generator.types.FunctionType; -import com.badlogic.gdx.jnigen.generator.types.MappedType; -import com.badlogic.gdx.jnigen.generator.types.NamedType; -import com.badlogic.gdx.jnigen.generator.types.PointerType; -import com.badlogic.gdx.jnigen.generator.types.PrimitiveType; -import com.badlogic.gdx.jnigen.generator.types.TypeDefinition; -import com.badlogic.gdx.jnigen.generator.types.TypeKind; +import com.badlogic.gdx.jnigen.generator.types.*; import org.bytedeco.javacpp.BytePointer; import org.bytedeco.javacpp.IntPointer; import org.bytedeco.javacpp.PointerPointer; @@ -307,7 +299,9 @@ public int call(@ByVal CXCursor current, @ByVal CXCursor parent, CXClientData cx for (int i = 1; i < nTokens.get(); i++) { value.append(clang_getTokenSpelling(translationUnit, tokens.position(i)).getString()); } - Manager.getInstance().registerMacro(tokenizedName, value.toString()); + + // Libclang doesn't support define comment parsing + Manager.getInstance().registerMacro(new MacroType(tokenizedName, value.toString(), null)); } } diff --git a/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Manager.java b/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Manager.java index 7d3a640b..0516fea9 100644 --- a/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Manager.java +++ b/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/Manager.java @@ -1,11 +1,6 @@ package com.badlogic.gdx.jnigen.generator; -import com.badlogic.gdx.jnigen.generator.types.ClosureType; -import com.badlogic.gdx.jnigen.generator.types.EnumType; -import com.badlogic.gdx.jnigen.generator.types.FunctionType; -import com.badlogic.gdx.jnigen.generator.types.GlobalType; -import com.badlogic.gdx.jnigen.generator.types.StackElementType; -import com.badlogic.gdx.jnigen.generator.types.TypeDefinition; +import com.badlogic.gdx.jnigen.generator.types.*; import com.github.javaparser.StaticJavaParser; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.Modifier.Keyword; @@ -58,7 +53,7 @@ public static void init(String parsedCHeader, String basePackage) { private final Map typedefs = new HashMap<>(); - private final Map macros = new HashMap<>(); + private final Map macros = new HashMap<>(); private final GlobalType globalType; @@ -128,12 +123,12 @@ public int getCTypeID(String name) { return knownCTypes.indexOf(name); } - public void registerMacro(String name, String value) { - if (macros.containsKey(name)) { - if (!macros.get(name).equals(value)) - throw new IllegalArgumentException("Macro with name " + name + " already exists, but has different value. Old: " + macros.get(name) + " != New: " + value); + public void registerMacro(MacroType macroType) { + if (macros.containsKey(macroType.getName())) { + if (!macros.get(macroType.getName()).getValue().equals(macroType.getValue())) + throw new IllegalArgumentException("Macro with name " + macroType.getName() + " already exists, but has different value. Old: " + macros.get(macroType.getName()).getValue() + " != New: " + macroType.getValue()); } - macros.put(name, value); + macros.put(macroType.getName(), macroType); } public void registerCTypeMapping(String name, TypeDefinition javaRepresentation) { @@ -255,52 +250,11 @@ public void emit(String basePath) { // Macros CompilationUnit constantsCU = new CompilationUnit(basePackage); ClassOrInterfaceDeclaration constantsClass = constantsCU.addClass("Constants", Keyword.PUBLIC, Keyword.FINAL); - macros.keySet().stream().sorted().forEach(name -> { - String value = macros.get(name); - - // TODO: 21.06.24 We need to find more reliable ways, maybe a fancy regex? - if (value.startsWith("(") && value.endsWith(")")) - value = value.substring(1, value.length() - 1); - - for (int i = 0; i < 3; i++) { - if (value.isEmpty()) - return; - char indexLowerCase = value.toLowerCase().charAt(value.length() - 1); - if (indexLowerCase == 'l' || indexLowerCase == 'u') - value = value.substring(0, value.length() - 1); - else - break; - } - - if (SourceVersion.isKeyword(name)) - name = name + "_r"; - try { - long l = Long.decode(value); - Class lowestBound; - if (l <= Byte.MAX_VALUE && l >= Byte.MIN_VALUE) { - lowestBound = byte.class; - } else if (l <= Short.MAX_VALUE && l >= Short.MIN_VALUE) { - lowestBound = short.class; - } else if (l <= Character.MAX_VALUE && l >= Character.MIN_VALUE) { - lowestBound = char.class; - } else if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) { - lowestBound = int.class; - } else { - value += "L"; - lowestBound = long.class; - } - constantsClass.addFieldWithInitializer(lowestBound, name, new IntegerLiteralExpr(value), Keyword.PUBLIC, Keyword.STATIC, Keyword.FINAL); - }catch (NumberFormatException ignored){ - try { - if (value.endsWith("L") || value.endsWith("l")) - value = value.substring(0, value.length() - 1); - Double.parseDouble(value); - boolean isFloat = value.endsWith("f") || value.endsWith("F"); - Class lowestBound = isFloat ? float.class : double.class; - constantsClass.addFieldWithInitializer(lowestBound, name, new DoubleLiteralExpr(value), Keyword.PUBLIC, Keyword.STATIC, Keyword.FINAL); - } catch (NumberFormatException ignored1){} - } - }); + + macros.entrySet().stream() + .sorted(Entry.comparingByValue(Comparator.comparing(MacroType::getName))) + .forEach(macroType -> macroType.getValue().write(constantsCU, constantsClass)); + Files.write(Paths.get(basePath + basePackage.replace(".", "/") + "/Constants.java"), constantsCU.toString().getBytes(StandardCharsets.UTF_8)); diff --git a/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/types/MacroType.java b/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/types/MacroType.java new file mode 100644 index 00000000..95c3d9e5 --- /dev/null +++ b/compiling/gdx-jnigen-generator/src/main/java/com/badlogic/gdx/jnigen/generator/types/MacroType.java @@ -0,0 +1,86 @@ +package com.badlogic.gdx.jnigen.generator.types; + +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.Modifier; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.body.FieldDeclaration; +import com.github.javaparser.ast.expr.DoubleLiteralExpr; +import com.github.javaparser.ast.expr.IntegerLiteralExpr; + +import javax.lang.model.SourceVersion; + +public class MacroType { + + private final String name; + private final String value; + private final String comment; + + public MacroType(String name, String value, String comment) { + this.name = name; + this.value = value; + this.comment = comment; + } + + public void write(CompilationUnit cu, ClassOrInterfaceDeclaration wrappingClass) { + String processedValue = value; + String processedName = name; + // TODO: 21.06.24 We need to find more reliable ways, maybe a fancy regex? + if (processedValue.startsWith("(") && processedValue.endsWith(")")) + processedValue = processedValue.substring(1, processedValue.length() - 1); + + for (int i = 0; i < 3; i++) { + if (processedValue.isEmpty()) + return; + char indexLowerCase = processedValue.toLowerCase().charAt(processedValue.length() - 1); + if (indexLowerCase == 'l' || indexLowerCase == 'u') + processedValue = processedValue.substring(0, processedValue.length() - 1); + else + break; + } + + if (SourceVersion.isKeyword(processedName)) + processedName = processedName + "_r"; + FieldDeclaration declaration = null; + try { + long l = Long.decode(processedValue); + Class lowestBound; + if (l <= Byte.MAX_VALUE && l >= Byte.MIN_VALUE) { + lowestBound = byte.class; + } else if (l <= Short.MAX_VALUE && l >= Short.MIN_VALUE) { + lowestBound = short.class; + } else if (l <= Character.MAX_VALUE && l >= Character.MIN_VALUE) { + lowestBound = char.class; + } else if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) { + lowestBound = int.class; + } else { + processedValue += "L"; + lowestBound = long.class; + } + declaration = wrappingClass.addFieldWithInitializer(lowestBound, processedName, new IntegerLiteralExpr(processedValue), Modifier.Keyword.PUBLIC, Modifier.Keyword.STATIC, Modifier.Keyword.FINAL); + }catch (NumberFormatException ignored){ + try { + if (processedValue.endsWith("L") || processedValue.endsWith("l")) + processedValue = processedValue.substring(0, processedValue.length() - 1); + Double.parseDouble(processedValue); + boolean isFloat = processedValue.endsWith("f") || processedValue.endsWith("F"); + Class lowestBound = isFloat ? float.class : double.class; + declaration = wrappingClass.addFieldWithInitializer(lowestBound, processedName, new DoubleLiteralExpr(processedValue), Modifier.Keyword.PUBLIC, Modifier.Keyword.STATIC, Modifier.Keyword.FINAL); + } catch (NumberFormatException ignored1){} + } + + if (declaration != null && comment != null) + declaration.setJavadocComment(comment); + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + public String getComment() { + return comment; + } +} diff --git a/gdx-jnigen-generator-test/src/test/resources/test_data.h b/gdx-jnigen-generator-test/src/test/resources/test_data.h index faf8ebcb..0c4384e2 100644 --- a/gdx-jnigen-generator-test/src/test/resources/test_data.h +++ b/gdx-jnigen-generator-test/src/test/resources/test_data.h @@ -11,6 +11,7 @@ extern "C" { #endif #define UNSIGNED_INT 10 +/// This has a comment #define SIGNED_INT -10 #define UNSIGNED_DOUBLE 10.5 #define SIGNED_DOUBLE -10.5