From 65f50bb1541831100845949e3af1bcb1770bc921 Mon Sep 17 00:00:00 2001 From: Natan Date: Sat, 15 Jul 2023 08:18:55 -0300 Subject: [PATCH] More gen improvements --- .../example-build/jni/cpp/src/NormalClass.cpp | 12 +- .../example-build/jni/cpp/src/NormalClass.h | 7 +- .../src/main/resources/idl/Test.idl | 19 +- .../jparser/example/NormalClassTest.java | 6 + .../codeparser/idl/IDLDefaultCodeParser.java | 19 +- .../core/codeparser/idl/IDLMethodParser.java | 193 +++++++++++++----- .../xpenatan/jparser/cpp/CppCodeParser.java | 145 +++++++------ .../jparser/cpp/NativeCPPGeneratorV2.java | 69 ++++++- .../IDLMethod.java | 3 + .../IDLParameter.java | 5 + .../xpenatan/jparser/idl/IDLReaderTest.java | 1 + 11 files changed, 344 insertions(+), 135 deletions(-) diff --git a/example/example-build/jni/cpp/src/NormalClass.cpp b/example/example-build/jni/cpp/src/NormalClass.cpp index ea95dda..397c360 100644 --- a/example/example-build/jni/cpp/src/NormalClass.cpp +++ b/example/example-build/jni/cpp/src/NormalClass.cpp @@ -30,9 +30,9 @@ NormalClass::NormalClass(ParamClass * pointerParamClass, ParamClass & refParamCl d++; } -int NormalClass::subIntValue(int a, int b) +int NormalClass::subIntValue(int a, int b, int subValue) { - return (a - b); + return (a - b) - subValue; } int NormalClass::addIntValue(int a, int b) @@ -40,7 +40,13 @@ int NormalClass::addIntValue(int a, int b) return (a + b) * hiddenInt * hiddenParentInt; } -ReturnClass NormalClass::getReturnValueClass() +ReturnClass NormalClass::getStaticReturnValueClass(ParamClass * paramClass) +{ + ReturnClass temp; + return temp; +} + +ReturnClass NormalClass::getReturnValueClass(ParamClass * paramClass) { return valueReturnClass; } diff --git a/example/example-build/jni/cpp/src/NormalClass.h b/example/example-build/jni/cpp/src/NormalClass.h index 45f808c..4e282de 100644 --- a/example/example-build/jni/cpp/src/NormalClass.h +++ b/example/example-build/jni/cpp/src/NormalClass.h @@ -18,9 +18,12 @@ class NormalClass : public ParentClass NormalClass(int c, ParamClass & refParamClass); NormalClass(ParamClass * pointerParamClass, ParamClass & refParamClass, ParamClass valueParamClass); - static int subIntValue(int a, int b); + static int subIntValue(int a, int b, int subValue = 0); int addIntValue(int a, int b); - ReturnClass getReturnValueClass(); + + static ReturnClass getStaticReturnValueClass(ParamClass * paramClass); + ReturnClass getReturnValueClass(ParamClass * paramClass); + ReturnClass & getReturnRefClass(); ReturnClass * getReturnPointerClass(); ReturnClass * getReturnNullPointerClass(); diff --git a/example/example-build/src/main/resources/idl/Test.idl b/example/example-build/src/main/resources/idl/Test.idl index 902f7c3..d999ca9 100644 --- a/example/example-build/src/main/resources/idl/Test.idl +++ b/example/example-build/src/main/resources/idl/Test.idl @@ -8,15 +8,18 @@ interface NormalClass { void NormalClass(long c, [Ref]ParamClass refParamClass); void NormalClass(ParamClass pointerParamClass, [Ref]ParamClass refParamClass, [Value]ParamClass valueParamClass); - static long subIntValue(long a, long b); +// static DOMString addString(DOMString text); + [Value] static ReturnClass getStaticReturnValueClass(ParamClass paramClass); + [Value]ReturnClass getReturnValueClass(ParamClass paramClass); + + static long subIntValue(long a, long b, optional long subValue); long addIntValue(long a, long b); -// [Value]ReturnClass getReturnValueClass(); -// [Ref]ReturnClass getReturnRefClass(); -// ReturnClass getReturnPointerClass(); -// ReturnClass getReturnNullPointerClass(); -// void refParam([Ref]ParamClass paramClass); -// void pointerParam(ParamClass paramClass); -// void valueParam([Value]ParamClass paramClass); + [Ref]ReturnClass getReturnRefClass(); + ReturnClass getReturnPointerClass(); + ReturnClass getReturnNullPointerClass(); + void refParam([Ref]ParamClass paramClass); + void pointerParam(ParamClass paramClass); + void valueParam([Value]ParamClass paramClass); }; NormalClass implements ParentClass; diff --git a/example/example-desktop/src/test/java/com/github/xpenatan/jparser/example/NormalClassTest.java b/example/example-desktop/src/test/java/com/github/xpenatan/jparser/example/NormalClassTest.java index 2530beb..2518aef 100644 --- a/example/example-desktop/src/test/java/com/github/xpenatan/jparser/example/NormalClassTest.java +++ b/example/example-desktop/src/test/java/com/github/xpenatan/jparser/example/NormalClassTest.java @@ -28,6 +28,12 @@ public void test_static_sub_int() { assertEquals(1, ret); } + @Test + public void test_static_sub_int_subValue() { + int ret = NormalClass.subIntValue(11, 10, 1); + assertEquals(0, ret); + } + @Test public void test_add_float() { NormalClass normalClass = new NormalClass(); diff --git a/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLDefaultCodeParser.java b/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLDefaultCodeParser.java index ae366d6..58905df 100644 --- a/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLDefaultCodeParser.java +++ b/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLDefaultCodeParser.java @@ -58,10 +58,13 @@ public void onParseClassStart(JParser jParser, CompilationUnit unit, ClassOrInte String nameStr = name.asString(); IDLClass idlClass = idlReader.getClass(nameStr); if(idlClass != null) { - ArrayList constructors = idlClass.constructors; - for(int i = 0; i < constructors.size(); i++) { - IDLConstructor idlConstructor = constructors.get(i); - IDLConstructorParser.generateConstructor(this, jParser, unit, classOrInterfaceDeclaration, idlClass, idlConstructor); + + if(generateClass) { + ArrayList constructors = idlClass.constructors; + for(int i = 0; i < constructors.size(); i++) { + IDLConstructor idlConstructor = constructors.get(i); + IDLConstructorParser.generateConstructor(this, jParser, unit, classOrInterfaceDeclaration, idlClass, idlConstructor); + } } ArrayList methods = idlClass.methods; @@ -114,4 +117,12 @@ public void onIDLMethodGenerated(JParser jParser, IDLClass idlClass, IDLMethod i public void onIDLMethodGenerated(JParser jParser, IDLMethod idlMethod, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration methodDeclaration, MethodDeclaration nativeMethodDeclaration) { } + /** + * true to accept the idl method + */ + @Deprecated + public boolean filterIDLMethod(IDLClass idlClass, IDLMethod idlMethod) { + return true; + } + } \ No newline at end of file diff --git a/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLMethodParser.java b/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLMethodParser.java index 5c752b6..ed78504 100644 --- a/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLMethodParser.java +++ b/jParser/core/src/main/java/com/github/xpenatan/jparser/core/codeparser/idl/IDLMethodParser.java @@ -14,8 +14,6 @@ import com.github.javaparser.ast.body.Parameter; import com.github.javaparser.ast.comments.BlockComment; import com.github.javaparser.ast.comments.Comment; -import com.github.javaparser.ast.expr.CastExpr; -import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.expr.ObjectCreationExpr; import com.github.javaparser.ast.stmt.BlockStmt; @@ -42,7 +40,16 @@ public class IDLMethodParser { " return [TYPE]_TEMP_GEN_[NUM];\n" + "}"; + static final String GET_TEMP_OBJECT_TEMPLATE = "" + + "{\n" + + " [METHOD];\n" + + " return [TYPE]_TEMP_GEN_[NUM];\n" + + "}"; + static final String TEMPLATE_TEMP_FIELD = "[TYPE]_TEMP_GEN_[NUM]"; + static final String TEMPLATE_NEW_FIELD = "[TYPE]_NEW_GEN_[NUM]"; + static final String TEMPLATE_TEMP_STATIC_FIELD = "[TYPE]_TEMP_STATIC_GEN_[NUM]"; + static final String TEMPLATE_NEW_STATIC_FIELD = "[TYPE]_NEW_STATIC_GEN_[NUM]"; static final String TEMPLATE_TAG_METHOD = "[METHOD]"; @@ -93,6 +100,10 @@ public static void generateMethods(IDLDefaultCodeParser idlParser, JParser jPars } } + if(!idlParser.filterIDLMethod(idlClass, idlMethod)) { + return; + } + ArrayList parameters = idlMethod.parameters; MethodDeclaration methodDeclaration = classOrInterfaceDeclaration.addMethod(methodName, Modifier.Keyword.PUBLIC); methodDeclaration.setStatic(idlMethod.isStaticMethod); @@ -118,81 +129,93 @@ public static void generateMethods(IDLDefaultCodeParser idlParser, JParser jPars } private static void setupMethod(IDLDefaultCodeParser idlParser, JParser jParser, IDLMethod idlMethod, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration methodDeclaration) { - MethodDeclaration nativeMethodDeclaration = generateNativeMethod(methodDeclaration); + MethodDeclaration nativeMethodDeclaration = generateNativeMethod(idlMethod, classDeclaration, methodDeclaration); if(!JParserHelper.containsMethod(classDeclaration, nativeMethodDeclaration)) { //Add native method if it does not exist classDeclaration.getMembers().add(nativeMethodDeclaration); // Now that we have the native method we setup the caller method. - boolean isStatic = methodDeclaration.isStatic(); - MethodCallExpr caller = new MethodCallExpr(); - caller.setName(nativeMethodDeclaration.getNameAsString()); - if(!isStatic) { - caller.addArgument(IDLDefaultCodeParser.CPOINTER_METHOD); - } + MethodCallExpr caller = createCaller(nativeMethodDeclaration); - NodeList methodParameters = methodDeclaration.getParameters(); Type methodReturnType = methodDeclaration.getType(); - for(int i = 0; i < methodParameters.size(); i++) { - Parameter parameter = methodParameters.get(i); - Type type = parameter.getType(); - String paramName = parameter.getNameAsString(); - if(type.isClassOrInterfaceType()) { - //All methods must contain a base class to get its pointer - String typeName = parameter.getType().toString(); - paramName = paramName + ".getCPointer()"; - } - caller.addArgument(paramName); - } - if(methodReturnType.isVoidType()) { // void types just call the method. + setupCallerParam(idlMethod, caller, methodDeclaration, null); BlockStmt blockStmt = methodDeclaration.getBody().get(); blockStmt.addStatement(caller); } else if(methodReturnType.isClassOrInterfaceType()) { // Class object needs to generate some additional code. // Needs to obtain the pointer and return a temp object. - BlockStmt blockStmt = generateTempObjects(classDeclaration, methodDeclaration, caller); + BlockStmt blockStmt = generateTempObjects(idlMethod, classDeclaration, methodDeclaration, nativeMethodDeclaration, caller); methodDeclaration.setBody(blockStmt); } else { // Should be a primitive return type. ReturnStmt returnStmt = getReturnStmt(methodDeclaration); + setupCallerParam(idlMethod, caller, methodDeclaration, null); returnStmt.setExpression(caller); } idlParser.onIDLMethodGenerated(jParser, idlMethod, classDeclaration, methodDeclaration, nativeMethodDeclaration); } } - private static BlockStmt generateTempObjects(ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration methodDeclaration, MethodCallExpr caller) { - // Will return a temp object. - // This variable will be created by checking its class, name and number. - // if the temp object already exist it will increment variable number and create it. + private static MethodCallExpr createCaller(MethodDeclaration nativeMethodDeclaration) { + String nativeMethodName = nativeMethodDeclaration.getNameAsString(); + MethodCallExpr caller = new MethodCallExpr(); + caller.setName(nativeMethodName); + return caller; + } + + private static void setupCallerParam(IDLMethod idlMethod, MethodCallExpr caller, MethodDeclaration methodDeclaration, String tempFieldName) { + boolean isStatic = idlMethod.isStaticMethod; + boolean isReturnValue = idlMethod.isReturnValue; + NodeList methodParameters = methodDeclaration.getParameters(); + + if(isReturnValue && tempFieldName != null) { + caller.addArgument(tempFieldName + "." + IDLDefaultCodeParser.CPOINTER_METHOD); + } + if(!isStatic) { + caller.addArgument(IDLDefaultCodeParser.CPOINTER_METHOD); + } + + for(int i = 0; i < methodParameters.size(); i++) { + Parameter parameter = methodParameters.get(i); + Type type = parameter.getType(); + String paramName = parameter.getNameAsString(); + if(type.isClassOrInterfaceType()) { + //All methods must contain a base class to get its pointer + paramName = paramName + ".getCPointer()"; + } + caller.addArgument(paramName); + } + } + + private static BlockStmt generateTempObjects(IDLMethod idlMethod, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration methodDeclaration, MethodDeclaration nativeMethodDeclaration, MethodCallExpr caller) { Type methodReturnType = methodDeclaration.getType(); String returnTypeName = methodReturnType.toString(); String newBody = null; - for(int i = 0; i < 20; i++) { - String fieldName = getFieldName(returnTypeName, i); - if(classDeclaration.getFieldByName(fieldName).isEmpty()) { - ObjectCreationExpr expression = new ObjectCreationExpr(); - expression.setType(returnTypeName); - expression.addArgument(StaticJavaParser.parseExpression("(byte)1")); - FieldDeclaration fieldDeclaration = classDeclaration.addFieldWithInitializer(methodReturnType, fieldName, expression, Modifier.Keyword.PRIVATE, Modifier.Keyword.FINAL); + boolean isReturnValue = idlMethod.isReturnValue; + boolean isStatic = methodDeclaration.isStatic(); - Position begin = new Position(0, 0); - Position end = new Position(0, 0); - Range range = new Range(begin, end); - fieldDeclaration.setRange(range); - String methodCaller = caller.toString(); - newBody = GET_OBJECT_TEMPLATE - .replace(TEMPLATE_TAG_METHOD, methodCaller) - .replace(TEMPLATE_TEMP_FIELD, fieldName); - break; - } + String fieldName = generateFieldName(classDeclaration, returnTypeName, isReturnValue, isStatic); + + setupCallerParam(idlMethod, caller, methodDeclaration, fieldName); + + String methodCaller = caller.toString(); + + if(isReturnValue) { + newBody = GET_TEMP_OBJECT_TEMPLATE + .replace(TEMPLATE_TAG_METHOD, methodCaller) + .replace(TEMPLATE_TEMP_FIELD, fieldName); + } + else { + newBody = GET_OBJECT_TEMPLATE + .replace(TEMPLATE_TAG_METHOD, methodCaller) + .replace(TEMPLATE_TEMP_FIELD, fieldName); } BlockStmt body = null; @@ -209,15 +232,66 @@ private static BlockStmt generateTempObjects(ClassOrInterfaceDeclaration classDe return body; } - private static String getFieldName(String type, int number) { - return TEMPLATE_TEMP_FIELD.replace(TEMPLATE_TAG_TYPE, type).replace(TEMPLATE_TAG_NUM, String.valueOf(number)); + public static String generateFieldName(ClassOrInterfaceDeclaration classDeclaration, String returnTypeName, boolean isTemp, boolean isStatic) { + // Will return a temp object. + // Java variable will be created by checking its class, name and number. + // if the temp object already exist it will increment variable number and create it. + // isTemp true will create an object to use a c++ pointer. cMemOwn = false + // isTemp false will actually create a c++ object by using the default constructor. cMemOwn = true + // When isTemp is false, the c++ class must have the assignment operator + + for(int i = 0; i < 20; i++) { + String fieldName = getFieldName(returnTypeName, i, isTemp, isStatic); + if(classDeclaration.getFieldByName(fieldName).isEmpty()) { + ObjectCreationExpr expression = new ObjectCreationExpr(); + expression.setType(returnTypeName); + if(isTemp) { + expression.addArgument(StaticJavaParser.parseExpression("(byte)1")); + } + FieldDeclaration fieldDeclaration; + if(isStatic) { + fieldDeclaration = classDeclaration.addFieldWithInitializer(returnTypeName, fieldName, expression, Modifier.Keyword.STATIC, Modifier.Keyword.PRIVATE, Modifier.Keyword.FINAL); + } + else { + fieldDeclaration = classDeclaration.addFieldWithInitializer(returnTypeName, fieldName, expression, Modifier.Keyword.PRIVATE, Modifier.Keyword.FINAL); + } + Position begin = new Position(0, 0); + Position end = new Position(0, 0); + Range range = new Range(begin, end); + fieldDeclaration.setRange(range); + return fieldName; + } + } + return null; + } + + private static String getFieldName(String type, int number, boolean isTemp, boolean isStatic) { + + if(isTemp) { + if(isStatic) { + return TEMPLATE_TEMP_STATIC_FIELD.replace(TEMPLATE_TAG_TYPE, type).replace(TEMPLATE_TAG_NUM, String.valueOf(number)); + } + else { + return TEMPLATE_TEMP_FIELD.replace(TEMPLATE_TAG_TYPE, type).replace(TEMPLATE_TAG_NUM, String.valueOf(number)); + } + } + else { + if(isStatic) { + return TEMPLATE_NEW_STATIC_FIELD.replace(TEMPLATE_TAG_TYPE, type).replace(TEMPLATE_TAG_NUM, String.valueOf(number)); + } + else { + return TEMPLATE_NEW_FIELD.replace(TEMPLATE_TAG_TYPE, type).replace(TEMPLATE_TAG_NUM, String.valueOf(number)); + } + } } - private static MethodDeclaration generateNativeMethod(MethodDeclaration methodDeclaration) { + private static MethodDeclaration generateNativeMethod(IDLMethod idlMethod, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration methodDeclaration) { String methodName = methodDeclaration.getNameAsString(); NodeList methodParameters = methodDeclaration.getParameters(); Type methodReturnType = methodDeclaration.getType(); boolean isStatic = methodDeclaration.isStatic(); + boolean isReturnValue = idlMethod.isReturnValue; + boolean isClassOrInterfaceType = methodReturnType.isClassOrInterfaceType(); // Clone some generated idl method settings MethodDeclaration nativeMethod = new MethodDeclaration(); @@ -225,9 +299,15 @@ private static MethodDeclaration generateNativeMethod(MethodDeclaration methodDe nativeMethod.setModifiers(Modifier.createModifierList(Modifier.Keyword.PRIVATE, Modifier.Keyword.STATIC, Modifier.Keyword.NATIVE)); nativeMethod.removeBody(); + if(isReturnValue) { + // We pass a temp c++ object to copy the returned temp c++ object + String pointerTempObject = "copy_addr"; + nativeMethod.addParameter("long", pointerTempObject); + } + if(!isStatic) { // Only generate addr if it's not a static method - nativeMethod.addAndGetParameter("long", "addr"); + nativeMethod.addParameter("long", "this_addr"); } for(int i = 0; i < methodParameters.size(); i++) { @@ -238,14 +318,21 @@ private static MethodDeclaration generateNativeMethod(MethodDeclaration methodDe nativeMethod.addParameter(type.clone(), nameAsString); } else { - String pointerMethod = nameAsString + "Addr"; + String pointerMethod = nameAsString + "_addr"; nativeMethod.addParameter("long", pointerMethod); } } - // If the return type is an object we need to return a pointer. - if(methodReturnType.isClassOrInterfaceType()) { - // Class Object needs to return a pointer - Type type = StaticJavaParser.parseType(long.class.getSimpleName()); + if(isClassOrInterfaceType) { + // If the return type is an object we need to return a pointer. + // If it's a value set to void + Type type; + if(isReturnValue) { + type = StaticJavaParser.parseType("void"); + } + else { + // If c++ is not a value and is a class object, return pointer + type = StaticJavaParser.parseType(long.class.getSimpleName()); + } nativeMethod.setType(type); } else { diff --git a/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/CppCodeParser.java b/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/CppCodeParser.java index 06cdcb4..e1e3b08 100644 --- a/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/CppCodeParser.java +++ b/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/CppCodeParser.java @@ -26,6 +26,7 @@ import com.github.xpenatan.jparser.idl.IDLParameter; import com.github.xpenatan.jparser.idl.IDLReader; import java.io.File; +import java.util.ArrayList; import java.util.List; public class CppCodeParser extends IDLDefaultCodeParser { @@ -38,6 +39,10 @@ public class CppCodeParser extends IDLDefaultCodeParser { protected static final String TEMPLATE_TAG_METHOD = "[METHOD]"; + protected static final String TEMPLATE_TAG_COPY_TYPE = "[COPY_TYPE]"; + + protected static final String TEMPLATE_TAG_COPY_PARAM = "[COPY_PARAM]"; + protected static final String STATIC_GET_METHOD_VOID_TEMPLATE = "" + "\n[TYPE]::[METHOD];\n"; @@ -51,19 +56,26 @@ public class CppCodeParser extends IDLDefaultCodeParser { "\nreturn [TYPE]::[METHOD];\n"; protected static final String GET_METHOD_VOID_TEMPLATE = "" + - "\n[TYPE]* nativeObject = ([TYPE]*)addr;\n" + + "\n[TYPE]* nativeObject = ([TYPE]*)this_addr;\n" + "nativeObject->[METHOD];\n"; protected static final String GET_METHOD_OBJ_POINTER_TEMPLATE = "" + - "\n[TYPE]* nativeObject = ([TYPE]*)addr;\n" + + "\n[TYPE]* nativeObject = ([TYPE]*)this_addr;\n" + "return (jlong)nativeObject->[METHOD];\n"; protected static final String GET_METHOD_OBJ_POINTER_REF_TEMPLATE = "" + - "\n[TYPE]* nativeObject = ([TYPE]*)addr;\n" + + "\n[TYPE]* nativeObject = ([TYPE]*)this_addr;\n" + "return (jlong)&nativeObject->[METHOD];\n"; + protected static final String COPY_METHOD_VALUE_TEMPLATE = "" + + "\n[TYPE]* nativeObject = ([TYPE]*)this_addr;\n" + + "*(([COPY_TYPE]*)[COPY_PARAM]) = nativeObject->[METHOD];\n"; + + protected static final String COPY_STATIC_METHOD_VALUE_TEMPLATE = "" + + "\n*(([COPY_TYPE]*)[COPY_PARAM]) = [TYPE]::[METHOD];\n"; + protected static final String GET_METHOD_PRIMITIVE_TEMPLATE = "" + - "\n[TYPE]* nativeObject = ([TYPE]*)addr;\n" + + "\n[TYPE]* nativeObject = ([TYPE]*)this_addr;\n" + "return nativeObject->[METHOD];\n"; protected static final String GET_OBJECT_TEMPLATE = "" + @@ -131,7 +143,7 @@ public CppCodeParser(CppGenerator cppGenerator, IDLReader idlReader, String base @Override public void onIDLMethodGenerated(JParser jParser, IDLMethod idlMethod, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration methodDeclaration, MethodDeclaration nativeMethodDeclaration) { - generateNativeMethodAnnotation(idlMethod, classDeclaration, methodDeclaration, nativeMethodDeclaration, false); + generateNativeAnnotation(idlMethod, classDeclaration, methodDeclaration, nativeMethodDeclaration); } @Override @@ -150,7 +162,7 @@ public void onIDLMethodGenerated(JParser jParser, IDLClass idlClass, IDLMethod i nativeMethod.setName(idlMethodName + "NATIVE"); nativeMethod.setModifiers(Modifier.createModifierList(Modifier.Keyword.PRIVATE, Modifier.Keyword.STATIC, Modifier.Keyword.NATIVE)); nativeMethod.removeBody(); - nativeMethod.addAndGetParameter("long", "addr"); + nativeMethod.addAndGetParameter("long", "this_addr"); for(int i = 0; i < idlMethodParameters.size(); i++) { Parameter parameter = idlMethodParameters.get(i); @@ -160,7 +172,7 @@ public void onIDLMethodGenerated(JParser jParser, IDLClass idlClass, IDLMethod i nativeMethod.addParameter(type.clone(), nameAsString); } else { - String pointerMethod = nameAsString + "Addr"; + String pointerMethod = nameAsString + "_addr"; nativeMethod.addParameter("long", pointerMethod); } } @@ -173,8 +185,7 @@ public void onIDLMethodGenerated(JParser jParser, IDLClass idlClass, IDLMethod i else { nativeMethod.setType(idlMethodReturnType); } - //Generate teaVM Annotation - generateNativeMethodAnnotation(idlMethod, classDeclaration, idlMethodDeclaration, nativeMethod, isAttribute); + generateNativeAnnotation(idlMethod, classDeclaration, idlMethodDeclaration, nativeMethod); } // Check if the generated method does not exist in the original class if(!JParserHelper.containsMethod(classDeclaration, nativeMethod)) { @@ -233,44 +244,15 @@ private ReturnStmt getReturnStmt(MethodDeclaration idlMethodDeclaration) { } } - private void generateNativeMethodAnnotation(IDLMethod idlMethod, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration idlMethodDeclaration, MethodDeclaration nativeMethod, boolean isAttribute) { + private void generateNativeAnnotation(IDLMethod idlMethod, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration idlMethodDeclaration, MethodDeclaration nativeMethod) { NodeList nativeParameters = nativeMethod.getParameters(); Type returnType = idlMethodDeclaration.getType(); String methodName = idlMethodDeclaration.getNameAsString(); boolean isStatic = idlMethodDeclaration.isStatic(); + boolean isReturnValue = idlMethod.isReturnValue; - String param = ""; - int size = nativeParameters.size(); - - for(int i = 0; i < size; i++) { - Parameter parameter = nativeParameters.get(i); - Type type = parameter.getType(); - String paramName = parameter.getNameAsString(); - boolean isObject = paramName.endsWith("Addr"); - if(i > 0 || isStatic) { - if(isObject && idlMethod != null) { - IDLParameter idlParameter = idlMethod.parameters.get(i - 1); - String classType = idlParameter.type; - IDLClass paramClass = idlParameter.idlFile.getClass(classType); - if(paramClass != null) { - classType = paramClass.getName(); - } - if(idlParameter.isRef) { - paramName = "*((" + classType + "* )" + paramName + ")"; - } - else { - paramName = "(" + classType + "* )" + paramName; - } - } - - param += paramName; - if(i < size - 1) { - param += ", "; - } - } - } - - String returnTypeName = classDeclaration.getNameAsString(); + String param = getParams(idlMethod, idlMethodDeclaration); + String classTypeName = classDeclaration.getNameAsString(); String methodCaller = methodName + "(" + param + ")"; String content = null; @@ -282,43 +264,57 @@ private void generateNativeMethodAnnotation(IDLMethod idlMethod, ClassOrInterfac // } if(isStatic) { - content = STATIC_GET_METHOD_VOID_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + content = STATIC_GET_METHOD_VOID_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); } else { - content = GET_METHOD_VOID_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + content = GET_METHOD_VOID_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); } } else if(returnType.isClassOrInterfaceType()) { - if(isAttribute) { - methodCaller = methodName; + if(idlMethod.isReturnRef) { + if(isStatic) { + content = STATIC_GET_METHOD_OBJ_POINTER_REF_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); + } + else { + content = GET_METHOD_OBJ_POINTER_REF_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); + } } - if(idlMethod != null && idlMethod.isReturnRef) { + else if(idlMethod.isReturnValue) { + // For temporary c++ object, the class needs to contains assignment operator if(isStatic) { - content = STATIC_GET_METHOD_OBJ_POINTER_REF_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + String returnTypeName = returnType.asClassOrInterfaceType().asClassOrInterfaceType().getNameAsString(); + String copyParam = "copy_addr"; + content = COPY_STATIC_METHOD_VALUE_TEMPLATE + .replace(TEMPLATE_TAG_METHOD, methodCaller) + .replace(TEMPLATE_TAG_TYPE, classTypeName) + .replace(TEMPLATE_TAG_COPY_TYPE, returnTypeName) + .replace(TEMPLATE_TAG_COPY_PARAM, copyParam); } else { - content = GET_METHOD_OBJ_POINTER_REF_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + String returnTypeName = returnType.asClassOrInterfaceType().asClassOrInterfaceType().getNameAsString(); + String copyParam = "copy_addr"; + content = COPY_METHOD_VALUE_TEMPLATE + .replace(TEMPLATE_TAG_METHOD, methodCaller) + .replace(TEMPLATE_TAG_TYPE, classTypeName) + .replace(TEMPLATE_TAG_COPY_TYPE, returnTypeName) + .replace(TEMPLATE_TAG_COPY_PARAM, copyParam); } } else { if(isStatic) { - content = STATIC_GET_METHOD_OBJ_POINTER_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + content = STATIC_GET_METHOD_OBJ_POINTER_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); } else { - content = GET_METHOD_OBJ_POINTER_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + content = GET_METHOD_OBJ_POINTER_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); } } } else { - if(isAttribute) { - methodCaller = methodName; - } - if(isStatic) { - content = STATIC_GET_METHOD_PRIMITIVE_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + content = STATIC_GET_METHOD_PRIMITIVE_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); } else { - content = GET_METHOD_PRIMITIVE_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, returnTypeName); + content = GET_METHOD_PRIMITIVE_TEMPLATE.replace(TEMPLATE_TAG_METHOD, methodCaller).replace(TEMPLATE_TAG_TYPE, classTypeName); } } @@ -329,6 +325,41 @@ else if(returnType.isClassOrInterfaceType()) { } } + private static String getParams(IDLMethod idlMethod, MethodDeclaration methodDeclaration) { + String param = ""; + + NodeList parameters = methodDeclaration.getParameters(); + ArrayList idParameters = idlMethod.parameters; + + for(int i = 0; i < parameters.size(); i++) { + Parameter parameter = parameters.get(i); + IDLParameter idlParameter = idParameters.get(i); + String paramName = idlParameter.name; + Type type = parameter.getType(); + boolean isObject = type.isClassOrInterfaceType(); + if(isObject) { + paramName += "_addr"; + String classType = idlParameter.type; + IDLClass paramClass = idlParameter.idlFile.getClass(classType); + if(paramClass != null) { + classType = paramClass.getName(); + } + if(idlParameter.isRef || idlParameter.isValue) { + paramName = "*((" + classType + "* )" + paramName + ")"; + } + else { + paramName = "(" + classType + "* )" + paramName; + } + } + + if(i > 0) { + param += ", "; + } + param += paramName; + } + return param; + } + protected BlockStmt generateObjectPointerReturnType(CompilationUnit unit, ClassOrInterfaceDeclaration classDeclaration, MethodDeclaration idlMethodDeclaration, MethodCallExpr caller) { // if return type is an object we need to get the method pointer, add it do a temp object and return this object Type type = idlMethodDeclaration.getType(); diff --git a/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/NativeCPPGeneratorV2.java b/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/NativeCPPGeneratorV2.java index 3b87129..a89552c 100644 --- a/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/NativeCPPGeneratorV2.java +++ b/jParser/cpp/src/main/java/com/github/xpenatan/jparser/cpp/NativeCPPGeneratorV2.java @@ -7,12 +7,14 @@ import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.Parameter; import com.github.xpenatan.jparser.core.JParser; +import com.github.xpenatan.jparser.core.JParserHelper; import com.github.xpenatan.jparser.core.JParserItem; import com.github.xpenatan.jparser.core.util.CustomFileDescriptor; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.Scanner; public class NativeCPPGeneratorV2 implements CppGenerator { @@ -21,8 +23,20 @@ public class NativeCPPGeneratorV2 implements CppGenerator { private static final Map arrayTypes; private static final Map bufferTypes; private static final Map otherTypes; + private static final Map valueTypes; static { + valueTypes = new HashMap<>(); + valueTypes.put(JavaMethodParser.ArgumentType.Boolean.getJniType(), "Z"); + valueTypes.put(JavaMethodParser.ArgumentType.Byte.getJniType(), "B"); + valueTypes.put(JavaMethodParser.ArgumentType.Char.getJniType(), "C"); + valueTypes.put(JavaMethodParser.ArgumentType.Short.getJniType(), "S"); + valueTypes.put(JavaMethodParser.ArgumentType.Integer.getJniType(), "I"); + valueTypes.put(JavaMethodParser.ArgumentType.Long.getJniType(), "J"); + valueTypes.put(JavaMethodParser.ArgumentType.Float.getJniType(), "F"); + valueTypes.put(JavaMethodParser.ArgumentType.Double.getJniType(), "D"); + valueTypes.put(JavaMethodParser.ArgumentType.Object.getJniType(), "L"); + plainOldDataTypes = new HashMap(); plainOldDataTypes.put("boolean", JavaMethodParser.ArgumentType.Boolean); plainOldDataTypes.put("byte", JavaMethodParser.ArgumentType.Byte); @@ -111,26 +125,34 @@ public void addNativeCode(MethodDeclaration methodDeclaration, String content) { String className = classDeclaration.getNameAsString(); String packageNameCPP = packageName.replace(".", "_"); String returnTypeStr = methodDeclaration.getType().toString(); - JavaMethodParser.ArgumentType returnType = getType(returnTypeStr); + String returnType = returnTypeStr.equals("void") ? returnTypeStr : getType(returnTypeStr).getJniType(); String params = "(JNIEnv* env, jclass clazz"; - ArrayList arguments = new ArrayList(); + ArrayList arguments = new ArrayList(); if(methodDeclaration.getParameters() != null) { for(Parameter parameter : methodDeclaration.getParameters()) { - JavaMethodParser.ArgumentType argumentType = getArgumentType(parameter); - arguments.add(new JavaMethodParser.Argument(argumentType, parameter.getNameAsString())); + Argument argument = getArgument(parameter); + arguments.add(argument); } } + String paramsType = ""; + for(int i = 0; i < arguments.size(); i++) { - JavaMethodParser.Argument argument = arguments.get(i); + Argument argument = arguments.get(i); + paramsType+= argument.getValueType(); params += ", " + argument.getType().getJniType() + " " + argument.getName(); } + if(!paramsType.isEmpty()) { + paramsType = "__" + paramsType; + } + params += ")"; - print("JNIEXPORT " + returnType.getJniType() + " JNICALL Java_" + packageNameCPP + "_" + className + "_" + methodName + params + " {"); + String fullMethodName = packageNameCPP + "_" + className + "_" + methodName + paramsType + params; + print("JNIEXPORT " + returnType + " JNICALL Java_" + fullMethodName + " {"); content = "\t" + content.replace("\n", "\n\t"); print(content); print("}"); @@ -159,10 +181,12 @@ public void generate(JParser jParser) { cppFile.writeString(include, false); } - private JavaMethodParser.ArgumentType getArgumentType(Parameter parameter) { + private Argument getArgument(Parameter parameter) { String[] typeTokens = parameter.getType().toString().split("\\."); String type = typeTokens[typeTokens.length - 1]; - return getType(type); + JavaMethodParser.ArgumentType argumentType = getType(type); + String valueType = valueTypes.get(argumentType.getJniType()); + return new Argument(argumentType, parameter.getNameAsString(), valueType); } private JavaMethodParser.ArgumentType getType(String type) { @@ -186,4 +210,33 @@ private JavaMethodParser.ArgumentType getType(String type) { if(otherTypes.containsKey(type)) return otherTypes.get(type); return JavaMethodParser.ArgumentType.Object; } + + public static class Argument { + final JavaMethodParser.ArgumentType type; + private final String name; + private final String valueType; + + public Argument (JavaMethodParser.ArgumentType type, String name, String valueType) { + this.type = type; + this.name = name; + this.valueType = valueType; + } + + public JavaMethodParser.ArgumentType getType () { + return type; + } + + public String getName () { + return name; + } + + public String getValueType() { + return valueType; + } + + @Override + public String toString () { + return "Argument [type=" + type + ", name=" + name + ", valueType=" + valueType + "]"; + } + } } diff --git a/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLMethod.java b/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLMethod.java index 533d8f8..bf3afdf 100644 --- a/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLMethod.java +++ b/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLMethod.java @@ -62,6 +62,9 @@ public void initMethod(String line) { if(returnType.equals("long")) { returnType = "int"; } + if(returnType.equals("DOMString")) { + returnType = "String"; + } name = s[s.length-1]; if(paramsLine != null && paramsLine.contains("any ")) { diff --git a/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLParameter.java b/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLParameter.java index 32fbdf2..bbd3d05 100644 --- a/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLParameter.java +++ b/jParser/idl/src/main/java/com.github.xpenatan.jparser.idl/IDLParameter.java @@ -14,6 +14,7 @@ public class IDLParameter { public boolean isArray; public boolean isRef; public boolean isConst; + public boolean isValue; public final ArrayList tags = new ArrayList<>(); public boolean optional; @@ -35,6 +36,7 @@ public void initParameter(String line) { String substring1 = line.substring(startIndex, endIndex + 1); isRef = substring1.contains("Ref"); isConst = substring1.contains("Const"); + isValue = substring1.contains("Value"); String substring2 = substring1.replace("[", "").replace("]", ""); String[] s = substring2.split(" "); for(int i = 0; i < s.length; i++) { @@ -50,6 +52,9 @@ public void initParameter(String line) { type = "int"; } + if(type.equals("DOMString")) { + type = "String"; + } name = s1[s1.length - 1]; } diff --git a/jParser/idl/src/test/java/com/github/xpenatan/jparser/idl/IDLReaderTest.java b/jParser/idl/src/test/java/com/github/xpenatan/jparser/idl/IDLReaderTest.java index a368442..7c0eb14 100644 --- a/jParser/idl/src/test/java/com/github/xpenatan/jparser/idl/IDLReaderTest.java +++ b/jParser/idl/src/test/java/com/github/xpenatan/jparser/idl/IDLReaderTest.java @@ -26,6 +26,7 @@ public void test_NoDeleteClassTest_static_method() { Assert.assertEquals("GetNormalValueClass", idlMethod.name); Assert.assertEquals("NormalClassTest", idlMethod.returnType); Assert.assertEquals(true, idlMethod.isReturnValue); + Assert.assertEquals(true, idlMethod.isStaticMethod); } @Test