package cn.bran.japid.compiler; import japa.parser.JavaParser; import japa.parser.ParseException; import japa.parser.TokenMgrError; import japa.parser.ast.BlockComment; import japa.parser.ast.CompilationUnit; import japa.parser.ast.ImportDeclaration; import japa.parser.ast.LineComment; import japa.parser.ast.Node; import japa.parser.ast.PackageDeclaration; import japa.parser.ast.TypeParameter; import japa.parser.ast.body.AnnotationDeclaration; import japa.parser.ast.body.AnnotationMemberDeclaration; import japa.parser.ast.body.ClassOrInterfaceDeclaration; import japa.parser.ast.body.ConstructorDeclaration; import japa.parser.ast.body.EmptyMemberDeclaration; import japa.parser.ast.body.EmptyTypeDeclaration; import japa.parser.ast.body.EnumConstantDeclaration; import japa.parser.ast.body.EnumDeclaration; import japa.parser.ast.body.FieldDeclaration; import japa.parser.ast.body.InitializerDeclaration; import japa.parser.ast.body.JavadocComment; import japa.parser.ast.body.MethodDeclaration; import japa.parser.ast.body.ModifierSet; import japa.parser.ast.body.Parameter; import japa.parser.ast.body.VariableDeclarator; import japa.parser.ast.body.VariableDeclaratorId; import japa.parser.ast.expr.AnnotationExpr; import japa.parser.ast.expr.ArrayAccessExpr; import japa.parser.ast.expr.ArrayCreationExpr; import japa.parser.ast.expr.ArrayInitializerExpr; import japa.parser.ast.expr.AssignExpr; import japa.parser.ast.expr.BinaryExpr; import japa.parser.ast.expr.BinaryExpr.Operator; import japa.parser.ast.expr.BooleanLiteralExpr; import japa.parser.ast.expr.CastExpr; import japa.parser.ast.expr.CharLiteralExpr; import japa.parser.ast.expr.ClassExpr; import japa.parser.ast.expr.ConditionalExpr; import japa.parser.ast.expr.DoubleLiteralExpr; import japa.parser.ast.expr.EnclosedExpr; import japa.parser.ast.expr.Expression; import japa.parser.ast.expr.FieldAccessExpr; import japa.parser.ast.expr.InstanceOfExpr; import japa.parser.ast.expr.IntegerLiteralExpr; import japa.parser.ast.expr.IntegerLiteralMinValueExpr; import japa.parser.ast.expr.LongLiteralExpr; import japa.parser.ast.expr.LongLiteralMinValueExpr; import japa.parser.ast.expr.MarkerAnnotationExpr; import japa.parser.ast.expr.MemberValuePair; import japa.parser.ast.expr.MethodCallExpr; import japa.parser.ast.expr.NameExpr; import japa.parser.ast.expr.NormalAnnotationExpr; import japa.parser.ast.expr.NullLiteralExpr; import japa.parser.ast.expr.ObjectCreationExpr; import japa.parser.ast.expr.QualifiedNameExpr; import japa.parser.ast.expr.SingleMemberAnnotationExpr; import japa.parser.ast.expr.StringLiteralExpr; import japa.parser.ast.expr.SuperExpr; import japa.parser.ast.expr.ThisExpr; import japa.parser.ast.expr.UnaryExpr; import japa.parser.ast.expr.VariableDeclarationExpr; import japa.parser.ast.stmt.AssertStmt; import japa.parser.ast.stmt.BlockStmt; import japa.parser.ast.stmt.BreakStmt; import japa.parser.ast.stmt.CatchClause; import japa.parser.ast.stmt.ContinueStmt; import japa.parser.ast.stmt.DoStmt; import japa.parser.ast.stmt.EmptyStmt; import japa.parser.ast.stmt.ExplicitConstructorInvocationStmt; import japa.parser.ast.stmt.ExpressionStmt; import japa.parser.ast.stmt.ForStmt; import japa.parser.ast.stmt.ForeachStmt; import japa.parser.ast.stmt.IfStmt; import japa.parser.ast.stmt.LabeledStmt; import japa.parser.ast.stmt.ReturnStmt; import japa.parser.ast.stmt.SwitchEntryStmt; import japa.parser.ast.stmt.SwitchStmt; import japa.parser.ast.stmt.SynchronizedStmt; import japa.parser.ast.stmt.ThrowStmt; import japa.parser.ast.stmt.TryStmt; import japa.parser.ast.stmt.TypeDeclarationStmt; import japa.parser.ast.stmt.WhileStmt; import japa.parser.ast.type.ClassOrInterfaceType; import japa.parser.ast.type.PrimitiveType; import japa.parser.ast.type.ReferenceType; import japa.parser.ast.type.Type; import japa.parser.ast.type.VoidType; import japa.parser.ast.type.WildcardType; import japa.parser.ast.visitor.GenericVisitor; import japa.parser.ast.visitor.VoidVisitor; import japa.parser.ast.visitor.VoidVisitorAdapter; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class JavaSyntaxTool { private static final String UTF_8 = "UTF-8"; public static CompilationUnit parse(String src) throws ParseException { ByteArrayInputStream in; try { in = new ByteArrayInputStream(src.getBytes(UTF_8)); CompilationUnit cu; cu = JavaParser.parse(in, UTF_8); return cu; } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (TokenMgrError e) { throw new ParseException(e.getMessage()); } return null; } public static boolean isValid(String src) { try { CompilationUnit cu = parse(src); return true; } catch (ParseException e) { String m = e.getMessage() + "\n"; System.out.println(m.substring(0, m.indexOf('\n'))); return false; } } /** * tell if a string is a valid method parameter list expression * * @author Bing Ran (bing.ran@gmail.com) * @param line * @return */ public static boolean isValidParamList(String line) { if (line == null) return false; if (line.trim().length() == 0) return true; try { parseParams(line); return true; } catch(Exception e) { return false; } } /** * * @author Bing Ran<bing_ran@hotmail.com> * @deprecated use the original Parameter for complete control */ public static class Param { public String type, name; public Param(String type, String name) { this.type = type; this.name = name; } } private static final String classTempForParams = "class T { void t(%s) {} }"; /** * parse a line of text that is supposed to be parameter list for a method * declaration. * * TODO: the parameter annotation, modifiers, etc ignored. should do it! * * @param line * @return */ public static List<Parameter> parseParams(String line) { final List<Parameter> ret = new ArrayList<Parameter>(); if (line == null || line.trim().length() == 0) return ret; // make it tolerant of lowercase default line = line.replace("@default(", "@Default("); String cl = String.format(classTempForParams, line); try { CompilationUnit cu = parse(cl); VoidVisitorAdapter visitor = new VoidVisitorAdapter() { @Override public void visit(Parameter p, Object arg) { ret.add(p); } }; cu.accept(visitor, null); } catch (ParseException e) { throw new RuntimeException( "the line does not seem to be a valid param list declaration: " + line); } return ret; } private static final String classTempForArgs = "class T { { foo(%s); } }"; private static final String classTempForArgsNoParenthesis = "class T { { foo%s; } }"; // XXX this method does not properly parse thingsl like A<t> a // it does not detect the error @SuppressWarnings("unchecked") public static List<String> parseArgs(String line) { final List<String> ret = new ArrayList<String>(); if (line == null || line.trim().length() == 0) return ret; @SuppressWarnings("rawtypes") VoidVisitorAdapter visitor = new VoidVisitorAdapter() { @Override public void visit(MethodCallExpr n, Object arg) { List<Expression> args = n.getArgs(); // api issue: args can be null in case of empty arg list if (args != null) for (Expression e : args) { ret.add(e.toString()); } } }; line = line.trim(); if (line.startsWith("(")){ // perhaps it's in the form of (...) String cl = String.format(classTempForArgsNoParenthesis, line); try { CompilationUnit cu = parse(cl); cu.accept(visitor, null); return ret; } catch (ParseException e) { // perhaps not really (...). fall through } } String cl = String.format(classTempForArgs, line); try { CompilationUnit cu = parse(cl); cu.accept(visitor, null); } catch (ParseException e) { throw new RuntimeException( "the line does not seem to be a valid arg list: " + line); } return ret; } /** * * @param line * @return list of named args if all the args are named; empty list if none * is named; or an exception is thrown if the arg list is not valid * or named and un-named are mixed * */ public static List<NamedArg> parseNamedArgs(String line) { final List<NamedArg> ret = new ArrayList<NamedArg>(); if (line == null || line.trim().length() == 0) return ret; line = line.trim(); // if (line.startsWith("(")) { // if (line.endsWith(")")) // line = line.substring(1, line.length() - 1); // else // throw new RuntimeException("no closing ')' in arg expression: " // + line); // } String cl = String.format(classTempForArgs, line); final String finalLine = line; try { CompilationUnit cu = parse(cl); VoidVisitorAdapter visitor = new VoidVisitorAdapter() { boolean hasNamed = false; boolean hasUnNamed = false; @Override public void visit(MethodCallExpr n, Object arg) { List<Expression> args = n.getArgs(); // api issue: args can be null in case of empty arg list if (args != null) for (Expression expr : args) { if (expr instanceof AssignExpr) { if (hasUnNamed) throw new RuntimeException( "the line has mixed named and un-named arg list. It's not valid in Japid tag invocation. It must be all-or-none.: " + finalLine); hasNamed = true; AssignExpr ae = (AssignExpr) expr; NamedArg na = new NamedArg(ae.getTarget(), ae.getValue()); ret.add(na); } else { if (hasNamed) throw new RuntimeException( "the line has mixed named and un-named arg list. It's not valid in Japid tag invocation. It must be all-or-none.: " + finalLine); hasUnNamed = true; } } } }; cu.accept(visitor, null); } catch (ParseException e) { throw new RuntimeException( "the line does not seem to be a valid arg list: " + line + ". "); } return ret; } public static boolean hasMethod(String javaSource, String string) throws ParseException { CompilationUnit cu = parse(javaSource); return hasMethod(cu, string); } public static boolean hasMethodInvocatioin(CompilationUnit cu, final String string) { if (string == null || string.trim().length() == 0) return false; final StringBuilder re = new StringBuilder(); VoidVisitorAdapter visitor = new VoidVisitorAdapter() { @Override public void visit(MethodCallExpr n, Object arg) { if (string.equals(n.getName())) { re.append(1); return; } else { super.visit(n, arg); } } }; cu.accept(visitor, null); if (re.length() == 0) return false; else return true; } public static boolean hasMethod(CompilationUnit cu, final String string) { final StringBuilder sb = new StringBuilder(); VoidVisitorAdapter visitor = new VoidVisitorAdapter() { @Override public void visit(MethodDeclaration n, Object arg) { if (n.getName().equals(string)) { sb.append(1); return; } } }; cu.accept(visitor, null); if (sb.length() == 0) return false; else return true; } public static boolean hasMethod(CompilationUnit cu, final String name, final int modis, final String returnType, String paramList) { final StringBuilder sb = new StringBuilder(); if (paramList == null) paramList = ""; String formalParamList = addParamNamesPlaceHolder(paramList); final List<Parameter> params = parseParams(formalParamList); VoidVisitorAdapter visitor = new VoidVisitorAdapter() { @Override public void visit(MethodDeclaration n, Object arg) { if (n.getName().equals(name)) { int modifiers2 = n.getModifiers(); if (modifiers2 == modis) { Type type = n.getType(); if (type.toString().equals(returnType)) { List<Parameter> ps = n.getParameters(); if (ps == null) ps = new ArrayList<Parameter>(); if (paramsMatch(params, ps)) { sb.append(1); return; } } } } } }; cu.accept(visitor, null); if (sb.length() == 0) return false; else return true; } /** * * @param cu * @param name * @param modifiers * @param returnType * @param paramList * , parameter type only: String, final int, etc * @return */ public static boolean hasMethod(CompilationUnit cu, final String name, final String modifiers, final String returnType, String paramList) { final int modis = parseModifiers(modifiers); return hasMethod(cu, name, modis, returnType, paramList); } /** * @param paramList * @return */ static String addParamNamesPlaceHolder(String paramList) { List<String> names = getNames(paramList); String formalParamList = ""; for (int i = 0; i < names.size(); i++) { formalParamList += names.get(i) + " " + (char) ('a' + i) + ","; } if (formalParamList.endsWith(",")) formalParamList = formalParamList.substring(0, formalParamList.length() - 1); return formalParamList; } /** * @param paramList * @return */ private static List<String> getNames(String paramList) { paramList = paramList.replace(' ', ','); String[] pams = paramList.split(","); List<String> names = new ArrayList<String>(); for (int i = 0; i < pams.length; i++) { String p = pams[i].trim(); if (p.length() > 0) names.add(p); } return names; } protected static boolean paramsMatch(List<Parameter> params, List<Parameter> ps) { if (params == ps) return true; if ((params == null && ps != null) || (params != null && ps == null)) return false; if (params.size() != ps.size()) { return false; } for (int i = 0; i < params.size(); i++) { Parameter p1 = params.get(i); Parameter p2 = ps.get(i); if (!matchParams(p1, p2)) { return false; } } return true; } /** * * @param p1 * @param p2 * @return true if the parameters signature matches. Parameter name does not * matter. */ private static boolean matchParams(Parameter p1, Parameter p2) { if (p1.equals(p2)) return true; if (p1.getModifiers() != p2.getModifiers()) return false; if (!p1.getType().equals(p2.getType())) return false; // TODO: compare annotations return true; } private static int parseModifiers(String modifiers) { int ret = 0; List<String> names = getNames(modifiers); for (String m : names) { if (m.equals("public")) { ret |= ModifierSet.PUBLIC; } else if (m.equals("private")) { ret |= ModifierSet.PRIVATE; } else if (m.equals("protected")) { ret |= ModifierSet.PROTECTED; } else if (m.equals("static")) { ret |= ModifierSet.STATIC; } else if (m.equals("final")) { ret |= ModifierSet.FINAL; } else if (m.equals("final")) { ret |= ModifierSet.FINAL; } else if (m.equals("synchronized")) { ret |= ModifierSet.SYNCHRONIZED; } } return ret; } /** * * @param params * Type1 p1, Type2 p2... * @return Final Type1 p1, final Type2 p2... */ public static String addFinalToAllParams(String paramline) { if (paramline == null) return null; paramline = paramline.trim(); if (paramline.length() == 0) return ""; List<Parameter> params = parseParams(paramline); String s = ""; for (Parameter p : params) { s += "final " + p.getType() + " " + p.getId().getName() + ", "; } return s.substring(0, s.lastIndexOf(", ")); } /** * box all primitive type declarations in a parameter list * * @param paramline * @return */ public static String boxPrimitiveTypesInParams(String paramline) { if (paramline == null) return null; paramline = paramline.trim(); if (paramline.length() == 0) return ""; List<Parameter> params = parseParams(paramline); String s = ""; for (Parameter p : params) { String decl = p.getType() + " " + p.getId().getName(); decl = cleanDeclPrimitive(decl); s += decl + ", "; } return s.substring(0, s.lastIndexOf(", ")); } private static final String classTempForExpr = "class T { { f = %s ; } }"; /** * starting from the start of a string and find out the longest possible * valid java expression * * @param src * @return the longest or "" in case of none */ public static String matchLongestPossibleExpr(String src) { if (src == null || src.trim().length() == 0) return ""; src = src.trim(); String expr = ""; int i = src.length(); for (; i > 0; i--) { expr = src.substring(0, i); if (expr.endsWith(";")) continue; String ss = String.format(classTempForExpr, expr); try { parse(ss); break; } catch (ParseException e) { // TODO perhaps modify Japa to create a // light weighted ParseException expr = ""; continue; } } return expr.trim(); } public static String getDefault(Parameter p) { String r = ""; List<AnnotationExpr> annotations = p.getAnnotations(); if (annotations == null) return null; for (AnnotationExpr an : annotations) { String name = an.getName().getName(); if ("Default".equals(name)) { String string = an.toString(); r = string.substring("@Default(".length(), string.length() - 1); break; } } return r; } /** * change all primitive data types to the object wrapper type in the * parameter list * * @param decl * int i, int[] ia, etc * @return the wrapper form */ public static String cleanDeclPrimitive(String decl) { decl = decl.trim(); int i = decl.length(); String var = ""; String type = ""; while (--i >= 0) { char c = decl.charAt(i); if (c == ' ' || c == '\t') { var = decl.substring(i + 1); type = decl.substring(0, i).trim(); break; } } if ("int".equals(type)) { decl = "Integer " + var; } else if ("long".equals(type)) { decl = "Long " + var; } else if ("short".equals(type)) { decl = "Short " + var; } else if ("byte".equals(type)) { decl = "Byte " + var; } else if ("float".equals(type)) { decl = "Float " + var; } else if ("double".equals(type)) { decl = "Double " + var; } else if ("char".equals(type)) { decl = "Character " + var; } else if ("boolean".equals(type)) { decl = "Boolean " + var; } return decl; } public static final Pattern AS_PATTERN = Pattern .compile("(.*)->\\s*(\\w+)"); static final String classTempForStmt = "class T { { %s ; } }"; static final String varDeclTemp = "class T { { for (%s : collection){} } }"; // /** // * // * @param s // * something like: "int a = 1, int b" // * @return // */ // public static String getFirstVarDeclare(String src) { // if (src == null || src.trim().length() == 0) // return ""; // // src = src.trim(); // final String[] ra = new String[1]; // // VoidVisitorAdapter visitor = new VoidVisitorAdapter() { // public void visit(VariableDeclarationExpr n, Object arg) { // // Type type = n.getType(); // List<VariableDeclarator> vars = n.getVars(); // if (vars.size() > 1) { // // not good yet // } // else { // VariableDeclarator var = vars.get(0); // VariableDeclaratorId id = var.getId(); // ra[0] = id.getName(); // } // } // }; // // String expr = ""; // int i = src.length(); // for (; i > 0; i--) { // expr = src.substring(0, i); // String ss = String.format(classTempForVarDef, expr); // try { // CompilationUnit cu = parse(ss); // cu.accept(visitor, null); // if (ra[0] != null) // break; // else // continue; // } catch (ParseException e) { // continue; // } // } // // return expr.trim(); // } /** * to extract the arg list part and optionally the local var part to take * the result. Used in doBody to set the result to a local variable Can also * be used to catch the tag invocation result in a local variable. * * * @param s * arg list: a, 1 -> var, (1, 2, 3, "as") -> var * @return an array of string, the first one being the arg list, the second * one, if exists, being the local var name */ public static String[] breakArgParts(String s) { Matcher m = AS_PATTERN.matcher(s); if (m.matches()) { String[] r = new String[2]; r[0] = m.group(1); r[1] = m.group(2); return r; } else { return new String[] { s }; } } public static boolean isValidExpr(String expr) { String ss = String.format(classTempForExpr, expr); try { parse(ss); return true; } catch (ParseException e) { return false; } } /** * verify that line is a valid method declaration part, excluding method body and the {} * @param line: something like foo(int a, String b) */ public static void isValidMethDecl(String line) { final String classTempForMeth = "class T { %s{} }"; String classString = String.format(classTempForMeth, line); try { CompilationUnit cu = parse(classString); VoidVisitorAdapter visitor = new VoidVisitorAdapter() { }; cu.accept(visitor, null); } catch (ParseException e) { throw new RuntimeException( "the line does not seem to be a valid method declaration: " + line + ". Was expecting something like foo(int a, String b)."); } } public static void isValidMethodCall(String src) { String classString = String.format(classTempForStmt, src); try { List<CodeNode> nodes = parseCode(classString); if (tyepMatch(nodes, 5, MethodCallExpr.class)) { // make sure there is only one statement at indentation level 4 if (getIndentatioCount(nodes, 4) == 1) { return; } } throw new RuntimeException( "the line does not seem to be a valid method invocation expression: " + src + ". Was expecting something like x.foo(a, b)."); // // CompilationUnit cu = parse(classString); // final boolean[] good = new boolean[1]; // good[0] = false; // VoidVisitorAdapter visitor = new VoidVisitorAdapter() { // @Override // public void visit(MethodCallExpr n, Object arg) { // good[0] = true; // } // // // TODO: should detect that the top most expression is a method call // }; // cu.accept(visitor, null); // // if (!good[0]) // throw new RuntimeException( // "the line does not seem to be a valid method invocation expression: " // + src + ". Was expecting something like x.foo(a, b)."); // else // if (!methPattern.matcher(src).matches()) // throw new RuntimeException( // "the line does not seem to be a valid method invocation expression: " // + src + ". Was expecting something like x.foo(a, b)."); // } catch (RuntimeException e) { throw new RuntimeException( "the line does not seem to be a valid method invocation expression: " + src + ". Was expecting something like foo(a, b)."); } } private static int getIndentatioCount(List<CodeNode> nodes, int i) { int c = 0; for (CodeNode n : nodes) { if (n.nestLevel == i) c++; } return c; } private static boolean tyepMatch(List<CodeNode> nodes, int pos, Class<? extends Node> targetClass) { return nodes.size() > pos && nodes.get(pos).node.getClass() == targetClass; } public static boolean isValidSingleVarDecl(String src) { String classString = String.format(varDeclTemp, src); try { CompilationUnit cu = parse(classString); return true; } catch (ParseException e) { return false; } } public final static Pattern methPattern = Pattern.compile("[\\w\\.\\$\\s]+\\(.*\\)"); public static boolean isValidMethodCallSimple(String src) { if (src == null ) return false; src = src.trim(); if (src.length() < 3) return false; if (!methPattern.matcher(src).matches()) return false; return true; } public static String IF_PREDICATE = "class T { { if %s {} } }"; public static String IF_PREDICATE_BRACE = "class T { { if %s } } }"; public static String IF_PREDICATE_OPEN = "class T { { if(%s) {} } }"; public static String IF_PREDICATE_OPEN_BRACE = "class T { { if (%s) } } }"; /** * tell if the input is a regular if predicate with () and optionally a { * @author Bing Ran (bing.ran@hotmail.com) * @param part * @return */ public static boolean isIf(String part) { String classString = String.format(IF_PREDICATE, part); try { CompilationUnit cu = parse(classString); return true; } catch (ParseException e) { classString = String.format(IF_PREDICATE_BRACE, part); try { CompilationUnit cu = parse(classString); return true; } catch (ParseException e1) { return false; } } } public static boolean isOpenIf(String part) { part = part.trim(); if (part.endsWith("{")) part = part.substring(0, part.length() - 1); String classString = String.format(IF_PREDICATE_OPEN, part); try { CompilationUnit cu = parse(classString); return true; } catch (ParseException e) { return false; } } /** * * @param part the part in a for(%s) {} * @return true if the input is a valid part in the for java 5 for loop predicative */ public static boolean isValidForLoopPredicate(String part){ String classString = String.format(TEMP_FOR_HEADER, part); try { CompilationUnit cu = parse(classString); return true; } catch (ParseException e) { return false; } } public static final String TEMP_FOR_HEADER = "class T { { for (%s){} } }"; public static class CodeNode{ public int nestLevel; public Node node; public CodeNode(int nestLevel, Node node) { this.nestLevel = nestLevel; this.node = node; } } public static class BinaryOrExpr extends Expression { BinaryExpr expr; public BinaryOrExpr(BinaryExpr expr) { this.expr = expr; } @Override public <R, A> R accept(GenericVisitor<R, A> arg0, A arg1) { return null; } @Override public <A> void accept(VoidVisitor<A> arg0, A arg1) { } } public static List<CodeNode> parseCode(String code) { try{ final List<CodeNode> nodes = new LinkedList(); CompilationUnit cu = parse(code); VoidVisitorAdapter visitor = new VoidVisitorAdapter() { int nested = 0; @Override public void visit(AnnotationDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(AnnotationMemberDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ArrayAccessExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ArrayCreationExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ArrayInitializerExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(AssertStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(AssignExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(BinaryExpr n, Object arg) { if (n.getOperator() == Operator.binOr) { nodes.add(new CodeNode(nested++, new BinaryOrExpr(n))); } else { nodes.add(new CodeNode(nested++, n)); } super.visit(n, arg); nested--; } @Override public void visit(BlockComment n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(BlockStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(BooleanLiteralExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(BreakStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(CastExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(CatchClause n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(CharLiteralExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ClassExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ClassOrInterfaceDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ClassOrInterfaceType n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(CompilationUnit n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ConditionalExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ConstructorDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ContinueStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(DoStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(DoubleLiteralExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(EmptyMemberDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(EmptyStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(EmptyTypeDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(EnclosedExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(EnumConstantDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(EnumDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ExplicitConstructorInvocationStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ExpressionStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(FieldAccessExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(FieldDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ForeachStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ForStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(IfStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ImportDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(InitializerDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(InstanceOfExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(IntegerLiteralExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(IntegerLiteralMinValueExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(JavadocComment n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(LabeledStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(LineComment n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(LongLiteralExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(LongLiteralMinValueExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(MarkerAnnotationExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(MemberValuePair n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(MethodCallExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(MethodDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(NameExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(NormalAnnotationExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(NullLiteralExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ObjectCreationExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(PackageDeclaration n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(Parameter n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(PrimitiveType n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(QualifiedNameExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ReferenceType n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ReturnStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(SingleMemberAnnotationExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(StringLiteralExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(SuperExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(SwitchEntryStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(SwitchStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(SynchronizedStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ThisExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(ThrowStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(TryStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(TypeDeclarationStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(TypeParameter n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(UnaryExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(VariableDeclarationExpr n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(VariableDeclarator n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(VariableDeclaratorId n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(VoidType n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(WhileStmt n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } @Override public void visit(WildcardType n, Object arg) { nodes.add(new CodeNode(nested++, n)); super.visit(n, arg); nested--; } }; cu.accept(visitor, null); return nodes; } catch (ParseException e) { throw new RuntimeException( "invalid Java code: " + code + ". " + e); } } }