diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java index 379d6fcdc3..f792460cbd 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java @@ -26,22 +26,26 @@ import java.lang.reflect.InvocationTargetException; import java.util.Collection; -import java.util.List; import java.util.Optional; -import java.util.Set; + +import static com.github.javaparser.ast.observer.ObservableProperty.Type.MULTIPLE_NODES; +import static com.github.javaparser.ast.observer.ObservableProperty.Type.MULTIPLE_PROPERTIES; +import static com.github.javaparser.ast.observer.ObservableProperty.Type.SINGLE_PROPERTY; /** * Properties considered by the AstObserver */ public enum ObservableProperty { - ANNOTATIONS(true), + ANNOTATIONS(MULTIPLE_NODES), ANONYMOUS_CLASS_BODY, - ARGUMENTS(true), + ARGUMENTS(MULTIPLE_NODES), + IS_ASTERISK, BLOCK, BODY, - CATCH_CLAUSES(true), + CATCH_CLAUSES(MULTIPLE_NODES), CHECK, CLASS_BODY, + CLASS_DECLARATION, CLASS_EXPR, COMMENT, COMMENTED_NODE, @@ -54,13 +58,14 @@ public enum ObservableProperty { ELEMENTS, ELSE_EXPR, ELSE_STMT, + ENCLOSING_PARAMETERS, ENTRIES, EXPRESSION, - EXTENDED_TYPES(true), + EXTENDED_TYPES(MULTIPLE_NODES), FIELD, FINALLY_BLOCK, IDENTIFIER, - IMPLEMENTED_TYPES(true), + IMPLEMENTED_TYPES(MULTIPLE_NODES), IMPORTS, INDEX, INITIALIZER, @@ -73,7 +78,7 @@ public enum ObservableProperty { LEVELS, MEMBERS, MEMBER_VALUE, - MODIFIERS, + MODIFIERS(MULTIPLE_PROPERTIES), MESSAGE, NAME, OPERATOR, @@ -81,14 +86,12 @@ public enum ObservableProperty { PAIRS, PARAMETER, PARAMETERS, - ENCLOSING_PARAMETERS, QUALIFIER, RANGE, RESOURCES, RIGHT, SCOPE, SELECTOR, - IS_ASTERISK, IS_STATIC, STATIC_MEMBER, STATEMENT, @@ -97,34 +100,56 @@ public enum ObservableProperty { TARGET, THEN_EXPR, THEN_STMT, - THROWN_TYPES(true), + THROWN_TYPES(MULTIPLE_NODES), TRY_BLOCK, - TYPE, + TYPE(SINGLE_PROPERTY), TYPES, - TYPE_ARGUMENTS(true), + TYPE_ARGUMENTS(MULTIPLE_NODES), TYPE_BOUND, - CLASS_DECLARATION, - TYPE_PARAMETERS(true), + TYPE_PARAMETERS(MULTIPLE_NODES), UPDATE, VALUE, VALUES, VARIABLE, - VARIABLES, + VARIABLES(MULTIPLE_NODES), ELEMENT_TYPE, - VAR_ARGS(true); + VAR_ARGS(MULTIPLE_NODES); + + enum Type { + SINGLE_PROPERTY(false, false), + SINGLE_NODE(false, true), + MULTIPLE_PROPERTIES(true, false), + MULTIPLE_NODES(true, true); + + private boolean multiple; + private boolean node; - private boolean multiple; + Type(boolean multiple, boolean node) { + this.multiple = multiple; + this.node = node; + } + } + + private Type type; - ObservableProperty(boolean multiple) { - this.multiple = multiple; + ObservableProperty(Type type) { + this.type = type; } ObservableProperty() { - this(false); + this(Type.SINGLE_NODE); + } + + public boolean isAboutNodes() { + return type.node; + } + + public boolean isAboutValues() { + return !isAboutNodes(); } public boolean isMultiple() { - return multiple; + return type.multiple; } public boolean isSingle() { @@ -135,7 +160,7 @@ public String camelCaseName() { return Utils.toCamelCase(name()); } - public Node singleValueFor(Node node) { + public Node singlePropertyFor(Node node) { String getterName = "get" + Utils.capitalize(camelCaseName()); try { Object result = node.getClass().getMethod(getterName).invoke(node); @@ -144,13 +169,37 @@ public Node singleValueFor(Node node) { } if (result instanceof Node) { return (Node)result; + } else if (result instanceof Optional){ + Optional opt = (Optional)result; + if (opt.isPresent()) { + return opt.get(); + } else { + return null; + } } else { + throw new RuntimeException(String.format("Property %s returned %s (%s)", this.name(), result.toString(), result.getClass().getCanonicalName())); + } + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new RuntimeException("Unable to get single value for " + this.name() + " from " + node, e); + } + } + + public Object singleValueFor(Node node) { + String getterName = "get" + Utils.capitalize(camelCaseName()); + try { + Object result = node.getClass().getMethod(getterName).invoke(node); + if (result == null) { + return null; + } + if (result instanceof Optional){ Optional opt = (Optional)result; if (opt.isPresent()) { return opt.get(); } else { return null; } + } else { + return result; } } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { throw new RuntimeException("Unable to get single value for " + this.name() + " from " + node, e); diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java b/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java index 289526bf9b..284329e3f4 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/ConcreteSyntaxModel.java @@ -23,32 +23,21 @@ import com.github.javaparser.ASTParserConstants; import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.ast.Modifier; import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.comments.Comment; -import com.github.javaparser.ast.expr.AnnotationExpr; import com.github.javaparser.ast.expr.ClassExpr; import com.github.javaparser.ast.expr.SimpleName; -import com.github.javaparser.ast.nodeTypes.NodeWithModifiers; -import com.github.javaparser.ast.nodeTypes.NodeWithTypeArguments; import com.github.javaparser.ast.nodeTypes.NodeWithVariables; -import com.github.javaparser.ast.observer.Observable; import com.github.javaparser.ast.observer.ObservableProperty; -import com.github.javaparser.ast.type.ArrayType; -import com.github.javaparser.ast.type.ClassOrInterfaceType; -import com.github.javaparser.ast.type.Type; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; +import com.github.javaparser.ast.type.*; + +import java.util.*; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; import static com.github.javaparser.ast.observer.ObservableProperty.*; import static com.github.javaparser.utils.PositionUtils.sortByBeginPosition; @@ -107,13 +96,29 @@ public ChildElement(ObservableProperty property) { @Override public void prettyPrint(Node node, SourcePrinter printer) { - Node child = property.singleValueFor(node); + Node child = property.singlePropertyFor(node); if (child != null) { genericPrettyPrint(child, printer); } } } + private static class ValueElement implements Element { + private ObservableProperty property; + + public ValueElement(ObservableProperty property) { + this.property = property; + } + + @Override + public void prettyPrint(Node node, SourcePrinter printer) { + Object value = property.singleValueFor(node); + if (value != null) { + printer.print(value.toString()); + } + } + } + private static class ListElement implements Element { private ObservableProperty property; private Element separator; @@ -139,21 +144,40 @@ public ListElement(ObservableProperty property, Element separator, Element prece @Override public void prettyPrint(Node node, SourcePrinter printer) { - NodeList nodeList = property.listValueFor(node); - if (nodeList == null) { - return; - } - if (!nodeList.isEmpty() && preceeding != null) { - preceeding.prettyPrint(node, printer); - } - for (int i=0;i values = property.listPropertyFor(node); + if (values == null) { + return; + } + if (!values.isEmpty() && preceeding != null) { + preceeding.prettyPrint(node, printer); + } + for (Iterator it = values.iterator(); it.hasNext(); ) { + printer.print(it.next().toString()); + if (separator != null && it.hasNext()) { + separator.prettyPrint(node, printer); + } + } + if (!values.isEmpty() && following != null) { + following.prettyPrint(node, printer); } - } - if (!nodeList.isEmpty() && following != null) { - following.prettyPrint(node, printer); } } } @@ -196,7 +220,7 @@ public void prettyPrint(Node node, SourcePrinter printer) { boolean test; if (condition != null) { if (condition.isSingle()) { - test = condition.singleValueFor(node) != null; + test = condition.singlePropertyFor(node) != null; } else { test = condition.listValueFor(node) != null && !condition.listValueFor(node).isEmpty(); } @@ -254,6 +278,10 @@ Builder child(ObservableProperty property) { return add(new ChildElement(property)); } + Builder value(ObservableProperty property) { + return add(new ValueElement(property)); + } + Builder string(int tokenType, String content) { return add(new StringElement(tokenType, content)); } @@ -328,8 +356,7 @@ Builder orphanCommentsBeforeThis() { } Builder annotations() { - //return list(ObservableProperty.ANNOTATIONS, newline(), null, newline()); - throw new UnsupportedOperationException(); + return add(ConcreteSyntaxModel.list(ObservableProperty.ANNOTATIONS, ConcreteSyntaxModel.newline(), null, ConcreteSyntaxModel.newline())); } Builder modifiers() { @@ -388,8 +415,8 @@ private static ChildElement child(ObservableProperty property) { return new ChildElement(property); } - private static ChildElement child(Node node) { - throw new UnsupportedOperationException(); + private static Element child(Node child) { + return (node, printer) -> genericPrettyPrint(child, printer); } private static ListElement list(ObservableProperty property) { @@ -500,6 +527,45 @@ public static ConcreteSyntaxModel forClass(Class nodeClazz) { .semicolon() .build(); } + if (nodeClazz.equals(PrimitiveType.class)) { + return new Builder() + .comment() + .annotations() + .value(ObservableProperty.TYPE) + .build(); + } + if (nodeClazz.equals(VariableDeclarator.class)) { + return new Builder() + .comment() + .child(ObservableProperty.NAME) + .annotations() + .value(ObservableProperty.TYPE) + .build(); + +// printJavaComment(n.getComment(), arg); +// n.getName().accept(this, arg); +// +// Type commonType = getMaximumCommonType(n.getAncestorOfType(NodeWithVariables.class).get()); +// +// Type type = n.getType(); +// +// ArrayType arrayType = null; +// +// for (int i = commonType.getArrayLevel(); i < type.getArrayLevel(); i++) { +// if (arrayType == null) { +// arrayType = (ArrayType) type; +// } else { +// arrayType = (ArrayType) arrayType.getComponentType(); +// } +// printAnnotations(arrayType.getAnnotations(), true, arg); +// printer.print("[]"); +// } +// +// if (n.getInitializer().isPresent()) { +// printer.print(" = "); +// n.getInitializer().get().accept(this, arg); +// } + } throw new UnsupportedOperationException("Class " + nodeClazz.getSimpleName()); }