You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2021/09/24 19:13:27 UTC

[plc4x] branch develop updated (583a8f9 -> ef35531)

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a change to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


    from 583a8f9  Removed a duplicate mention of the mspec base OPC-UA driver
     new 9470bbb  fix: fix stackoverflow on type referencing each other
     new 212818e  feat: inject tracer into freemarker templates
     new 26bcca7  feat: add more tracer calls
     new ef35531  fix(java/codegen): virtual field handling

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../BaseFreemarkerLanguageTemplateHelper.java      |  71 +++---
 .../freemarker/FreemarkerLanguageOutput.java       |   2 +
 .../language/go/GoLanguageTemplateHelper.java      |  16 +-
 .../language/java/JavaLanguageTemplateHelper.java  | 266 ++++++++++++---------
 4 files changed, 205 insertions(+), 150 deletions(-)

[plc4x] 03/04: feat: add more tracer calls

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 26bcca72547d2a6f755567632a19664d9aeb9760
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 24 20:35:19 2021 +0200

    feat: add more tracer calls
---
 .../language/go/GoLanguageTemplateHelper.java      |  16 +-
 .../language/java/JavaLanguageTemplateHelper.java  | 263 ++++++++++++---------
 2 files changed, 158 insertions(+), 121 deletions(-)

diff --git a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
index feb766e..9347768 100644
--- a/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
+++ b/code-generation/language-go/src/main/java/org/apache/plc4x/language/go/GoLanguageTemplateHelper.java
@@ -512,7 +512,7 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                 tracer = tracer.dive("null literal instanceOf");
                 return tracer + "nil";
             } else if (term instanceof BooleanLiteral) {
-                tracer = tracer.dive("null literal instanceOf");
+                tracer = tracer.dive("boolean literal instanceOf");
                 return tracer + getCastExpressionForTypeReference(fieldType) + "(" + ((BooleanLiteral) term).getValue() + ")";
             } else if (term instanceof NumericLiteral) {
                 tracer = tracer.dive("numeric literal instanceOf");
@@ -523,9 +523,11 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                     return tracer + getCastExpressionForTypeReference(fieldType) + "(" + ((NumericLiteral) term).getNumber().toString() + ")";
                 }
             } else if (term instanceof StringLiteral) {
-                return "\"" + ((StringLiteral) term).getValue() + "\"";
+                tracer = tracer.dive("string literal instanceOf");
+                return tracer + "\"" + ((StringLiteral) term).getValue() + "\"";
             } else if (term instanceof VariableLiteral) {
-                return toVariableExpression(fieldType, (VariableLiteral) term, parserArguments, serializerArguments, serialize, suppressPointerAccess);
+                tracer = tracer.dive("variable literal instanceOf");
+                return tracer+toVariableExpression(fieldType, (VariableLiteral) term, parserArguments, serializerArguments, serialize, suppressPointerAccess);
             } else {
                 throw new RuntimeException("Unsupported Literal type " + term.getClass().getName());
             }
@@ -707,11 +709,11 @@ public class GoLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHelp
                     }
                     if (isParserArg) {
                         if (va.getName().equals("_value")) {
-                            sb.append(va.getName().substring(1) + ((va.getChild() != null) ?
-                                "." + toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, false, suppressPointerAccess) : ""));
+                            sb.append(va.getName().substring(1)).append((va.getChild() != null) ?
+                                "." + toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, false, suppressPointerAccess) : "");
                         } else {
-                            sb.append(va.getName() + ((va.getChild() != null) ?
-                                "." + toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, false, suppressPointerAccess) : ""));
+                            sb.append(va.getName()).append((va.getChild() != null) ?
+                                "." + toVariableExpression(typeReference, vl.getChild(), parserArguments, serializerArguments, false, suppressPointerAccess) : "");
                         }
                     }
                     // We have to manually evaluate the type information at code-generation time.
diff --git a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index 39973ee..e12fd93 100644
--- a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -18,12 +18,19 @@
  */
 package org.apache.plc4x.language.java;
 
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.util.Optional;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang3.math.NumberUtils;
 import org.apache.commons.text.WordUtils;
 import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.BaseFreemarkerLanguageTemplateHelper;
+import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.Tracer;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.*;
 import org.apache.plc4x.plugins.codegenerator.types.fields.*;
 import org.apache.plc4x.plugins.codegenerator.types.references.*;
