diff --git a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java index 0521640c254..96afd3410b0 100644 --- a/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java +++ b/src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java @@ -31,7 +31,6 @@ import spoon.reflect.code.CtCase; import spoon.reflect.code.CtCatch; import spoon.reflect.code.CtCatchVariable; -import spoon.reflect.code.CtCodeElement; import spoon.reflect.code.CtCodeSnippetExpression; import spoon.reflect.code.CtCodeSnippetStatement; import spoon.reflect.code.CtComment; @@ -127,7 +126,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import java.util.Set; @@ -413,16 +411,15 @@ public void visitCtAnnotation(CtAnnotation annotation) printer.writeSeparator("@"); scan(annotation.getAnnotationType()); if (annotation.getValues().size() > 0) { - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, "(", false, false, ",", true, false, ")")) { - for (Entry e : annotation.getValues().entrySet()) { - lp.printSeparatorIfAppropriate(); + elementPrinterHelper.printList(annotation.getValues().entrySet(), + null, false, "(", false, false, ",", true, false, ")", + e -> { if ((annotation.getValues().size() == 1 && "value".equals(e.getKey())) == false) { //it is not a default value attribute. We must print a attribute name too. printer.writeIdentifier(e.getKey()).writeSpace().writeOperator("=").writeSpace(); } elementPrinterHelper.writeAnnotationElement(annotation.getFactory(), e.getValue()); - } - } + }); } } @@ -587,13 +584,9 @@ public void visitCtCatch(CtCatch catchBlock) { printer.writeSpace().writeKeyword("catch").writeSpace().writeSeparator("("); CtCatchVariable parameter = catchBlock.getParameter(); if (parameter != null && parameter.getMultiTypes().size() > 1) { - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, null, false, true, "|", true, false, null)) { - for (int i = 0; i < parameter.getMultiTypes().size(); i++) { - lp.printSeparatorIfAppropriate(); - CtTypeReference type = parameter.getMultiTypes().get(i); - scan(type); - } - } + elementPrinterHelper.printList(parameter.getMultiTypes(), + null, false, null, false, true, "|", true, false, null, + type -> scan(type)); printer.writeSpace().writeIdentifier(parameter.getSimpleName()); } else { scan(parameter); @@ -734,12 +727,9 @@ public > void visitCtEnum(CtEnum ctEnum) { if (ctEnum.getEnumValues().size() == 0) { printer.writeSeparator(";").writeln(); } else { - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, null, false, false, ",", true, false, ";")) { - for (CtEnumValue enumValue : ctEnum.getEnumValues()) { - lp.printSeparatorIfAppropriate(); - scan(enumValue); - } - } + elementPrinterHelper.printList(ctEnum.getEnumValues(), + null, false, null, false, false, ",", true, false, ";", + enumValue -> scan(enumValue)); } elementPrinterHelper.writeElementList(ctEnum.getTypeMembers()); @@ -1061,12 +1051,9 @@ public void visitCtPackageExport(CtPackageExport moduleExport) { visitCtPackageReference(moduleExport.getPackageReference()); if (!moduleExport.getTargetExport().isEmpty()) { - try (ListPrinter lp = this.elementPrinterHelper.createListPrinter(false, " to", true, false, ",", true, false, null)) { - for (CtModuleReference moduleReference : moduleExport.getTargetExport()) { - lp.printSeparatorIfAppropriate(); - scan(moduleReference); - } - } + this.elementPrinterHelper.printList(moduleExport.getTargetExport(), + null, false, " to", true, false, ",", true, false, null, + moduleReference -> scan(moduleReference)); } printer.writeSeparator(";").writeln(); } @@ -1076,12 +1063,9 @@ public void visitCtModuleRequirement(CtModuleRequirement moduleRequirement) { printer.writeKeyword("requires").writeSpace(); if (!moduleRequirement.getRequiresModifiers().isEmpty()) { - try (ListPrinter lp = this.elementPrinterHelper.createListPrinter(false, null, false, false, " ", false, false, " ")) { - for (CtModuleRequirement.RequiresModifier modifier : moduleRequirement.getRequiresModifiers()) { - lp.printSeparatorIfAppropriate(); - printer.writeKeyword(modifier.name().toLowerCase()); - } - } + this.elementPrinterHelper.printList(moduleRequirement.getRequiresModifiers(), + null, false, null, false, false, " ", false, false, " ", + modifier -> printer.writeKeyword(modifier.name().toLowerCase())); } scan(moduleRequirement.getModuleReference()); @@ -1092,12 +1076,9 @@ public void visitCtModuleRequirement(CtModuleRequirement moduleRequirement) { public void visitCtProvidedService(CtProvidedService moduleProvidedService) { printer.writeKeyword("provides").writeSpace(); scan(moduleProvidedService.getServiceType()); - try (ListPrinter lp = this.elementPrinterHelper.createListPrinter(false, " with", true, false, ",", true, false, null)) { - for (CtTypeReference implementations : moduleProvidedService.getImplementationTypes()) { - lp.printSeparatorIfAppropriate(); - scan(implementations); - } - } + this.elementPrinterHelper.printList(moduleProvidedService.getImplementationTypes(), + null, false, " with", true, false, ",", true, false, null, + implementations -> scan(implementations)); printer.writeSeparator(";").writeln(); } @@ -1186,12 +1167,9 @@ public void visitCtFor(CtFor forLoop) { if (!forLoop.getForUpdate().isEmpty()) { printer.writeSpace(); } - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, null, false, true, ",", true, false, null)) { - for (CtStatement s : forLoop.getForUpdate()) { - lp.printSeparatorIfAppropriate(); - scan(s); - } - } + elementPrinterHelper.printList(forLoop.getForUpdate(), + null, false, null, false, true, ",", true, false, null, + s -> scan(s)); printer.writeSeparator(")"); elementPrinterHelper.writeIfOrLoopBlock(forLoop.getBody()); } @@ -1237,13 +1215,9 @@ public void visitCtInterface(CtInterface intrface) { } if (intrface.getSuperInterfaces().size() > 0) { - printer.writeSpace().writeKeyword("extends").writeSpace(); - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, null, false, true, ",", true, false, null)) { - for (CtTypeReference ref : intrface.getSuperInterfaces()) { - lp.printSeparatorIfAppropriate(); - scan(ref); - } - } + elementPrinterHelper.printList(intrface.getSuperInterfaces(), + "extends", false, null, false, true, ",", true, false, null, + ref -> scan(ref)); } context.pushCurrentThis(intrface); printer.writeSpace().writeSeparator("{").incTab(); @@ -1296,12 +1270,9 @@ public void visitCtInvocation(CtInvocation invocation) { } printer.writeIdentifier(invocation.getExecutable().getSimpleName()); } - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, "(", false, false, ",", true, false, ")")) { - for (CtExpression e : invocation.getArguments()) { - lp.printSeparatorIfAppropriate(); - scan(e); - } - } + elementPrinterHelper.printList(invocation.getArguments(), + null, false, "(", false, false, ",", true, false, ")", + e -> scan(e)); exitCtExpression(invocation); } @@ -1358,9 +1329,6 @@ public void visitCtMethod(CtMethod m) { elementPrinterHelper.writeComment(m); elementPrinterHelper.visitCtNamedElement(m, sourceCompilationUnit); elementPrinterHelper.writeModifiers(m); - if (m.isDefaultMethod()) { - printer.writeKeyword("default").writeSpace(); - } elementPrinterHelper.writeFormalTypeParameters(m); if (m.getFormalCtTypeParameters().size() > 0) { printer.writeSpace(); @@ -1440,13 +1408,10 @@ public void visitCtNewArray(CtNewArray newArray) { } } if (newArray.getDimensionExpressions().size() == 0) { - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, "{", true, false, ",", true, true, "}")) { - for (CtExpression e : newArray.getElements()) { - lp.printSeparatorIfAppropriate(); - scan(e); - } - elementPrinterHelper.writeComment(newArray, CommentOffset.INSIDE); - } + elementPrinterHelper.printList(newArray.getElements(), + null, false, "{", true, false, ",", true, true, "}", + e -> scan(e)); + elementPrinterHelper.writeComment(newArray, CommentOffset.INSIDE); } elementPrinterHelper.writeComment(newArray, CommentOffset.AFTER); exitCtExpression(newArray); @@ -1495,12 +1460,9 @@ private void printConstructorCall(CtConstructorCall ctConstructorCall) { scan(ctConstructorCall.getType()); } - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, "(", false, false, ",", true, false, ")")) { - for (CtCodeElement exp : ctConstructorCall.getArguments()) { - lp.printSeparatorIfAppropriate(); - scan(exp); - } - } + elementPrinterHelper.printList(ctConstructorCall.getArguments(), + null, false, "(", false, false, ",", true, false, ")", + exp -> scan(exp)); } /** @@ -1536,14 +1498,9 @@ private boolean hasDeclaringTypeWithGenerics(CtTypeReference reference) { public void visitCtLambda(CtLambda lambda) { enterCtExpression(lambda); - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, "(", false, false, ",", false, false, ")")) { - if (lambda.getParameters().size() > 0) { - for (CtParameter parameter : lambda.getParameters()) { - lp.printSeparatorIfAppropriate(); - scan(parameter); - } - } - } + elementPrinterHelper.printList(lambda.getParameters(), + null, false, "(", false, false, ",", false, false, ")", + parameter -> scan(parameter)); printer.writeSpace(); printer.writeSeparator("->"); printer.writeSpace(); @@ -1707,12 +1664,9 @@ public void visitCtTryWithResource(CtTryWithResource tryWithResource) { enterCtStatement(tryWithResource); printer.writeKeyword("try").writeSpace(); if (tryWithResource.getResources() != null && !tryWithResource.getResources().isEmpty()) { - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, "(", false, false, ";", false, false, ")")) { - for (CtLocalVariable r : tryWithResource.getResources()) { - lp.printSeparatorIfAppropriate(); - scan(r); - } - } + elementPrinterHelper.printList(tryWithResource.getResources(), + null, false, "(", false, false, ";", false, false, ")", + r -> scan(r)); } printer.writeSpace(); scan(tryWithResource.getBody()); @@ -1781,12 +1735,9 @@ private boolean printQualified(CtTypeReference ref) { @Override public void visitCtIntersectionTypeReference(CtIntersectionTypeReference reference) { - try (ListPrinter lp = elementPrinterHelper.createListPrinter(false, null, false, true, "&", true, false, null)) { - for (CtTypeReference bound : reference.getBounds()) { - lp.printSeparatorIfAppropriate(); - scan(bound); - } - } + elementPrinterHelper.printList(reference.getBounds(), + null, false, null, false, true, "&", true, false, null, + bound -> scan(bound)); } @Override diff --git a/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java b/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java index e8e62b3593d..d139a9de629 100644 --- a/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java +++ b/src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java @@ -37,7 +37,6 @@ import spoon.reflect.declaration.CtFormalTypeDeclarer; import spoon.reflect.declaration.CtModifiable; import spoon.reflect.declaration.CtNamedElement; -import spoon.reflect.declaration.CtParameter; import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.CtTypeMember; import spoon.reflect.declaration.CtTypeParameter; @@ -48,6 +47,7 @@ import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtFieldReference; import spoon.reflect.declaration.CtImport; +import spoon.reflect.declaration.CtMethod; import spoon.reflect.reference.CtPackageReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.printer.CommentOffset; @@ -55,12 +55,14 @@ import spoon.support.reflect.CtExtendedModifier; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.StringTokenizer; +import java.util.function.Consumer; public class ElementPrinterHelper { private final DefaultJavaPrettyPrinter prettyPrinter; @@ -124,6 +126,13 @@ public void writeModifiers(CtModifiable modifiable) { for (String s : thirdPosition) { printer.writeKeyword(s).writeSpace(); } + + if (modifiable instanceof CtMethod) { + CtMethod m = (CtMethod) modifiable; + if (m.isDefaultMethod()) { + printer.writeKeyword("default").writeSpace(); + } + } } public void visitCtNamedElement(CtNamedElement namedElement, CompilationUnit sourceCompilationUnit) { @@ -143,35 +152,24 @@ public void writeExtendsClause(CtType type) { /** writes the implemented interfaces with a ListPrinter */ public void writeImplementsClause(CtType type) { if (type.getSuperInterfaces().size() > 0) { - printer.writeSpace().writeKeyword("implements").writeSpace(); - try (ListPrinter lp = createListPrinter(false, null, false, true, ",", true, false, null)) { - for (CtTypeReference ref : type.getSuperInterfaces()) { - lp.printSeparatorIfAppropriate(); - prettyPrinter.scan(ref); - } - } + printList(type.getSuperInterfaces(), "implements", + false, null, false, true, ",", true, false, null, + ref -> prettyPrinter.scan(ref)); } } public void writeExecutableParameters(CtExecutable executable) { - try (ListPrinter lp = createListPrinter(false, "(", false, false, ",", true, false, ")")) { - for (CtParameter p : executable.getParameters()) { - lp.printSeparatorIfAppropriate(); - prettyPrinter.scan(p); - } - } + printList(executable.getParameters(), null, + false, "(", false, false, ",", true, false, ")", + p -> prettyPrinter.scan(p)); } /** writes the thrown exception with a ListPrinter */ public void writeThrowsClause(CtExecutable executable) { if (executable.getThrownTypes().size() > 0) { - printer.writeSpace().writeKeyword("throws").writeSpace(); - try (ListPrinter lp = createListPrinter(false, null, false, false, ",", true, false, null)) { - for (CtTypeReference ref : executable.getThrownTypes()) { - lp.printSeparatorIfAppropriate(); - prettyPrinter.scan(ref); - } - } + printList(executable.getThrownTypes(), "throws", + false, null, false, false, ",", true, false, null, + ref -> prettyPrinter.scan(ref)); } } @@ -215,19 +213,13 @@ public void writeAnnotationElement(Factory factory, Object value) { } else if (value instanceof String) { printer.writeLiteral("\"" + LiteralHelper.getStringLiteral((String) value, true) + "\""); } else if (value instanceof Collection) { - try (ListPrinter lp = createListPrinter(false, "{", false, true, ",", false, false, "}")) { - for (Object obj : (Collection) value) { - lp.printSeparatorIfAppropriate(); - writeAnnotationElement(factory, obj); - } - } + printList((Collection) value, null, + false, "{", false, true, ",", false, false, "}", + obj -> writeAnnotationElement(factory, obj)); } else if (value instanceof Object[]) { - try (ListPrinter lp = createListPrinter(false, "{", false, true, ",", false, false, "}")) { - for (Object obj : (Object[]) value) { - lp.printSeparatorIfAppropriate(); - writeAnnotationElement(factory, obj); - } - } + printList(Arrays.asList((Object[]) value), null, + false, "{", false, true, ",", false, false, "}", + obj -> writeAnnotationElement(factory, obj)); } else if (value instanceof Enum) { try (Writable c = prettyPrinter.getContext().modify().ignoreGenerics(true)) { prettyPrinter.scan(factory.Type().createReference(((Enum) value).getDeclaringClass())); @@ -252,12 +244,9 @@ public void writeFormalTypeParameters(CtFormalTypeDeclarer ctFormalTypeDeclarer) return; } if (parameters.size() > 0) { - try (ListPrinter lp = createListPrinter(false, "<", false, false, ",", true, false, ">")) { - for (CtTypeParameter parameter : parameters) { - lp.printSeparatorIfAppropriate(); - prettyPrinter.scan(parameter); - } - } + printList(parameters, + null, false, "<", false, false, ",", true, false, ">", + parameter -> prettyPrinter.scan(parameter)); } } @@ -270,18 +259,15 @@ public void writeFormalTypeParameters(CtFormalTypeDeclarer ctFormalTypeDeclarer) public void writeActualTypeArguments(CtActualTypeContainer ctGenericElementReference) { final Collection> arguments = ctGenericElementReference.getActualTypeArguments(); if (arguments != null && arguments.size() > 0) { - try (ListPrinter lp = createListPrinter(false, "<", false, false, ",", true, false, ">")) { - for (CtTypeReference argument : arguments) { - if (!argument.isImplicit()) { - lp.printSeparatorIfAppropriate(); - if (prettyPrinter.context.forceWildcardGenerics()) { - printer.writeSeparator("?"); - } else { - prettyPrinter.scan(argument); - } + printList(arguments.stream().filter(a -> !a.isImplicit())::iterator, + null, false, "<", false, false, ",", true, false, ">", + argument -> { + if (prettyPrinter.context.forceWildcardGenerics()) { + printer.writeSeparator("?"); + } else { + prettyPrinter.scan(argument); } - } - } + }); } } @@ -477,18 +463,18 @@ public void writeIfOrLoopBlock(CtStatement block) { /** * Creates new handler which assures consistent printing of lists * prefixed with `start`, separated by `next` and suffixed by `end` - * @param startPrefixSpace TODO + * @param startPrefixSpace if true then `start` token is prefixed with space * @param start the string which has to be printed at the beginning of the list - * @param startSufficSpace TODO - * @param nextPrefixSpace TODO + * @param startSufficSpace if true then `start` token is suffixed with space + * @param nextPrefixSpace if true then `next` token is prefixed with space * @param next the string which has to be used as separator before each next item - * @param nextSuffixSpace TODO - * @param endPrefixSpace TODO + * @param nextSuffixSpace if true then `next` token is suffixed with space + * @param endPrefixSpace if true then `end` token is prefixed with space * @param end the string which has to be printed after the list * @return the {@link ListPrinter} whose {@link ListPrinter#printSeparatorIfAppropriate()} has to be called * before printing of each item. */ - public ListPrinter createListPrinter(boolean startPrefixSpace, String start, boolean startSufficSpace, boolean nextPrefixSpace, String next, boolean nextSuffixSpace, boolean endPrefixSpace, String end) { + private ListPrinter createListPrinter(boolean startPrefixSpace, String start, boolean startSufficSpace, boolean nextPrefixSpace, String next, boolean nextSuffixSpace, boolean endPrefixSpace, String end) { return new ListPrinter(printer, startPrefixSpace, start, startSufficSpace, nextPrefixSpace, next, nextSuffixSpace, endPrefixSpace, end); } @@ -514,4 +500,40 @@ public TokenWriter writeQualifiedName(String qualifiedName) { private PrinterHelper getPrinterHelper() { return printer.getPrinterHelper(); } + + /** + * Prints list of elements with defined delimiters using `printer` + * @param iterable the iterable of to be printed elements + * @param startKeyword the optional start keyword. It is always printed if the value is not null + * @param startPrefixSpace if true then `start` token is prefixed with space + * @param start the string which has to be printed at the beginning of the list + * @param startSuffixSpace if true then `start` token is suffixed with space + * @param nextPrefixSpace if true then `next` token is prefixed with space + * @param next the string which has to be used as separator before each next item + * @param nextSuffixSpace if true then `next` token is suffixed with space + * @param endPrefixSpace if true then `end` token is prefixed with space + * @param end the string which has to be printed after the list + * @param elementPrinter the {@link Consumer}, which is called once for each printer element of the `iterable` + */ + public void printList(Iterable iterable, + String startKeyword, + boolean startPrefixSpace, String start, boolean startSuffixSpace, + boolean nextPrefixSpace, String next, boolean nextSuffixSpace, + boolean endPrefixSpace, String end, + Consumer elementPrinter) { + + if (startKeyword != null) { + printer.writeSpace().writeKeyword(startKeyword).writeSpace(); + } + try (spoon.reflect.visitor.ListPrinter lp = createListPrinter( + startPrefixSpace, start, startSuffixSpace, + nextPrefixSpace, next, nextSuffixSpace, + endPrefixSpace, end + )) { + for (T item : iterable) { + lp.printSeparatorIfAppropriate(); + elementPrinter.accept(item); + } + } + } } diff --git a/src/test/java/spoon/test/prettyprinter/PrinterTest.java b/src/test/java/spoon/test/prettyprinter/PrinterTest.java index 0d8ee4472c8..93e6060f82e 100644 --- a/src/test/java/spoon/test/prettyprinter/PrinterTest.java +++ b/src/test/java/spoon/test/prettyprinter/PrinterTest.java @@ -455,12 +455,7 @@ public void testListPrinter() { String[] listString = new String[] {"un", "deux", "trois"}; - try (ListPrinter listPrinter = elementPrinterHelper.createListPrinter(true, "start", true, true, "next", true, true, "end")) { - for (String s : listString) { - listPrinter.printSeparatorIfAppropriate(); - tw.writeIdentifier(s); - } - } + elementPrinterHelper.printList(Arrays.asList(listString), null, true, "start", true, true, "next", true, true, "end", s -> tw.writeIdentifier(s)); String expectedResult = " start un next deux next trois end"; assertEquals(expectedResult, pp.toString());