From b306fd2ed24eccbf11555cd070c31a0679d8edb7 Mon Sep 17 00:00:00 2001 From: canonical Date: Fri, 16 Aug 2024 23:33:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0JavaToXLangTransformer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nop-dependencies/pom.xml | 2 +- .../model/ast/io/nop/xlang/ast/XLangAST.xjava | 9 + .../io/nop/xlang/ast/CompilationUnit.java | 8 + .../java/io/nop/xlang/ast/XLangASTKind.java | 210 ++++++------- .../io/nop/xlang/ast/XLangASTOptimizer.java | 21 ++ .../io/nop/xlang/ast/XLangASTProcessor.java | 7 + .../io/nop/xlang/ast/XLangASTVisitor.java | 9 + .../nop/xlang/ast/_gen/_CompilationUnit.java | 197 ++++++++++++ .../xlang/ast/_gen/_ImportAsDeclaration.java | 20 ++ .../ast/print/XLangExpressionPrinter.java | 30 +- .../xlang/ast/print/XLangSourcePrinter.java | 130 ++++++++ .../xlang/janino/JaninoASTNodeBuilder.java | 135 --------- .../xlang/janino/JavaToXLangTransformer.java | 285 ++++++++++++++++++ .../nop/xlang/xmeta/xjava/JaninoHelper.java | 16 + .../nop/xlang/janino/TestJavaTransformer.java | 47 +++ 15 files changed, 882 insertions(+), 244 deletions(-) create mode 100644 nop-xlang/src/main/java/io/nop/xlang/ast/CompilationUnit.java create mode 100644 nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_CompilationUnit.java create mode 100644 nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangSourcePrinter.java delete mode 100644 nop-xlang/src/main/java/io/nop/xlang/janino/JaninoASTNodeBuilder.java create mode 100644 nop-xlang/src/main/java/io/nop/xlang/janino/JavaToXLangTransformer.java create mode 100644 nop-xlang/src/test/java/io/nop/xlang/janino/TestJavaTransformer.java diff --git a/nop-dependencies/pom.xml b/nop-dependencies/pom.xml index c649dc608..db777765b 100644 --- a/nop-dependencies/pom.xml +++ b/nop-dependencies/pom.xml @@ -35,7 +35,7 @@ - 3.1.9 + 3.1.12 2.8.0 diff --git a/nop-xlang/model/ast/io/nop/xlang/ast/XLangAST.xjava b/nop-xlang/model/ast/io/nop/xlang/ast/XLangAST.xjava index 226548eaa..7440abc0d 100644 --- a/nop-xlang/model/ast/io/nop/xlang/ast/XLangAST.xjava +++ b/nop-xlang/model/ast/io/nop/xlang/ast/XLangAST.xjava @@ -52,6 +52,13 @@ public class XLangAST { } + class CompilationUnit{ + @PropMeta(mandatory=true) + String packageName; + + List statements; + } + class Program extends Expression { String sourceType; //: "script" | "module"; @@ -574,6 +581,8 @@ public class XLangAST { XLangASTNode source; Identifier local; + + boolean staticImport; } //import {foo as bar} from "mod" diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/CompilationUnit.java b/nop-xlang/src/main/java/io/nop/xlang/ast/CompilationUnit.java new file mode 100644 index 000000000..98132f5b8 --- /dev/null +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/CompilationUnit.java @@ -0,0 +1,8 @@ + +package io.nop.xlang.ast; + +import io.nop.xlang.ast._gen._CompilationUnit; + +public class CompilationUnit extends _CompilationUnit{ + +} diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTKind.java b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTKind.java index 4e4233517..04689641a 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTKind.java +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTKind.java @@ -3,212 +3,214 @@ public enum XLangASTKind{ - Program, // ordinal: 0 + CompilationUnit, // ordinal: 0 - Identifier, // ordinal: 1 + Program, // ordinal: 1 - Literal, // ordinal: 2 + Identifier, // ordinal: 2 - TemplateStringLiteral, // ordinal: 3 + Literal, // ordinal: 3 - RegExpLiteral, // ordinal: 4 + TemplateStringLiteral, // ordinal: 4 - BlockStatement, // ordinal: 5 + RegExpLiteral, // ordinal: 5 - EmptyStatement, // ordinal: 6 + BlockStatement, // ordinal: 6 - ReturnStatement, // ordinal: 7 + EmptyStatement, // ordinal: 7 - BreakStatement, // ordinal: 8 + ReturnStatement, // ordinal: 8 - ContinueStatement, // ordinal: 9 + BreakStatement, // ordinal: 9 - IfStatement, // ordinal: 10 + ContinueStatement, // ordinal: 10 - SwitchStatement, // ordinal: 11 + IfStatement, // ordinal: 11 - SwitchCase, // ordinal: 12 + SwitchStatement, // ordinal: 12 - ThrowStatement, // ordinal: 13 + SwitchCase, // ordinal: 13 - TryStatement, // ordinal: 14 + ThrowStatement, // ordinal: 14 - CatchClause, // ordinal: 15 + TryStatement, // ordinal: 15 - WhileStatement, // ordinal: 16 + CatchClause, // ordinal: 16 - DoWhileStatement, // ordinal: 17 + WhileStatement, // ordinal: 17 - VariableDeclarator, // ordinal: 18 + DoWhileStatement, // ordinal: 18 - VariableDeclaration, // ordinal: 19 + VariableDeclarator, // ordinal: 19 - ForStatement, // ordinal: 20 + VariableDeclaration, // ordinal: 20 - ForOfStatement, // ordinal: 21 + ForStatement, // ordinal: 21 - ForRangeStatement, // ordinal: 22 + ForOfStatement, // ordinal: 22 - ForInStatement, // ordinal: 23 + ForRangeStatement, // ordinal: 23 - DeleteStatement, // ordinal: 24 + ForInStatement, // ordinal: 24 - ChainExpression, // ordinal: 25 + DeleteStatement, // ordinal: 25 - ThisExpression, // ordinal: 26 + ChainExpression, // ordinal: 26 - SuperExpression, // ordinal: 27 + ThisExpression, // ordinal: 27 - TemplateStringExpression, // ordinal: 28 + SuperExpression, // ordinal: 28 - ArrayExpression, // ordinal: 29 + TemplateStringExpression, // ordinal: 29 - ObjectExpression, // ordinal: 30 + ArrayExpression, // ordinal: 30 - PropertyAssignment, // ordinal: 31 + ObjectExpression, // ordinal: 31 - ParameterDeclaration, // ordinal: 32 + PropertyAssignment, // ordinal: 32 - FunctionDeclaration, // ordinal: 33 + ParameterDeclaration, // ordinal: 33 - ArrowFunctionExpression, // ordinal: 34 + FunctionDeclaration, // ordinal: 34 - UnaryExpression, // ordinal: 35 + ArrowFunctionExpression, // ordinal: 35 - UpdateExpression, // ordinal: 36 + UnaryExpression, // ordinal: 36 - BinaryExpression, // ordinal: 37 + UpdateExpression, // ordinal: 37 - InExpression, // ordinal: 38 + BinaryExpression, // ordinal: 38 - ExpressionStatement, // ordinal: 39 + InExpression, // ordinal: 39 - AssignmentExpression, // ordinal: 40 + ExpressionStatement, // ordinal: 40 - LogicalExpression, // ordinal: 41 + AssignmentExpression, // ordinal: 41 - MemberExpression, // ordinal: 42 + LogicalExpression, // ordinal: 42 - EvalExpression, // ordinal: 43 + MemberExpression, // ordinal: 43 - CallExpression, // ordinal: 44 + EvalExpression, // ordinal: 44 - NewExpression, // ordinal: 45 + CallExpression, // ordinal: 45 - SpreadElement, // ordinal: 46 + NewExpression, // ordinal: 46 - SequenceExpression, // ordinal: 47 + SpreadElement, // ordinal: 47 - ConcatExpression, // ordinal: 48 + SequenceExpression, // ordinal: 48 - TemplateExpression, // ordinal: 49 + ConcatExpression, // ordinal: 49 - BraceExpression, // ordinal: 50 + TemplateExpression, // ordinal: 50 - ObjectBinding, // ordinal: 51 + BraceExpression, // ordinal: 51 - PropertyBinding, // ordinal: 52 + ObjectBinding, // ordinal: 52 - RestBinding, // ordinal: 53 + PropertyBinding, // ordinal: 53 - ArrayBinding, // ordinal: 54 + RestBinding, // ordinal: 54 - ArrayElementBinding, // ordinal: 55 + ArrayBinding, // ordinal: 55 - ExportDeclaration, // ordinal: 56 + ArrayElementBinding, // ordinal: 56 - ExportNamedDeclaration, // ordinal: 57 + ExportDeclaration, // ordinal: 57 - ExportAllDeclaration, // ordinal: 58 + ExportNamedDeclaration, // ordinal: 58 - ExportSpecifier, // ordinal: 59 + ExportAllDeclaration, // ordinal: 59 - ImportDeclaration, // ordinal: 60 + ExportSpecifier, // ordinal: 60 - ImportAsDeclaration, // ordinal: 61 + ImportDeclaration, // ordinal: 61 - ImportSpecifier, // ordinal: 62 + ImportAsDeclaration, // ordinal: 62 - ImportDefaultSpecifier, // ordinal: 63 + ImportSpecifier, // ordinal: 63 - ImportNamespaceSpecifier, // ordinal: 64 + ImportDefaultSpecifier, // ordinal: 64 - AwaitExpression, // ordinal: 65 + ImportNamespaceSpecifier, // ordinal: 65 - Decorators, // ordinal: 66 + AwaitExpression, // ordinal: 66 - QualifiedName, // ordinal: 67 + Decorators, // ordinal: 67 - Decorator, // ordinal: 68 + QualifiedName, // ordinal: 68 - MetaObject, // ordinal: 69 + Decorator, // ordinal: 69 - MetaProperty, // ordinal: 70 + MetaObject, // ordinal: 70 - MetaArray, // ordinal: 71 + MetaProperty, // ordinal: 71 - UsingStatement, // ordinal: 72 + MetaArray, // ordinal: 72 - MacroExpression, // ordinal: 73 + UsingStatement, // ordinal: 73 - TextOutputExpression, // ordinal: 74 + MacroExpression, // ordinal: 74 - EscapeOutputExpression, // ordinal: 75 + TextOutputExpression, // ordinal: 75 - CollectOutputExpression, // ordinal: 76 + EscapeOutputExpression, // ordinal: 76 - CompareOpExpression, // ordinal: 77 + CollectOutputExpression, // ordinal: 77 - AssertOpExpression, // ordinal: 78 + CompareOpExpression, // ordinal: 78 - BetweenOpExpression, // ordinal: 79 + AssertOpExpression, // ordinal: 79 - GenNodeExpression, // ordinal: 80 + BetweenOpExpression, // ordinal: 80 - GenNodeAttrExpression, // ordinal: 81 + GenNodeExpression, // ordinal: 81 - OutputXmlAttrExpression, // ordinal: 82 + GenNodeAttrExpression, // ordinal: 82 - OutputXmlExtAttrsExpression, // ordinal: 83 + OutputXmlAttrExpression, // ordinal: 83 - TypeOfExpression, // ordinal: 84 + OutputXmlExtAttrsExpression, // ordinal: 84 - InstanceOfExpression, // ordinal: 85 + TypeOfExpression, // ordinal: 85 - CastExpression, // ordinal: 86 + InstanceOfExpression, // ordinal: 86 - ArrayTypeNode, // ordinal: 87 + CastExpression, // ordinal: 87 - ParameterizedTypeNode, // ordinal: 88 + ArrayTypeNode, // ordinal: 88 - TypeNameNode, // ordinal: 89 + ParameterizedTypeNode, // ordinal: 89 - UnionTypeDef, // ordinal: 90 + TypeNameNode, // ordinal: 90 - IntersectionTypeDef, // ordinal: 91 + UnionTypeDef, // ordinal: 91 - ObjectTypeDef, // ordinal: 92 + IntersectionTypeDef, // ordinal: 92 - PropertyTypeDef, // ordinal: 93 + ObjectTypeDef, // ordinal: 93 - TupleTypeDef, // ordinal: 94 + PropertyTypeDef, // ordinal: 94 - TypeParameterNode, // ordinal: 95 + TupleTypeDef, // ordinal: 95 - TypeAliasDeclaration, // ordinal: 96 + TypeParameterNode, // ordinal: 96 - FunctionTypeDef, // ordinal: 97 + TypeAliasDeclaration, // ordinal: 97 - FunctionArgTypeDef, // ordinal: 98 + FunctionTypeDef, // ordinal: 98 - EnumDeclaration, // ordinal: 99 + FunctionArgTypeDef, // ordinal: 99 - EnumMember, // ordinal: 100 + EnumDeclaration, // ordinal: 100 - ClassDefinition, // ordinal: 101 + EnumMember, // ordinal: 101 - FieldDeclaration, // ordinal: 102 + ClassDefinition, // ordinal: 102 - CustomExpression, // ordinal: 103 + FieldDeclaration, // ordinal: 103 + + CustomExpression, // ordinal: 104 } diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTOptimizer.java b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTOptimizer.java index 4de389244..cecec357e 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTOptimizer.java +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTOptimizer.java @@ -10,6 +10,9 @@ public class XLangASTOptimizer extends AbstractOptimizer{ public XLangASTNode optimize(XLangASTNode node,C context){ switch(node.getASTKind()){ + case CompilationUnit: + return optimizeCompilationUnit((CompilationUnit)node,context); + case Program: return optimizeProgram((Program)node,context); @@ -328,6 +331,24 @@ public XLangASTNode optimize(XLangASTNode node,C context){ } + public XLangASTNode optimizeCompilationUnit(CompilationUnit node, C context){ + CompilationUnit ret = node; + + + if(node.getStatements() != null){ + + java.util.List statementsOpt = optimizeList(node.getStatements(),true, context); + if(statementsOpt != node.getStatements()){ + incChangeCount(); + if(shouldClone(ret,node)) { clearParent(statementsOpt); ret = node.deepClone();} + ret.setStatements(statementsOpt); + } + + } + + return ret; + } + public XLangASTNode optimizeProgram(Program node, C context){ Program ret = node; diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTProcessor.java b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTProcessor.java index 989f1fece..718d17c33 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTProcessor.java +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTProcessor.java @@ -9,6 +9,9 @@ public T processAST(XLangASTNode node, C context){ return null; switch(node.getASTKind()){ + case CompilationUnit: + return processCompilationUnit((CompilationUnit)node,context); + case Program: return processProgram((Program)node,context); @@ -327,6 +330,10 @@ public T processAST(XLangASTNode node, C context){ } + public T processCompilationUnit(CompilationUnit node, C context){ + return defaultProcess(node, context); + } + public T processProgram(Program node, C context){ return defaultProcess(node, context); } diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTVisitor.java b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTVisitor.java index 6d8144eeb..d1e43778f 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTVisitor.java +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/XLangASTVisitor.java @@ -10,6 +10,10 @@ public class XLangASTVisitor extends AbstractVisitor{ public void visit(XLangASTNode node){ switch(node.getASTKind()){ + case CompilationUnit: + visitCompilationUnit((CompilationUnit)node); + return; + case Program: visitProgram((Program)node); return; @@ -432,6 +436,11 @@ public void visit(XLangASTNode node){ } + public void visitCompilationUnit(CompilationUnit node){ + + this.visitChildren(node.getStatements()); + } + public void visitProgram(Program node){ this.visitChildren(node.getBody()); diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_CompilationUnit.java b/nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_CompilationUnit.java new file mode 100644 index 000000000..7ea32dcb5 --- /dev/null +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_CompilationUnit.java @@ -0,0 +1,197 @@ +//__XGEN_FORCE_OVERRIDE__ +package io.nop.xlang.ast._gen; + +import io.nop.xlang.ast.CompilationUnit; +import io.nop.xlang.ast.XLangASTNode; //NOPMD NOSONAR - suppressed UnusedImports - Auto Gen Code + +import io.nop.xlang.ast.XLangASTKind; +import io.nop.core.lang.json.IJsonHandler; +import io.nop.api.core.util.ProcessResult; +import java.util.function.Function; +import java.util.function.Consumer; + + +// tell cpd to start ignoring code - CPD-OFF +@SuppressWarnings({"PMD.UselessOverridingMethod","PMD.UnusedLocalVariable","java:S116","java:S3008","java:S1602", + "PMD.UnnecessaryFullyQualifiedName","PMD.UnnecessaryImport","PMD.EmptyControlStatement"}) +public abstract class _CompilationUnit extends XLangASTNode { + + protected java.lang.String packageName; + + protected java.util.List statements; + + + public _CompilationUnit(){ + } + + + public java.lang.String getPackageName(){ + return packageName; + } + + public void setPackageName(java.lang.String value){ + checkAllowChange(); + + this.packageName = value; + } + + public java.util.List getStatements(){ + return statements; + } + + public void setStatements(java.util.List value){ + checkAllowChange(); + + if(value != null){ + value.forEach(node->node.setASTParent((XLangASTNode)this)); + } + + this.statements = value; + } + + public java.util.List makeStatements(){ + java.util.List list = getStatements(); + if(list == null){ + list = new java.util.ArrayList<>(); + setStatements(list); + } + return list; + } + + + public void validate(){ + super.validate(); + + checkMandatory("packageName",getPackageName()); + + } + + + public CompilationUnit newInstance(){ + return new CompilationUnit(); + } + + @Override + public CompilationUnit deepClone(){ + CompilationUnit ret = newInstance(); + ret.setLocation(getLocation()); + ret.setLeadingComment(getLeadingComment()); + ret.setTrailingComment(getTrailingComment()); + copyExtFieldsTo(ret); + + if(packageName != null){ + + ret.setPackageName(packageName); + + } + + if(statements != null){ + + java.util.List copy_statements = new java.util.ArrayList<>(statements.size()); + for(io.nop.xlang.ast.Statement item: statements){ + copy_statements.add(item.deepClone()); + } + ret.setStatements(copy_statements); + + } + + return ret; + } + + @Override + public void forEachChild(Consumer processor){ + + if(statements != null){ + for(io.nop.xlang.ast.Statement child: statements){ + processor.accept(child); + } + } + } + + @Override + public ProcessResult processChild(Function processor){ + + if(statements != null){ + for(io.nop.xlang.ast.Statement child: statements){ + if(processor.apply(child) == ProcessResult.STOP) + return ProcessResult.STOP; + } + } + return ProcessResult.CONTINUE; + } + + @Override + public boolean replaceChild(XLangASTNode oldChild, XLangASTNode newChild){ + + if(this.statements != null){ + int index = this.statements.indexOf(oldChild); + if(index >= 0){ + java.util.List list = this.replaceInList(this.statements,index,newChild); + this.setStatements(list); + return true; + } + } + return false; + } + + @Override + public boolean removeChild(XLangASTNode child){ + + if(this.statements != null){ + int index = this.statements.indexOf(child); + if(index >= 0){ + java.util.List list = this.removeInList(this.statements,index); + this.setStatements(list); + return true; + } + } + return false; + } + + @Override + public boolean isEquivalentTo(XLangASTNode node){ + if(this.getASTKind() != node.getASTKind()) + return false; + CompilationUnit other = (CompilationUnit)node; + + if(!isValueEquivalent(this.packageName,other.getPackageName())){ + return false; + } + + if(isListEquivalent(this.statements,other.getStatements())){ + return false; + } + return true; + } + + @Override + public XLangASTKind getASTKind(){ + return XLangASTKind.CompilationUnit; + } + + protected void serializeFields(IJsonHandler json) { + + if(packageName != null){ + + json.put("packageName", packageName); + + } + + if(statements != null){ + + if(!statements.isEmpty()) + json.put("statements", statements); + + } + + } + + @Override + public void freeze(boolean cascade){ + super.freeze(cascade); + + statements = io.nop.api.core.util.FreezeHelper.freezeList(statements,cascade); + } + +} + // resume CPD analysis - CPD-ON diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_ImportAsDeclaration.java b/nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_ImportAsDeclaration.java index bb04e90bd..b16796763 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_ImportAsDeclaration.java +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/_gen/_ImportAsDeclaration.java @@ -20,6 +20,8 @@ public abstract class _ImportAsDeclaration extends io.nop.xlang.ast.ModuleDeclar protected io.nop.xlang.ast.XLangASTNode source; + protected boolean staticImport; + public _ImportAsDeclaration(){ } @@ -47,6 +49,16 @@ public void setSource(io.nop.xlang.ast.XLangASTNode value){ this.source = value; } + public boolean getStaticImport(){ + return staticImport; + } + + public void setStaticImport(boolean value){ + checkAllowChange(); + + this.staticImport = value; + } + public void validate(){ super.validate(); @@ -80,6 +92,8 @@ public ImportAsDeclaration deepClone(){ } + ret.setStaticImport(staticImport); + return ret; } @@ -152,6 +166,10 @@ public boolean isEquivalentTo(XLangASTNode node){ return false; } + if(!isValueEquivalent(this.staticImport,other.getStaticImport())){ + return false; + } + return true; } @@ -174,6 +192,8 @@ protected void serializeFields(IJsonHandler json) { } + json.put("staticImport", staticImport); + } @Override diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangExpressionPrinter.java b/nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangExpressionPrinter.java index a48ef8f24..2901603c9 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangExpressionPrinter.java +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangExpressionPrinter.java @@ -115,6 +115,8 @@ import io.nop.xlang.ast.XLangASTVisitor; import io.nop.xlang.ast.XLangOperator; +import java.util.List; + public class XLangExpressionPrinter extends XLangASTVisitor { protected final StringBuilder sb; @@ -134,6 +136,11 @@ public String toExprString(Expression expr) { return getResult(); } + public String toSource(XLangASTNode node) { + visit(node); + return getResult(); + } + public String getResult() { return sb.toString(); } @@ -161,12 +168,26 @@ protected XLangExpressionPrinter print(Object text) { return this; } - void incIndent() { + protected XLangExpressionPrinter printList(List node, String separator) { + if (node == null || node.isEmpty()) + return this; + + for (int i = 0, n = node.size(); i < n; i++) { + if (i != 0) + print(separator); + visit(node.get(i)); + } + return this; + } + + XLangExpressionPrinter incIndent() { indentLevel++; + return this; } - void decIndent() { + XLangExpressionPrinter decIndent() { indentLevel--; + return this; } void indent() { @@ -177,9 +198,10 @@ void indent() { } } - void println() { + XLangExpressionPrinter println() { print("\n"); indent(); + return this; } @Override @@ -627,7 +649,7 @@ public void visitDecorators(Decorators node) { @Override public void visitQualifiedName(QualifiedName node) { - super.visitQualifiedName(node); + print(node.getFullName()); } @Override diff --git a/nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangSourcePrinter.java b/nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangSourcePrinter.java new file mode 100644 index 000000000..bd0f2d900 --- /dev/null +++ b/nop-xlang/src/main/java/io/nop/xlang/ast/print/XLangSourcePrinter.java @@ -0,0 +1,130 @@ +package io.nop.xlang.ast.print; + +import io.nop.xlang.ast.ClassDefinition; +import io.nop.xlang.ast.CompilationUnit; +import io.nop.xlang.ast.CustomExpression; +import io.nop.xlang.ast.EnumDeclaration; +import io.nop.xlang.ast.EnumMember; +import io.nop.xlang.ast.FieldDeclaration; +import io.nop.xlang.ast.FunctionDeclaration; +import io.nop.xlang.ast.ImportAsDeclaration; +import io.nop.xlang.ast.ParameterDeclaration; +import io.nop.xlang.ast.ParameterizedTypeNode; +import io.nop.xlang.ast.XLangClassKind; + +public class XLangSourcePrinter extends XLangExpressionPrinter { + + public XLangSourcePrinter(){ + setPretty(true); + } + + @Override + public void visitCompilationUnit(CompilationUnit node) { + print("package "); + print(node.getPackageName()); + print(';'); + println(); + println(); + + visitChildren(node.getStatements()); + } + + @Override + public void visitImportAsDeclaration(ImportAsDeclaration node) { + print("import "); + if(node.getStaticImport()){ + print(" static "); + } + if (node.getSource() != null) + visit(node.getSource()); + if (node.getLocal() != null) { + print(" as "); + visit(node.getLocal()); + } + print(';'); + println(); + } + + @Override + public void visitClassDefinition(ClassDefinition node) { + println(); + if (node.getClassKind() == XLangClassKind.INTERFACE) { + print("interface "); + } else { + print("class "); + } + visit(node.getName()); + if (node.getExtendsType() != null) { + print(" extends "); + visit(node.getExtendsType()); + } + + if (node.getImplementTypes() != null) { + print(" implements "); + printList(node.getImplementTypes(), " , "); + } + print("{").incIndent().println(); + + if (node.getMethods() != null) { + for (FunctionDeclaration fn : node.getMethods()) { + visit(fn); + } + } + + decIndent().println().print("}").println(); + } + + @Override + public void visitParameterizedTypeNode(ParameterizedTypeNode node) { + print(node.getTypeName()); + if (node.getTypeArgs() != null && node.getTypeArgs().size() > 0) { + print('<'); + printList(node.getTypeArgs(), " , "); + print('>'); + } + } + + @Override + public void visitFunctionDeclaration(FunctionDeclaration node) { + println(); + visit(node.getName()); + print('('); + printList(node.getParams(), " , "); + print(')'); + if (node.getReturnType() != null) { + print(':'); + visit(node.getReturnType()); + } + print(' ').print('{').incIndent().println(); + decIndent().println().print('}').println(); + } + + @Override + public void visitParameterDeclaration(ParameterDeclaration node) { + visit(node.getName()); + if (node.getType() != null) { + print(':'); + visit(node.getType()); + } + } + + @Override + public void visitFieldDeclaration(FieldDeclaration node) { + super.visitFieldDeclaration(node); + } + + @Override + public void visitCustomExpression(CustomExpression node) { + super.visitCustomExpression(node); + } + + @Override + public void visitEnumMember(EnumMember node) { + super.visitEnumMember(node); + } + + @Override + public void visitEnumDeclaration(EnumDeclaration node) { + super.visitEnumDeclaration(node); + } +} diff --git a/nop-xlang/src/main/java/io/nop/xlang/janino/JaninoASTNodeBuilder.java b/nop-xlang/src/main/java/io/nop/xlang/janino/JaninoASTNodeBuilder.java deleted file mode 100644 index 039167132..000000000 --- a/nop-xlang/src/main/java/io/nop/xlang/janino/JaninoASTNodeBuilder.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (c) 2017-2024 Nop Platform. All rights reserved. - * Author: canonical_entropy@163.com - * Blog: https://www.zhihu.com/people/canonical-entropy - * Gitee: https://gitee.com/canonical-entropy/nop-entropy - * Github: https://github.com/entropy-cloud/nop-entropy - */ -package io.nop.xlang.janino; - -import io.nop.api.core.exceptions.NopException; -import io.nop.api.core.util.SourceLocation; -import io.nop.commons.util.StringHelper; -import io.nop.javac.JavaCompilerErrors; -import io.nop.xlang.ast.ClassDefinition; -import io.nop.xlang.ast.Declaration; -import io.nop.xlang.ast.EnumDeclaration; -import io.nop.xlang.ast.EnumMember; -import io.nop.xlang.ast.Identifier; -import io.nop.xlang.ast.ImportAsDeclaration; -import io.nop.xlang.ast.Program; -import io.nop.xlang.ast.QualifiedName; -import io.nop.xlang.ast.XLangASTBuilder; -import io.nop.xlang.ast.XLangASTKind; -import io.nop.xlang.ast.XLangASTNode; -import io.nop.xlang.ast.XLangClassKind; -import org.codehaus.commons.compiler.Location; -import org.codehaus.janino.Java; - -import java.util.ArrayList; -import java.util.List; - -public class JaninoASTNodeBuilder { - - public Program buildProgram(Java.CompilationUnit unit) { - Program program = new Program(); - program.setLocation(SourceLocation.fromPath(unit.fileName)); - - List body = new ArrayList<>(); - for (Java.AbstractCompilationUnit.ImportDeclaration decl : unit.importDeclarations) { - body.add(buildImportDeclaration(decl)); - } - - for (Java.PackageMemberTypeDeclaration type : unit.packageMemberTypeDeclarations) { - body.add(buildDeclaration(type)); - } - - program.setBody(body); - return program; - } - - protected String buildFilePath(String path) { - return path; - } - - private SourceLocation buildLocation(Java.Locatable node) { - Location loc = node.getLocation(); - String path = buildFilePath(loc.getFileName()); - return SourceLocation.fromLine(path, loc.getLineNumber(), loc.getColumnNumber()); - } - - public ImportAsDeclaration buildImportDeclaration(Java.AbstractCompilationUnit.ImportDeclaration decl) { - if (decl instanceof Java.AbstractCompilationUnit.SingleTypeImportDeclaration) { - return buildImportAsDeclaration((Java.AbstractCompilationUnit.SingleTypeImportDeclaration) decl); - } else { - throw newTransformError(decl, XLangASTKind.ImportAsDeclaration); - } - } - - private NopException newTransformError(Java.Locatable node, XLangASTKind kind) { - throw new NopException(JavaCompilerErrors.ERR_JAVAC_NOT_SUPPORT_TRANSFORM_TO_XLANG_AST_FAIL) - .param(JavaCompilerErrors.ARG_JAVA_TYPE, node.getClass().getSimpleName()) - .param(JavaCompilerErrors.ARG_AST_KIND, kind); - } - - public ImportAsDeclaration buildImportAsDeclaration(Java.AbstractCompilationUnit.SingleTypeImportDeclaration decl) { - SourceLocation loc = buildLocation(decl); - - QualifiedName source = QualifiedName.valueOf(loc, StringHelper.joinArray(decl.identifiers, ".")); - return XLangASTBuilder.importClass(loc, source, null); - } - - public Declaration buildDeclaration(Java.PackageMemberTypeDeclaration type) { - if (type instanceof Java.PackageMemberEnumDeclaration) { - return buildEnumDeclaration((Java.PackageMemberEnumDeclaration) type); - } else if (type instanceof Java.PackageMemberClassDeclaration) { - return buildClassDeclaration((Java.PackageMemberClassDeclaration) type); - } else if (type instanceof Java.PackageMemberInterfaceDeclaration) { - return buildInterfaceDeclaration((Java.PackageMemberInterfaceDeclaration) type); - } else { - throw newTransformError(type, XLangASTKind.ClassDefinition); - } - } - - public ClassDefinition buildClassDeclaration(Java.PackageMemberClassDeclaration type) { - SourceLocation loc = buildLocation(type); - - ClassDefinition def = new ClassDefinition(); - def.setLocation(loc); - def.setClassKind(XLangClassKind.CLASS); - return def; - } - - public ClassDefinition buildInterfaceDeclaration(Java.PackageMemberInterfaceDeclaration type) { - SourceLocation loc = buildLocation(type); - - ClassDefinition def = new ClassDefinition(); - def.setLocation(loc); - def.setClassKind(XLangClassKind.INTERFACE); - return def; - } - - public EnumDeclaration buildEnumDeclaration(Java.PackageMemberEnumDeclaration type) { - SourceLocation loc = buildLocation(type); - - EnumDeclaration decl = new EnumDeclaration(); - decl.setName(XLangASTBuilder.identifier(loc, type.getName())); - - List members = new ArrayList<>(); - for (Java.EnumConstant constant : type.getConstants()) { - EnumMember member = buildEnumMember(constant); - members.add(member); - } - decl.setMembers(members); - return decl; - } - - private EnumMember buildEnumMember(Java.EnumConstant constant) { - SourceLocation loc = buildLocation(constant); - - EnumMember member = new EnumMember(); - member.setLocation(loc); - member.setName(Identifier.valueOf(loc, constant.name)); - return member; - } -} \ No newline at end of file diff --git a/nop-xlang/src/main/java/io/nop/xlang/janino/JavaToXLangTransformer.java b/nop-xlang/src/main/java/io/nop/xlang/janino/JavaToXLangTransformer.java new file mode 100644 index 000000000..35049d66d --- /dev/null +++ b/nop-xlang/src/main/java/io/nop/xlang/janino/JavaToXLangTransformer.java @@ -0,0 +1,285 @@ +/** + * Copyright (c) 2017-2024 Nop Platform. All rights reserved. + * Author: canonical_entropy@163.com + * Blog: https://www.zhihu.com/people/canonical-entropy + * Gitee: https://gitee.com/canonical-entropy/nop-entropy + * Github: https://github.com/entropy-cloud/nop-entropy + */ +package io.nop.xlang.janino; + +import io.nop.api.core.exceptions.NopException; +import io.nop.api.core.util.SourceLocation; +import io.nop.commons.util.StringHelper; +import io.nop.javac.JavaCompilerErrors; +import io.nop.xlang.ast.ClassDefinition; +import io.nop.xlang.ast.CompilationUnit; +import io.nop.xlang.ast.Declaration; +import io.nop.xlang.ast.EnumDeclaration; +import io.nop.xlang.ast.EnumMember; +import io.nop.xlang.ast.FieldDeclaration; +import io.nop.xlang.ast.FunctionDeclaration; +import io.nop.xlang.ast.Identifier; +import io.nop.xlang.ast.ImportAsDeclaration; +import io.nop.xlang.ast.NamedTypeNode; +import io.nop.xlang.ast.ParameterDeclaration; +import io.nop.xlang.ast.ParameterizedTypeNode; +import io.nop.xlang.ast.Program; +import io.nop.xlang.ast.QualifiedName; +import io.nop.xlang.ast.Statement; +import io.nop.xlang.ast.TypeNameNode; +import io.nop.xlang.ast.XLangASTBuilder; +import io.nop.xlang.ast.XLangASTKind; +import io.nop.xlang.ast.XLangASTNode; +import io.nop.xlang.ast.XLangClassKind; +import org.codehaus.commons.compiler.Location; +import org.codehaus.janino.Java; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 将Java的抽象语法树转换为XLang的AST + */ +public class JavaToXLangTransformer { + private final boolean ignoreInvalidSyntax; + + public JavaToXLangTransformer(boolean ignoreInvalidSyntax) { + this.ignoreInvalidSyntax = ignoreInvalidSyntax; + } + + public JavaToXLangTransformer() { + this(false); + } + + public Program buildProgram(Java.CompilationUnit unit) { + Program program = new Program(); + program.setLocation(SourceLocation.fromPath(unit.fileName)); + + List body = new ArrayList<>(); + for (Java.AbstractCompilationUnit.ImportDeclaration decl : unit.importDeclarations) { + body.add(buildImportDeclaration(decl)); + } + + for (Java.PackageMemberTypeDeclaration type : unit.packageMemberTypeDeclarations) { + body.add(buildDeclaration(type)); + } + + program.setBody(body); + return program; + } + + public CompilationUnit buildCompilationUnit(Java.CompilationUnit unit) { + CompilationUnit ret = new CompilationUnit(); + ret.setLocation(SourceLocation.fromPath(unit.fileName)); + + if (unit.packageDeclaration != null) + ret.setPackageName(unit.packageDeclaration.packageName); + + List statements = new ArrayList<>(); + for (Java.AbstractCompilationUnit.ImportDeclaration decl : unit.importDeclarations) { + statements.add(buildImportDeclaration(decl)); + } + + for (Java.PackageMemberTypeDeclaration type : unit.packageMemberTypeDeclarations) { + statements.add(buildDeclaration(type)); + } + ret.setStatements(statements); + return ret; + } + + protected String buildFilePath(String path) { + return path; + } + + private SourceLocation buildLocation(Java.Locatable node) { + Location loc = node.getLocation(); + if (loc == null) + return null; + String path = buildFilePath(loc.getFileName()); + return SourceLocation.fromLine(path, loc.getLineNumber(), loc.getColumnNumber()); + } + + public ImportAsDeclaration buildImportDeclaration(Java.AbstractCompilationUnit.ImportDeclaration decl) { + if (decl instanceof Java.AbstractCompilationUnit.SingleTypeImportDeclaration) { + return buildImportAsDeclaration((Java.AbstractCompilationUnit.SingleTypeImportDeclaration) decl); + } else if (decl instanceof Java.AbstractCompilationUnit.SingleStaticImportDeclaration) { + return buildImportStaticDeclaration((Java.AbstractCompilationUnit.SingleStaticImportDeclaration) decl); + } else { + if (ignoreInvalidSyntax) + return new ImportAsDeclaration(); + throw newTransformError(decl, XLangASTKind.ImportAsDeclaration); + } + } + + private NopException newTransformError(Java.Locatable node, XLangASTKind kind) { + throw new NopException(JavaCompilerErrors.ERR_JAVAC_NOT_SUPPORT_TRANSFORM_TO_XLANG_AST_FAIL) + .param(JavaCompilerErrors.ARG_JAVA_TYPE, node.getClass().getSimpleName()) + .param(JavaCompilerErrors.ARG_AST_KIND, kind); + } + + public ImportAsDeclaration buildImportAsDeclaration(Java.AbstractCompilationUnit.SingleTypeImportDeclaration decl) { + SourceLocation loc = buildLocation(decl); + + QualifiedName source = QualifiedName.valueOf(loc, StringHelper.joinArray(decl.identifiers, ".")); + return XLangASTBuilder.importClass(loc, source, null); + } + + public ImportAsDeclaration buildImportStaticDeclaration(Java.AbstractCompilationUnit.SingleStaticImportDeclaration decl) { + SourceLocation loc = buildLocation(decl); + + QualifiedName source = QualifiedName.valueOf(loc, StringHelper.joinArray(decl.identifiers, ".")); + ImportAsDeclaration ret = XLangASTBuilder.importClass(loc, source, null); + ret.setStaticImport(true); + return ret; + } + + public Declaration buildDeclaration(Java.PackageMemberTypeDeclaration type) { + if (type instanceof Java.PackageMemberEnumDeclaration) { + return buildEnumDeclaration((Java.PackageMemberEnumDeclaration) type); + } else if (type instanceof Java.PackageMemberClassDeclaration) { + return buildClassDeclaration((Java.PackageMemberClassDeclaration) type); + } else if (type instanceof Java.PackageMemberInterfaceDeclaration) { + return buildInterfaceDeclaration((Java.PackageMemberInterfaceDeclaration) type); + } else { + if (ignoreInvalidSyntax) + return new ClassDefinition(); + throw newTransformError(type, XLangASTKind.ClassDefinition); + } + } + + public ClassDefinition buildClassDeclaration(Java.PackageMemberClassDeclaration type) { + SourceLocation loc = buildLocation(type); + + ClassDefinition def = new ClassDefinition(); + def.setLocation(loc); + def.setClassKind(XLangClassKind.CLASS); + def.setName(Identifier.valueOf(loc, type.getName())); + ParameterizedTypeNode pType = buildType(type.extendedType); + def.setExtendsType(pType); + def.setImplementTypes(buildTypes(type.implementedTypes)); + List fields = buildFieldDeclarations(type.getMemberTypeDeclarations()); + def.setFields(fields); + List methods = buildFunctionDeclarations(type.getMethodDeclarations()); + def.setMethods(methods); + return def; + } + + public ParameterizedTypeNode buildType(Java.Type type) { + if (type == null) + return null; + SourceLocation loc = buildLocation(type); + ParameterizedTypeNode ret = new ParameterizedTypeNode(); + ret.setLocation(loc); + + if (type instanceof Java.ReferenceType) { + Java.ReferenceType refType = (Java.ReferenceType) type; + ret.setTypeName(StringHelper.joinArray(refType.identifiers, ".")); + if (refType.typeArguments != null) { + List args = new ArrayList<>(); + for (Java.TypeArgument typeArg : refType.typeArguments) { + args.add(buildTypeArgument(typeArg)); + } + ret.setTypeArgs(args); + } + } + return ret; + } + + public List buildTypes(Java.Type[] types) { + if (types == null || types.length == 0) + return null; + + List ret = new ArrayList<>(); + for (Java.Type type : types) { + ret.add(buildType(type)); + } + return ret; + } + + public NamedTypeNode buildTypeArgument(Java.TypeArgument arg) { + if (arg instanceof Java.ReferenceType) { + return buildType((Java.ReferenceType) arg); + } + return new TypeNameNode(); + } + + public ClassDefinition buildInterfaceDeclaration(Java.PackageMemberInterfaceDeclaration type) { + SourceLocation loc = buildLocation(type); + + ClassDefinition def = new ClassDefinition(); + def.setLocation(loc); + def.setClassKind(XLangClassKind.INTERFACE); + def.setName(Identifier.valueOf(loc, type.getName())); + return def; + } + + public List buildFieldDeclarations(Collection members) { + return members.stream().map(this::buildFieldDeclaration).collect(Collectors.toList()); + } + + public List buildFunctionDeclarations(List members) { + return members.stream().map(this::buildFunctionDeclaration).collect(Collectors.toList()); + } + + public FieldDeclaration buildFieldDeclaration(Java.MemberTypeDeclaration member) { + SourceLocation loc = buildLocation(member); + FieldDeclaration ret = new FieldDeclaration(); + ret.setLocation(loc); + ret.setName(Identifier.valueOf(loc, member.getName())); + return ret; + } + + public FunctionDeclaration buildFunctionDeclaration(Java.MethodDeclarator method) { + SourceLocation loc = buildLocation(method); + + FunctionDeclaration ret = new FunctionDeclaration(); + ret.setLocation(loc); + ret.setName(Identifier.valueOf(loc, method.name)); + if (method.formalParameters != null) { + List params = new ArrayList<>(); + Java.FunctionDeclarator.FormalParameter[] parameters = method.formalParameters.parameters; + for (int i = 0; i < parameters.length; ++i) { + params.add(buildParamDeclaration(parameters[i])); + } + + ret.setParams(params); + } + ret.setReturnType(buildType(method.type)); + return ret; + } + + public ParameterDeclaration buildParamDeclaration(Java.FunctionDeclarator.FormalParameter param) { + SourceLocation loc = buildLocation(param); + ParameterDeclaration ret = new ParameterDeclaration(); + ret.setLocation(loc); + ret.setName(Identifier.valueOf(null, param.name)); + ret.setType(buildType(param.type)); + return ret; + } + + public EnumDeclaration buildEnumDeclaration(Java.PackageMemberEnumDeclaration type) { + SourceLocation loc = buildLocation(type); + + EnumDeclaration decl = new EnumDeclaration(); + decl.setName(XLangASTBuilder.identifier(loc, type.getName())); + + List members = new ArrayList<>(); + for (Java.EnumConstant constant : type.getConstants()) { + EnumMember member = buildEnumMember(constant); + members.add(member); + } + decl.setMembers(members); + return decl; + } + + private EnumMember buildEnumMember(Java.EnumConstant constant) { + SourceLocation loc = buildLocation(constant); + + EnumMember member = new EnumMember(); + member.setLocation(loc); + member.setName(Identifier.valueOf(loc, constant.name)); + return member; + } +} \ No newline at end of file diff --git a/nop-xlang/src/main/java/io/nop/xlang/xmeta/xjava/JaninoHelper.java b/nop-xlang/src/main/java/io/nop/xlang/xmeta/xjava/JaninoHelper.java index b8ffe259c..9cee719b6 100644 --- a/nop-xlang/src/main/java/io/nop/xlang/xmeta/xjava/JaninoHelper.java +++ b/nop-xlang/src/main/java/io/nop/xlang/xmeta/xjava/JaninoHelper.java @@ -9,19 +9,29 @@ import io.nop.api.core.exceptions.NopException; import io.nop.api.core.util.SourceLocation; +import io.nop.core.resource.IResource; +import io.nop.core.resource.ResourceHelper; import org.codehaus.commons.compiler.CompileException; import org.codehaus.commons.compiler.Location; import org.codehaus.janino.Java; import org.codehaus.janino.Parser; import org.codehaus.janino.Scanner; +import org.codehaus.janino.Unparser; import java.io.IOException; import java.io.StringReader; +import java.io.StringWriter; import static io.nop.xlang.XLangErrors.ARG_DETAIL; import static io.nop.xlang.XLangErrors.ERR_JAVAC_PARSE_FAIL; public class JaninoHelper { + public static Java.CompilationUnit parseFromResource(IResource resource) { + SourceLocation loc = SourceLocation.fromPath(resource.getPath()); + String source = ResourceHelper.readText(resource); + return parseJavaSource(loc, source); + } + public static Java.CompilationUnit parseJavaSource(SourceLocation loc, String source) { if (loc == null) loc = SourceLocation.fromClass(JaninoHelper.class); @@ -41,6 +51,12 @@ public static Java.CompilationUnit parseJavaSource(SourceLocation loc, String so } } + public static String unparse(Java.CompilationUnit unit) { + StringWriter out = new StringWriter(); + Unparser.unparse(unit, out); + return out.toString(); + } + static String getErrorDetail(CompileException e) { Location loc = e.getLocation(); if (loc == null) diff --git a/nop-xlang/src/test/java/io/nop/xlang/janino/TestJavaTransformer.java b/nop-xlang/src/test/java/io/nop/xlang/janino/TestJavaTransformer.java new file mode 100644 index 000000000..db6e9d325 --- /dev/null +++ b/nop-xlang/src/test/java/io/nop/xlang/janino/TestJavaTransformer.java @@ -0,0 +1,47 @@ +package io.nop.xlang.janino; + +import io.nop.commons.util.FileHelper; +import io.nop.core.exceptions.ErrorMessageManager; +import io.nop.core.resource.IResource; +import io.nop.core.resource.impl.FileResource; +import io.nop.core.resource.scan.FileScanHelper; +import io.nop.core.unittest.BaseTestCase; +import io.nop.xlang.ast.CompilationUnit; +import io.nop.xlang.ast.print.XLangSourcePrinter; +import io.nop.xlang.xmeta.xjava.JaninoHelper; +import org.codehaus.janino.Java; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.io.File; + +@Disabled +public class TestJavaTransformer extends BaseTestCase { + + @Test + public void testTransform() throws Exception { + File rootDir = getModuleDir().getCanonicalFile(); + + FileScanHelper.scanDir(rootDir, file -> { + String absPath = file.getAbsolutePath().replace('\\','/'); + if (absPath.contains("/target/") || !absPath.contains("/src/")) + return; + if (!file.isDirectory() && file.getName().endsWith(".java")) { + String relativePath = FileHelper.getRelativePath(rootDir, file); + transformJavaFile(new FileResource("/" + relativePath, file)); + } + }); + } + + void transformJavaFile(IResource resource) { + try { + File targetFile = getTargetFile(resource.getPath()); + Java.CompilationUnit unit = JaninoHelper.parseFromResource(resource); + CompilationUnit xUnit = new JavaToXLangTransformer(true).buildCompilationUnit(unit); + String code = new XLangSourcePrinter().toSource(xUnit); + FileHelper.writeText(targetFile, code, null); + } catch (Exception e) { + System.err.println("parse-failed;" + resource.toFile() + ",error=" + ErrorMessageManager.instance().getRealCause(e).toString()); + } + } +}