@@ -95,42 +102,42 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
             SimpleTypeReference simpleTypeReference = (SimpleTypeReference) typeReference;
             switch (simpleTypeReference.getBaseType()) {
                 case BIT: {
-                    return allowPrimitive ? "boolean" : "Boolean";
+                    return allowPrimitive ? boolean.class.getSimpleName() : Boolean.class.getSimpleName();
                 }
                 case BYTE: {
-                    return allowPrimitive ? "byte" : "Byte";
+                    return allowPrimitive ? byte.class.getSimpleName() : Byte.class.getSimpleName();
                 }
                 case UINT: {
                     IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
                     if (integerTypeReference.getSizeInBits() <= 4) {
-                        return allowPrimitive ? "byte" : "Byte";
+                        return allowPrimitive ? byte.class.getSimpleName() : Byte.class.getSimpleName();
                     }
                     if (integerTypeReference.getSizeInBits() <= 8) {
-                        return allowPrimitive ? "short" : "Short";
+                        return allowPrimitive ? short.class.getSimpleName() : Short.class.getSimpleName();
                     }
                     if (integerTypeReference.getSizeInBits() <= 16) {
-                        return allowPrimitive ? "int" : "Integer";
+                        return allowPrimitive ? int.class.getSimpleName() : Integer.class.getSimpleName();
                     }
                     if (integerTypeReference.getSizeInBits() <= 32) {
-                        return allowPrimitive ? "long" : "Long";
+                        return allowPrimitive ? long.class.getSimpleName() : Long.class.getSimpleName();
                     }
-                    return "BigInteger";
+                    return BigInteger.class.getSimpleName();
                 }
                 case INT: {
                     IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference;
                     if (integerTypeReference.getSizeInBits() <= 8) {
-                        return allowPrimitive ? "byte" : "Byte";
+                        return allowPrimitive ? byte.class.getSimpleName() : Byte.class.getSimpleName();
                     }
                     if (integerTypeReference.getSizeInBits() <= 16) {
-                        return allowPrimitive ? "short" : "Short";
+                        return allowPrimitive ? short.class.getSimpleName() : Short.class.getSimpleName();
                     }
                     if (integerTypeReference.getSizeInBits() <= 32) {
-                        return allowPrimitive ? "int" : "Integer";
+                        return allowPrimitive ? int.class.getSimpleName() : Integer.class.getSimpleName();
                     }
                     if (integerTypeReference.getSizeInBits() <= 64) {
-                        return allowPrimitive ? "long" : "Long";
+                        return allowPrimitive ? long.class.getSimpleName() : Long.class.getSimpleName();
                     }
-                    return "BigInteger";
+                    return BigInteger.class.getSimpleName();
                 }
                 case FLOAT:
                 case UFLOAT: {
@@ -138,24 +145,24 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                     int sizeInBits = ((floatTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.FLOAT) ? 1 : 0) +
                         floatTypeReference.getExponent() + floatTypeReference.getMantissa();
                     if (sizeInBits <= 32) {
-                        return allowPrimitive ? "float" : "Float";
+                        return allowPrimitive ? float.class.getSimpleName() : Float.class.getSimpleName();
                     }
                     if (sizeInBits <= 64) {
-                        return allowPrimitive ? "double" : "Double";
+                        return allowPrimitive ? double.class.getSimpleName() : Double.class.getSimpleName();
                     }
-                    return "BigDecimal";
+                    return BigDecimal.class.getSimpleName();
                 }
                 case STRING: {
-                    return "String";
+                    return String.class.getSimpleName();
                 }
                 case TIME: {
-                    return "LocalTime";
+                    return LocalTime.class.getSimpleName();
                 }
                 case DATE: {
-                    return "LocalDate";
+                    return LocalDate.class.getSimpleName();
                 }
                 case DATETIME: {
-                    return "LocalDateTime";
+                    return LocalDateTime.class.getSimpleName();
                 }
             }
             throw new RuntimeException("Unsupported simple type");
@@ -534,80 +541,97 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
     }*/
 
     public String toAccessExpression(TypedField field, Term term, Argument[] parserArguments) {
-        return toExpression(field, term, term1 -> {
-            VariableLiteral vl = (VariableLiteral) term1;
-            if (isVariableLiteralVirtualField(vl) || isVariableLiteralDiscriminatorField(vl)) { // If we are accessing virtual|discriminator fields, we need to call the getter.
-                return "get" + StringUtils.capitalize(vl.getName()) + "()";
+        return toExpression(field, term, variableLiteral -> {
+            if (isVariableLiteralVirtualField(variableLiteral) || isVariableLiteralDiscriminatorField(variableLiteral)) { // If we are accessing virtual|discriminator fields, we need to call the getter.
+                return "get" + StringUtils.capitalize(variableLiteral.getName()) + "()";
             }
-            return toVariableParseExpression(field, term1, parserArguments);
+            return toVariableParseExpression(field, variableLiteral, parserArguments);
         });
     }
 
     public String toParseExpression(TypedField field, Term term, Argument[] parserArguments) {
-        return toExpression(field, term, term1 -> toVariableParseExpression(field, term1, parserArguments));
+        Tracer tracer = Tracer.start("toParseExpression");
+        return tracer + toExpression(field, term, variableLiteral -> tracer.dive("variableExpressionGenerator") + toVariableParseExpression(field, variableLiteral, parserArguments));
     }
 
     public String toSerializationExpression(TypedField field, Term term, Argument[] serializerArgments) {
-        return toExpression(field, term, term1 -> toVariableSerializationExpression(field, term1, serializerArgments));
+        Tracer tracer = Tracer.start("toSerializationExpression");
+        return tracer + toExpression(field, term, variableLiteral -> tracer.dive("variableExpressionGenerator") + toVariableSerializationExpression(field, variableLiteral, serializerArgments));
     }
 
-    private String toExpression(TypedField field, Term term, Function<Term, String> variableExpressionGenerator) {
+    private String toExpression(TypedField field, Term term, Function<VariableLiteral, String> variableExpressionGenerator) {
+        Tracer tracer = Tracer.start("toExpression");
         if (term == null) {
             return "";
         }
         if (term instanceof Literal) {
-            if (term instanceof NullLiteral) {
-                return "null";
-            } else if (term instanceof BooleanLiteral) {
-                return Boolean.toString(((BooleanLiteral) term).getValue());
-            } else if (term instanceof NumericLiteral) {
-                return ((NumericLiteral) term).getNumber().toString();
-            } else if (term instanceof StringLiteral) {
-                return "\"" + ((StringLiteral) term).getValue() + "\"";
-            } else if (term instanceof VariableLiteral) {
-                VariableLiteral variableLiteral = (VariableLiteral) term;
+            tracer = tracer.dive("literal term instanceOf");
+            Literal literal = (Literal) term;
+            if (literal instanceof NullLiteral) {
+                tracer = tracer.dive("null literal instanceOf");
+                return tracer + "null";
+            } else if (literal instanceof BooleanLiteral) {
+                tracer = tracer.dive("boolean literal instanceOf");
+                return tracer + Boolean.toString(((BooleanLiteral) literal).getValue());
+            } else if (literal instanceof NumericLiteral) {
+                tracer = tracer.dive("numeric literal instanceOf");
+                return tracer + ((NumericLiteral) literal).getNumber().toString();
+            } else if (literal instanceof StringLiteral) {
+                tracer = tracer.dive("string literal instanceOf");
+                return tracer + "\"" + ((StringLiteral) literal).getValue() + "\"";
+            } else if (literal instanceof VariableLiteral) {
+                tracer = tracer.dive("variable literal instanceOf");
+                VariableLiteral variableLiteral = (VariableLiteral) literal;
                 // If this literal references an Enum type, then we have to output it differently.
                 if (getTypeDefinitions().get(variableLiteral.getName()) instanceof EnumTypeDefinition) {
-                    return variableLiteral.getName() + "." + variableLiteral.getChild().getName() +
+                    tracer = tracer.dive("enum definition instanceOf");
+                    return tracer + variableLiteral.getName() + "." + variableLiteral.getChild().getName() +
                         ((variableLiteral.getChild().getChild() != null) ?
                             "." + toVariableExpressionRest(variableLiteral.getChild().getChild()) : "");
                 } else {
-                    return variableExpressionGenerator.apply(term);
+                    return tracer + variableExpressionGenerator.apply(variableLiteral);
                 }
             } else {
-                throw new RuntimeException("Unsupported Literal type " + term.getClass().getName());
+                throw new RuntimeException("Unsupported Literal type " + literal.getClass().getName());
             }
         } else if (term instanceof UnaryTerm) {
+            tracer = tracer.dive("unary term instanceOf");
             UnaryTerm ut = (UnaryTerm) term;
             Term a = ut.getA();
             switch (ut.getOperation()) {
                 case "!":
-                    return "!(" + toExpression(field, a, variableExpressionGenerator) + ")";
+                    tracer = tracer.dive("case !");
+                    return tracer + "!(" + toExpression(field, a, variableExpressionGenerator) + ")";
                 case "-":
-                    return "-(" + toExpression(field, a, variableExpressionGenerator) + ")";
+                    tracer = tracer.dive("case -");
+                    return tracer + "-(" + toExpression(field, a, variableExpressionGenerator) + ")";
                 case "()":
-                    return "(" + toExpression(field, a, variableExpressionGenerator) + ")";
+                    tracer = tracer.dive("case ()");
+                    return tracer + "(" + toExpression(field, a, variableExpressionGenerator) + ")";
                 default:
                     throw new RuntimeException("Unsupported unary operation type " + ut.getOperation());
             }
         } else if (term instanceof BinaryTerm) {
+            tracer = tracer.dive("binary term instanceOf");
             BinaryTerm bt = (BinaryTerm) term;
             Term a = bt.getA();
             Term b = bt.getB();
             String operation = bt.getOperation();
             switch (operation) {
                 case "^":
-                    return "Math.pow((" + toExpression(field, a, variableExpressionGenerator) + "), (" + toExpression(field, b, variableExpressionGenerator) + "))";
+                    tracer = tracer.dive("^");
+                    return tracer + "Math.pow((" + toExpression(field, a, variableExpressionGenerator) + "), (" + toExpression(field, b, variableExpressionGenerator) + "))";
                 default:
-                    return "(" + toExpression(field, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, b, variableExpressionGenerator) + ")";
+                    return tracer + "(" + toExpression(field, a, variableExpressionGenerator) + ") " + operation + " (" + toExpression(field, b, variableExpressionGenerator) + ")";
             }
         } else if (term instanceof TernaryTerm) {
+            tracer = tracer.dive("ternary term instanceOf");
             TernaryTerm tt = (TernaryTerm) term;
             if ("if".equals(tt.getOperation())) {
                 Term a = tt.getA();
                 Term b = tt.getB();
                 Term c = tt.getC();
-                return "((" + toExpression(field, a, variableExpressionGenerator) + ") ? " + toExpression(field, b, variableExpressionGenerator) + " : " + toExpression(field, c, variableExpressionGenerator) + ")";
+                return tracer + "((" + toExpression(field, a, variableExpressionGenerator) + ") ? " + toExpression(field, b, variableExpressionGenerator) + " : " + toExpression(field, c, variableExpressionGenerator) + ")";
             } else {
                 throw new RuntimeException("Unsupported ternary operation type " + tt.getOperation());
             }
@@ -616,49 +640,53 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
         }
     }
 
-    private String toVariableParseExpression(TypedField field, Term term, Argument[] parserArguments) {
-        VariableLiteral vl = (VariableLiteral) term;
+    private String toVariableParseExpression(TypedField field, VariableLiteral variableLiteral, Argument[] parserArguments) {
+        Tracer tracer = Tracer.start("toVariableParseExpression");
         // CAST expressions are special as we need to add a ".class" to the second parameter in Java.
-        if ("CAST".equals(vl.getName())) {
-            StringBuilder sb = new StringBuilder(vl.getName());
-            if ((vl.getArgs() == null) || (vl.getArgs().size() != 2)) {
+        if ("CAST".equals(variableLiteral.getName())) {
+            tracer = tracer.dive("CAST");
+            StringBuilder sb = new StringBuilder(variableLiteral.getName());
+            if ((variableLiteral.getArgs() == null) || (variableLiteral.getArgs().size() != 2)) {
                 throw new RuntimeException("A CAST expression expects exactly two arguments.");
             }
-            sb.append("(").append(toVariableParseExpression(field, vl.getArgs().get(0), parserArguments))
-                .append(", ").append(((VariableLiteral) vl.getArgs().get(1)).getName()).append(".class)");
-            return sb + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
-        } else if ("STATIC_CALL".equals(vl.getName())) {
+            sb.append("(")
+                .append(toVariableParseExpression(field, (VariableLiteral) variableLiteral.getArgs().get(0), parserArguments))
+                .append(", ")
+                .append(((VariableLiteral) variableLiteral.getArgs().get(1)).getName()).append(".class)");
+            return tracer + sb.toString() + ((variableLiteral.getChild() != null) ? "." + toVariableExpressionRest(variableLiteral.getChild()) : "");
+        } else if ("STATIC_CALL".equals(variableLiteral.getName())) {
+            tracer = tracer.dive("STATIC_CALL");
             StringBuilder sb = new StringBuilder();
-            if (!(vl.getArgs().get(0) instanceof StringLiteral)) {
+            if (!(variableLiteral.getArgs().get(0) instanceof StringLiteral)) {
                 throw new RuntimeException("Expecting the first argument of a 'STATIC_CALL' to be a StringLiteral");
             }
             // Get the class and method name
-            String methodName = ((StringLiteral) vl.getArgs().get(0)).getValue();
+            String methodName = ((StringLiteral) variableLiteral.getArgs().get(0)).getValue();
             // Cut off the double-quotes
             methodName = methodName.substring(1, methodName.length() - 1);
             sb.append(methodName).append("(");
-            for (int i = 1; i < vl.getArgs().size(); i++) {
-                Term arg = vl.getArgs().get(i);
+            for (int i = 1; i < variableLiteral.getArgs().size(); i++) {
+                Term arg = variableLiteral.getArgs().get(i);
                 if (i > 1) {
                     sb.append(", ");
                 }
                 if (arg instanceof VariableLiteral) {
-                    VariableLiteral va = (VariableLiteral) arg;
+                    VariableLiteral variableLiteralArg = (VariableLiteral) arg;
                     // "readBuffer" is the default name of the reader argument which is always available.
-                    boolean isParserArg = "readBuffer".equals(va.getName());
-                    boolean isTypeArg = "_type".equals(va.getName());
+                    boolean isParserArg = "readBuffer".equals(variableLiteralArg.getName());
+                    boolean isTypeArg = "_type".equals(variableLiteralArg.getName());
                     if (!isParserArg && !isTypeArg && parserArguments != null) {
                         for (Argument parserArgument : parserArguments) {
-                            if (parserArgument.getName().equals(va.getName())) {
+                            if (parserArgument.getName().equals(variableLiteralArg.getName())) {
                                 isParserArg = true;
                                 break;
                             }
                         }
                     }
                     if (isParserArg) {
-                        sb.append(va.getName()).append((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : "");
+                        sb.append(variableLiteralArg.getName()).append((variableLiteralArg.getChild() != null) ? "." + toVariableExpressionRest(variableLiteralArg.getChild()) : "");
                     } else if (isTypeArg) {// We have to manually evaluate the type information at code-generation time.
-                        String part = va.getChild().getName();
+                        String part = variableLiteralArg.getChild().getName();
                         switch (part) {
                             case "name":
                                 sb.append("\"").append(field.getTypeName()).append("\"");
@@ -674,22 +702,24 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                                 break;
                         }
                     } else {
-                        sb.append(toVariableParseExpression(field, va, null));
+                        sb.append(toVariableParseExpression(field, variableLiteralArg, null));
                     }
                 } else if (arg instanceof StringLiteral) {
                     sb.append(((StringLiteral) arg).getValue());
                 }
             }
             sb.append(")");
-            return sb.toString();
-        } else if (isVariableLiteralImplicitField(vl)) { // If we are accessing implicit fields, we need to rely on a local variable instead.
-            return vl.getName();
-        } else if (vl.getName().equals(vl.getName().toUpperCase())) { // All uppercase names are not fields, but utility methods.
-            StringBuilder sb = new StringBuilder(vl.getName());
-            if (vl.getArgs() != null) {
+            return tracer + sb.toString();
+        } else if (isVariableLiteralImplicitField(variableLiteral)) { // If we are accessing implicit fields, we need to rely on a local variable instead.
+            tracer = tracer.dive("implicit");
+            return tracer + variableLiteral.getName();
+        } else if (variableLiteral.getName().equals(variableLiteral.getName().toUpperCase())) { // All uppercase names are not fields, but utility methods.
+            tracer = tracer.dive("UPPERCASE");
+            StringBuilder sb = new StringBuilder(variableLiteral.getName());
+            if (variableLiteral.getArgs() != null) {
                 sb.append("(");
                 boolean firstArg = true;
-                for (Term arg : vl.getArgs()) {
+                for (Term arg : variableLiteral.getArgs()) {
                     if (!firstArg) {
                         sb.append(", ");
                     }
@@ -698,26 +728,27 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                 }
                 sb.append(")");
             }
-            if (vl.getIndex() != VariableLiteral.NO_INDEX) {
-                sb.append("[").append(vl.getIndex()).append("]");
+            if (variableLiteral.getIndex() != VariableLiteral.NO_INDEX) {
+                sb.append("[").append(variableLiteral.getIndex()).append("]");
             }
-            return sb + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+            return tracer + sb.toString() + ((variableLiteral.getChild() != null) ? "." + toVariableExpressionRest(variableLiteral.getChild()) : "");
         }
-        return vl.getName() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+        return tracer + variableLiteral.getName() + ((variableLiteral.getChild() != null) ? "." + toVariableExpressionRest(variableLiteral.getChild()) : "");
     }
 
-    private String toVariableSerializationExpression(TypedField field, Term term, Argument[] serialzerArguments) {
-        VariableLiteral vl = (VariableLiteral) term;
-        if ("STATIC_CALL".equals(vl.getName())) {
+    private String toVariableSerializationExpression(TypedField field, VariableLiteral variableLiteral, Argument[] serialzerArguments) {
+        Tracer tracer = Tracer.start("variable serialization expression");
+        if ("STATIC_CALL".equals(variableLiteral.getName())) {
+            tracer = tracer.dive("STATIC_CALL");
             StringBuilder sb = new StringBuilder();
-            if (!(vl.getArgs().get(0) instanceof StringLiteral)) {
+            if (!(variableLiteral.getArgs().get(0) instanceof StringLiteral)) {
                 throw new RuntimeException("Expecting the first argument of a 'STATIC_CALL' to be a StringLiteral");
             }
-            String methodName = ((StringLiteral) vl.getArgs().get(0)).getValue();
+            String methodName = ((StringLiteral) variableLiteral.getArgs().get(0)).getValue();
             methodName = methodName.substring(1, methodName.length() - 1);
             sb.append(methodName).append("(");
-            for (int i = 1; i < vl.getArgs().size(); i++) {
-                Term arg = vl.getArgs().get(i);
+            for (int i = 1; i < variableLiteral.getArgs().size(); i++) {
+                Term arg = variableLiteral.getArgs().get(i);
                 if (i > 1) {
                     sb.append(", ");
                 }
@@ -735,7 +766,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                         }
                     }
                     if (isSerializerArg) {
-                        sb.append(va.getName() + ((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : ""));
+                        sb.append(va.getName()).append((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : "");
                     } else if (isTypeArg) {
                         String part = va.getChild().getName();
                         switch (part) {
@@ -760,15 +791,16 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                 }
             }
             sb.append(")");
-            return sb.toString();
+            return tracer + sb.toString();
         }
         // All uppercase names are not fields, but utility methods.
-        else if (vl.getName().equals(vl.getName().toUpperCase())) {
-            StringBuilder sb = new StringBuilder(vl.getName());
-            if (vl.getArgs() != null) {
+        else if (variableLiteral.getName().equals(variableLiteral.getName().toUpperCase())) {
+            tracer = tracer.dive("UPPER_CASE");
+            StringBuilder sb = new StringBuilder(variableLiteral.getName());
+            if (variableLiteral.getArgs() != null) {
                 sb.append("(");
                 boolean firstArg = true;
-                for (Term arg : vl.getArgs()) {
+                for (Term arg : variableLiteral.getArgs()) {
                     if (!firstArg) {
                         sb.append(", ");
                     }
@@ -786,7 +818,7 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                             }
                         }
                         if (isSerializerArg) {
-                            sb.append(va.getName() + ((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : ""));
+                            sb.append(va.getName()).append((va.getChild() != null) ? "." + toVariableExpressionRest(va.getChild()) : "");
                         } else if (isTypeArg) {
                             String part = va.getChild().getName();
                             switch (part) {
@@ -813,60 +845,63 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
                 }
                 sb.append(")");
             }
-            return sb.toString();
-        }
-        // If we are accessing implicit fields, we need to rely on a local variable instead.
-        else if (isVariableLiteralImplicitField(vl)) {
-            return toSerializationExpression(getReferencedImplicitField(vl), getReferencedImplicitField(vl).getSerializeExpression(), serialzerArguments);
+            return tracer + sb.toString();
+        } else if (isVariableLiteralImplicitField(variableLiteral)) { // If we are accessing implicit fields, we need to rely on a local variable instead.
+            tracer = tracer.dive("implicit field");
+            return tracer + toSerializationExpression(getReferencedImplicitField(variableLiteral), getReferencedImplicitField(variableLiteral).getSerializeExpression(), serialzerArguments);
         }
         // The synthetic checksumRawData is a local field and should not be accessed as bean property.
-        boolean isSerializerArg = "checksumRawData".equals(vl.getName()) || "_value".equals(vl.getName()) || "element".equals(vl.getName()) || "size".equals(vl.getName());
-        boolean isTypeArg = "_type".equals(vl.getName());
+        boolean isSerializerArg = "checksumRawData".equals(variableLiteral.getName()) || "_value".equals(variableLiteral.getName()) || "element".equals(variableLiteral.getName()) || "size".equals(variableLiteral.getName());
+        boolean isTypeArg = "_type".equals(variableLiteral.getName());
         if (!isSerializerArg && !isTypeArg && serialzerArguments != null) {
             for (Argument serializerArgument : serialzerArguments) {
-                if (serializerArgument.getName().equals(vl.getName())) {
+                if (serializerArgument.getName().equals(variableLiteral.getName())) {
                     isSerializerArg = true;
                     break;
                 }
             }
         }
         if (isSerializerArg) {
-            return vl.getName() + ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : "");
+            tracer = tracer.dive("serializer arg");
+            return tracer + variableLiteral.getName() + ((variableLiteral.getChild() != null) ? "." + toVariableExpressionRest(variableLiteral.getChild()) : "");
         } else if (isTypeArg) {
-            String part = vl.getChild().getName();
+            tracer = tracer.dive("type arg");
+            String part = variableLiteral.getChild().getName();
             switch (part) {
                 case "name":
-                    return "\"" + field.getTypeName() + "\"";
+                    return tracer + "\"" + field.getTypeName() + "\"";
                 case "length":
-                    return "\"" + ((SimpleTypeReference) field).getSizeInBits() + "\"";
+                    return tracer + "\"" + ((SimpleTypeReference) field).getSizeInBits() + "\"";
                 case "encoding":
                     String encoding = ((StringTypeReference) field.getType()).getEncoding();
                     // Cut off the single quotes.
                     encoding = encoding.substring(1, encoding.length() - 1);
-                    return "\"" + encoding + "\"";
+                    return tracer + "\"" + encoding + "\"";
                 default:
-                    return "";
+                    return tracer + "";
             }
         } else {
-            return "_value." + toVariableExpressionRest(vl);
+            return tracer + "_value." + toVariableExpressionRest(variableLiteral);
         }
     }
 
-    private String toVariableExpressionRest(VariableLiteral vl) {
+    private String toVariableExpressionRest(VariableLiteral variableLiteral) {
+        Tracer tracer = Tracer.start("variable expression rest");
         // length is kind of a keyword in mspec, so we shouldn't be naming variables length. if we ask for the length of a object we can just return length().
         // This way we can get the length of a string when serializing
-        if (vl.getName().equals("length")) {
-            return vl.getName() + "()" + ((vl.isIndexed() ? "[" + vl.getIndex() + "]" : "") +
-                ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : ""));
-        } else {
-            return "get" + WordUtils.capitalize(vl.getName()) + "()" + ((vl.isIndexed() ? "[" + vl.getIndex() + "]" : "") +
-                ((vl.getChild() != null) ? "." + toVariableExpressionRest(vl.getChild()) : ""));
+        String variableLiteralName = variableLiteral.getName();
+        if (variableLiteralName.equals("length")) {
+            tracer = tracer.dive("length");
+            return tracer + variableLiteralName + "()" + ((variableLiteral.isIndexed() ? "[" + variableLiteral.getIndex() + "]" : "") +
+                ((variableLiteral.getChild() != null) ? "." + toVariableExpressionRest(variableLiteral.getChild()) : ""));
         }
+        return tracer + "get" + WordUtils.capitalize(variableLiteralName) + "()" + ((variableLiteral.isIndexed() ? "[" + variableLiteral.getIndex() + "]" : "") +
+            ((variableLiteral.getChild() != null) ? "." + toVariableExpressionRest(variableLiteral.getChild()) : ""));
     }
 
     public String getSizeInBits(ComplexTypeDefinition complexTypeDefinition, Argument[] parserArguments) {
         int sizeInBits = 0;
-        StringBuilder sb = new StringBuilder("");
+        StringBuilder sb = new StringBuilder();
         for (Field field : complexTypeDefinition.getFields()) {
             if (field instanceof ArrayField) {
                 ArrayField arrayField = (ArrayField) field;

[plc4x] 04/04: fix(java/codegen): virtual field handling

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit ef35531d5a872f29dccddb3a11a135b166958185
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 24 20:37:13 2021 +0200

    fix(java/codegen): virtual field handling
---
 .../org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java     | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
index e12fd93..b7d8d3d 100644
--- a/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
+++ b/code-generation/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java
@@ -849,6 +849,9 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe
         } else if (isVariableLiteralImplicitField(variableLiteral)) { // If we are accessing implicit fields, we need to rely on a local variable instead.
             tracer = tracer.dive("implicit field");
             return tracer + toSerializationExpression(getReferencedImplicitField(variableLiteral), getReferencedImplicitField(variableLiteral).getSerializeExpression(), serialzerArguments);
+        } else if (isVariableLiteralVirtualField(variableLiteral)) {
+            tracer = tracer.dive("virtual field");
+            return tracer + "_value." + toVariableExpressionRest(variableLiteral);
         }
         // The synthetic checksumRawData is a local field and should not be accessed as bean property.
         boolean isSerializerArg = "checksumRawData".equals(variableLiteral.getName()) || "_value".equals(variableLiteral.getName()) || "element".equals(variableLiteral.getName()) || "size".equals(variableLiteral.getName());

[plc4x] 01/04: fix: fix stackoverflow on type referencing each other

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 9470bbb3d6b06da665e3db7fe0e25c8f04e516db
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 24 20:30:54 2021 +0200

    fix: fix stackoverflow on type referencing each other
---
 .../BaseFreemarkerLanguageTemplateHelper.java      | 71 +++++++++++++---------
 1 file changed, 42 insertions(+), 29 deletions(-)

diff --git a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
index 286da39..e494acd 100644
--- a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
+++ b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/BaseFreemarkerLanguageTemplateHelper.java
@@ -23,12 +23,8 @@ import net.objecthunter.exp4j.ExpressionBuilder;
 import org.apache.plc4x.plugins.codegenerator.types.definitions.*;
 import org.apache.plc4x.plugins.codegenerator.types.enums.EnumValue;
 import org.apache.plc4x.plugins.codegenerator.types.fields.*;
-import org.apache.plc4x.plugins.codegenerator.types.references.ComplexTypeReference;
-import org.apache.plc4x.plugins.codegenerator.types.references.SimpleTypeReference;
-import org.apache.plc4x.plugins.codegenerator.types.references.StringTypeReference;
-import org.apache.plc4x.plugins.codegenerator.types.references.TypeReference;
+import org.apache.plc4x.plugins.codegenerator.types.references.*;
 import org.apache.plc4x.plugins.codegenerator.types.terms.*;
-import org.w3c.dom.Node;
 
 import java.util.*;
 import java.util.stream.Collectors;
@@ -199,13 +195,18 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
      * @return collection of complex type references used in the type.
      */
     public Collection<String> getComplexTypeReferences(TypeDefinition baseType) {
-        Set<String> complexTypeReferences = new HashSet<>();
+        return getComplexTypeReferences(baseType, new HashSet<>());
+    }
+
+    public Collection<String> getComplexTypeReferences(TypeDefinition baseType, Set<String> complexTypeReferences) {
+        // We add ourselves to avoid a stackoverflow
+        complexTypeReferences.add(baseType.getName());
         // If this is a subtype of a discriminated type, we have to add a reference to the parent type.
         if (baseType instanceof DiscriminatedComplexTypeDefinition) {
             DiscriminatedComplexTypeDefinition discriminatedComplexTypeDefinition = (DiscriminatedComplexTypeDefinition) baseType;
             if (!discriminatedComplexTypeDefinition.isAbstract()) {
-                complexTypeReferences.add(((ComplexTypeReference)
-                    discriminatedComplexTypeDefinition.getParentType().getTypeReference()).getName());
+                String typeReferenceName = ((ComplexTypeReference) discriminatedComplexTypeDefinition.getParentType().getTypeReference()).getName();
+                complexTypeReferences.add(typeReferenceName);
             }
         }
         // If it's a complex type definition, add all the types referenced by any property fields
@@ -222,13 +223,14 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
                 } else if (field instanceof SwitchField) {
                     SwitchField switchField = (SwitchField) field;
                     for (DiscriminatedComplexTypeDefinition switchCase : switchField.getCases()) {
-                        complexTypeReferences.addAll(getComplexTypeReferences(switchCase));
+                        if (complexTypeReferences.contains(switchCase.getName())) {
+                            continue;
+                        }
+                        complexTypeReferences.addAll(getComplexTypeReferences(switchCase, complexTypeReferences));
                     }
                 }
             }
-        }
-        // In case this is a enum type, we have to check all the constant types.
-        else if (baseType instanceof EnumTypeDefinition) {
+        } else if (baseType instanceof EnumTypeDefinition) {// In case this is an enum type, we have to check all the constant types.
             for (String constantName : ((EnumTypeDefinition) baseType).getConstantNames()) {
                 final TypeReference constantType = ((EnumTypeDefinition) thisType).getConstantType(constantName);
                 if (constantType instanceof ComplexTypeReference) {
@@ -246,6 +248,9 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
                 }
             }
         }
+
+        // We remove ourselves to avoid a stackoverflow
+        complexTypeReferences.remove(baseType.getName());
         return complexTypeReferences;
     }
 
@@ -323,13 +328,13 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
         if (!(typeReference instanceof ComplexTypeReference)) {
             throw new FreemarkerException("type reference for enum types must be of type complex type");
         }
-        ComplexTypeReference complexTypeReference = (ComplexTypeReference) typeReference;
-        final TypeDefinition typeDefinition = types.get(complexTypeReference.getName());
+        String typeName = ((ComplexTypeReference) typeReference).getName();
+        final TypeDefinition typeDefinition = types.get(typeName);
         if (typeDefinition == null) {
-            throw new FreemarkerException("Couldn't find given enum type definition with name " + complexTypeReference.getName());
+            throw new FreemarkerException("Couldn't find given enum type definition with name " + typeName);
         }
         if (!(typeDefinition instanceof EnumTypeDefinition)) {
-            throw new FreemarkerException("Referenced type with name " + complexTypeReference.getName() + " is not an enum type");
+            throw new FreemarkerException("Referenced type with name " + typeName + " is not an enum type");
         }
         EnumTypeDefinition enumTypeDefinition = (EnumTypeDefinition) typeDefinition;
         // Enum types always have simple type references.
@@ -368,7 +373,11 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
         if (!(getThisTypeDefinition() instanceof ComplexTypeDefinition)) {
             return null;
         }
-        return ((ComplexTypeDefinition) getThisTypeDefinition()).getAllPropertyFields()
+        return getAllPropertyFields((ComplexTypeDefinition) getThisTypeDefinition(), fieldName);
+    }
+
+    public PropertyField getAllPropertyFields(ComplexTypeDefinition complexTypeDefinition, String fieldName) {
+        return complexTypeDefinition.getAllPropertyFields()
             .stream()
             .filter(propertyField -> propertyField.getName().equals(fieldName))
             .findFirst()
@@ -379,7 +388,11 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
         if (!(getThisTypeDefinition() instanceof ComplexTypeDefinition)) {
             return null;
         }
-        return ((ComplexTypeDefinition) getThisTypeDefinition()).getPropertyFields()
+        return getPropertyField((ComplexTypeDefinition) getThisTypeDefinition(), fieldName);
+    }
+
+    public PropertyField getPropertyField(ComplexTypeDefinition complexTypeDefinition, String fieldName) {
+        return complexTypeDefinition.getPropertyFields()
             .stream()
             .filter(propertyField -> propertyField.getName().equals(fieldName))
             .findFirst()
@@ -696,8 +709,8 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
      * @return true if a field with the given name already exists in the same type.
      */
     public boolean isNonDiscriminatorField(String discriminatorName) {
-        return ((ComplexTypeDefinition) thisType).getAllPropertyFields().stream().anyMatch(
-            field -> !(field instanceof DiscriminatorField) && field.getName().equals(discriminatorName));
+        return ((ComplexTypeDefinition) thisType).getAllPropertyFields().stream()
+            .anyMatch(field -> !(field instanceof DiscriminatorField) && field.getName().equals(discriminatorName));
     }
 
     /**
@@ -711,8 +724,8 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
     public boolean isDiscriminatorField(String discriminatorName) {
         List<String> names = getDiscriminatorNames();
         if (names != null) {
-            return getDiscriminatorNames().stream().anyMatch(
-                field -> field.equals(discriminatorName));
+            return getDiscriminatorNames().stream()
+                .anyMatch(field -> field.equals(discriminatorName));
         }
         return false;
     }
@@ -844,7 +857,7 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
         }
         TypeDefinition complexTypeDefinition = getTypeDefinitions().get(complexTypeReference.getName());
         if (complexTypeDefinition.getParserArguments().length <= index) {
-            throw new FreemarkerException("Type " + complexTypeReference.getName() + " specifies too few parser arguments");
+            throw new FreemarkerException("Type " + complexTypeReference.getName() + " specifies too few parser arguments. Available:" + complexTypeDefinition.getParserArguments().length + " index:" + index);
         }
         return complexTypeDefinition.getParserArguments()[index].getType();
     }
@@ -1001,16 +1014,16 @@ public abstract class BaseFreemarkerLanguageTemplateHelper implements Freemarker
      * Confirms if a variable is an virtual variable. These need to be handled differently when serializing and parsing.
      *
      * @param vl The variable to search for.
-     * @return boolean returns true if the variable's name is an vritual field
+     * @return boolean returns true if the variable's name is an virtual field
      */
     protected boolean isVariableLiteralVirtualField(VariableLiteral vl) {
-        List<Field> fields = null;
+        List<Field> fields = new ArrayList<>();
         if (thisType instanceof ComplexTypeDefinition) {
             ComplexTypeDefinition complexType = (ComplexTypeDefinition) getThisTypeDefinition();
-            fields = complexType.getFields();
-        }
-        if (fields == null) {
-            return false;
+            fields.addAll(complexType.getFields());
+            if (complexType.getParentType() != null) {
+                fields.addAll(((ComplexTypeDefinition) complexType.getParentType()).getFields());
+            }
         }
         for (Field field : fields) {
             if (field.getTypeName().equals(VIRTUAL)) {

[plc4x] 02/04: feat: inject tracer into freemarker templates

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 212818e71a428eced6de2fd35aac71708fa9d217
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Sep 24 20:31:19 2021 +0200

    feat: inject tracer into freemarker templates
---
 .../codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java     | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
index 237798a..a89aa92 100644
--- a/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
+++ b/code-generation/language-base-freemarker/src/main/java/org/apache/plc4x/plugins/codegenerator/protocol/freemarker/FreemarkerLanguageOutput.java
@@ -71,6 +71,7 @@ public abstract class FreemarkerLanguageOutput implements LanguageOutput {
             typeContext.put("protocolName", protocolName);
             typeContext.put("outputFlavor", outputFlavor);
             typeContext.put("helper", getHelper(null, protocolName, outputFlavor, types, options));
+            typeContext.put("tracer", Tracer.start("global"));
             typeContext.putAll(options);
 
             for (Template template : specTemplates) {
@@ -92,6 +93,7 @@ public abstract class FreemarkerLanguageOutput implements LanguageOutput {
             typeContext.put("typeName", typeEntry.getKey());
             typeContext.put("type", typeEntry.getValue());
             typeContext.put("helper", getHelper(typeEntry.getValue(), protocolName, outputFlavor, types, options));
+            typeContext.put("tracer", Tracer.start("types"));
 
             // Depending on the type, get the corresponding list of templates.
             List<Template> templateList;