All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.python.internal.PythonPrinter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2023 the original author or authors.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* https://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openrewrite.python.internal; import org.jspecify.annotations.Nullable; import org.openrewrite.Cursor; import org.openrewrite.PrintOutputCapture; import org.openrewrite.Tree; import org.openrewrite.java.JavaPrinter; import org.openrewrite.java.marker.OmitParentheses; import org.openrewrite.java.marker.Semicolon; import org.openrewrite.java.marker.TrailingComma; import org.openrewrite.java.tree.*; import org.openrewrite.java.tree.J.Import; import org.openrewrite.java.tree.Space.Location; import org.openrewrite.marker.Marker; import org.openrewrite.marker.Markers; import org.openrewrite.python.PythonVisitor; import org.openrewrite.python.marker.KeywordArguments; import org.openrewrite.python.marker.KeywordOnlyArguments; import org.openrewrite.python.marker.Quoted; import org.openrewrite.python.marker.SuppressNewline; import org.openrewrite.python.tree.*; import java.util.Iterator; import java.util.List; import java.util.Optional; import java.util.function.UnaryOperator; import static java.util.Objects.requireNonNull; public class PythonPrinter

extends PythonVisitor> { private final PythonJavaPrinter delegate = new PythonJavaPrinter(); @Override public J visit(@Nullable Tree tree, PrintOutputCapture

p) { if (!(tree instanceof Py)) { // re-route printing to the Java printer return delegate.visitNonNull(requireNonNull(tree), p); } else { //noinspection DataFlowIssue return super.visit(tree, p); } } @Override public void setCursor(@Nullable Cursor cursor) { super.setCursor(cursor); delegate.internalSetCursor(cursor); } private void internalSetCursor(@Nullable Cursor cursor) { super.setCursor(cursor); } @Override public J visitCompilationUnit(Py.CompilationUnit cu, PrintOutputCapture

p) { beforeSyntax(cu, Location.COMPILATION_UNIT_PREFIX, p); for (JRightPadded anImport : cu.getPadding().getImports()) { visitRightPadded(anImport, PyRightPadded.Location.TOP_LEVEL_STATEMENT_SUFFIX, p); } for (JRightPadded statement : cu.getPadding().getStatements()) { visitRightPadded(statement, PyRightPadded.Location.TOP_LEVEL_STATEMENT_SUFFIX, p); } visitSpace(cu.getEof(), Location.COMPILATION_UNIT_EOF, p); if (cu.getMarkers().findFirst(SuppressNewline.class).isPresent()) { if (lastCharIs(p, '\n')) { p.out.setLength(p.out.length() - 1); } } afterSyntax(cu, p); return cu; } @Override public J visitBinary(Py.Binary binary, PrintOutputCapture

p) { beforeSyntax(binary, PySpace.Location.BINARY_PREFIX, p); visit(binary.getLeft(), p); visitSpace(binary.getPadding().getOperator().getBefore(), PySpace.Location.BINARY_OPERATOR, p); switch (binary.getOperator()) { case NotIn: p.append("not"); if (binary.getNegation() != null) { visitSpace(binary.getNegation(), PySpace.Location.BINARY_NEGATION, p); } else { p.append(' '); } p.append("in"); break; case In: p.append("in"); break; case Is: p.append("is"); break; case IsNot: p.append("is"); if (binary.getNegation() != null) { visitSpace(binary.getNegation(), PySpace.Location.BINARY_NEGATION, p); } else { p.append(' '); } p.append("not"); break; case FloorDivision: p.append("//"); break; case MatrixMultiplication: p.append("@"); break; case Power: p.append("**"); break; case StringConcatenation: // empty break; } visit(binary.getRight(), p); afterSyntax(binary, p); return binary; } @Override public J visitCollectionLiteral(Py.CollectionLiteral coll, PrintOutputCapture

p) { beforeSyntax(coll, PySpace.Location.COLLECTION_LITERAL_PREFIX, p); JContainer elements = coll.getPadding().getElements(); switch (coll.getKind()) { case LIST: visitContainer("[", elements, PyContainer.Location.COLLECTION_LITERAL_ELEMENTS, ",", "]", p); break; case SET: visitContainer("{", elements, PyContainer.Location.COLLECTION_LITERAL_ELEMENTS, ",", "}", p); break; case TUPLE: if (elements.getMarkers().findFirst(OmitParentheses.class).isPresent()) { visitContainer("", elements, PyContainer.Location.COLLECTION_LITERAL_ELEMENTS, ",", "", p); } else { visitContainer("(", elements, PyContainer.Location.COLLECTION_LITERAL_ELEMENTS, ",", ")", p); } break; } afterSyntax(coll, p); return coll; } @Override public J visitDictLiteral(Py.DictLiteral dict, PrintOutputCapture

p) { beforeSyntax(dict, PySpace.Location.DICT_LITERAL_PREFIX, p); visitContainer("{", dict.getPadding().getElements(), PyContainer.Location.DICT_LITERAL_ELEMENTS, ",", "}", p); afterSyntax(dict, p); return dict; } @Override public J visitFormattedString(Py.FormattedString fString, PrintOutputCapture

p) { beforeSyntax(fString, PySpace.Location.FORMATTED_STRING_PREFIX, p); p.append(fString.getDelimiter()); visit(fString.getParts(), p); if (!fString.getDelimiter().isEmpty()) { int idx = Math.max(fString.getDelimiter().indexOf('\''), fString.getDelimiter().indexOf('"')); p.append(fString.getDelimiter().substring(idx)); } return fString; } @Override public J visitFormattedStringValue(Py.FormattedString.Value value, PrintOutputCapture

p) { beforeSyntax(value, PySpace.Location.FORMATTED_STRING_VALUE_PREFIX, p); p.append('{'); visitRightPadded(value.getPadding().getExpression(), PyRightPadded.Location.FORMATTED_STRING_VALUE_EXPRESSION, p); if (value.getPadding().getDebug() != null) { p.append('='); visitSpace(value.getPadding().getDebug().getAfter(), PySpace.Location.FORMATTED_STRING_VALUE_DEBUG_SUFFIX, p); } if (value.getConversion() != null) { p.append('!'); switch (value.getConversion()) { case STR: p.append('s'); break; case REPR: p.append('r'); break; case ASCII: p.append('a'); break; } } if (value.getFormat() != null) { p.append(':'); visit(value.getFormat(), p); } p.append('}'); return value; } @Override public J visitMultiImport(Py.MultiImport multiImport_, PrintOutputCapture

p) { beforeSyntax(multiImport_, PySpace.Location.MULTI_IMPORT_PREFIX, p); if (multiImport_.getFrom() != null) { p.append("from"); visitRightPadded(multiImport_.getPadding().getFrom(), PyRightPadded.Location.MULTI_IMPORT_FROM, p); } p.append("import"); if (multiImport_.isParenthesized()) { visitContainer("(", multiImport_.getPadding().getNames(), PyContainer.Location.MULTI_IMPORT_NAMES, ",", ")", p); } else { visitContainer("", multiImport_.getPadding().getNames(), PyContainer.Location.MULTI_IMPORT_NAMES, ",", "", p); } afterSyntax(multiImport_, p); return multiImport_; } @Override public J visitKeyValue(Py.KeyValue keyValue, PrintOutputCapture

p) { beforeSyntax(keyValue, PySpace.Location.KEY_VALUE_PREFIX, p); visitRightPadded(keyValue.getPadding().getKey(), PyRightPadded.Location.KEY_VALUE_KEY_SUFFIX, p); p.append(':'); visit(keyValue.getValue(), p); afterSyntax(keyValue, p); return keyValue; } @Override public J visitPass(Py.Pass pass, PrintOutputCapture

p) { beforeSyntax(pass, PySpace.Location.PASS_PREFIX, p); p.append("pass"); afterSyntax(pass, p); return pass; } @Override public J visitComprehensionExpression(Py.ComprehensionExpression comp, PrintOutputCapture

p) { beforeSyntax(comp, PySpace.Location.COMPREHENSION_PREFIX, p); String open; String close; switch (comp.getKind()) { case DICT: case SET: open = "{"; close = "}"; break; case LIST: open = "["; close = "]"; break; case GENERATOR: if (comp.getMarkers().findFirst(OmitParentheses.class).isPresent()) { open = ""; close = ""; } else { open = "("; close = ")"; } break; default: throw new IllegalStateException(); } p.append(open); visit(comp.getResult(), p); for (Py.ComprehensionExpression.Clause clause : comp.getClauses()) { visit(clause, p); } visitSpace(comp.getSuffix(), PySpace.Location.COMPREHENSION_SUFFIX, p); p.append(close); afterSyntax(comp, p); return comp; } @Override public J visitComprehensionClause(Py.ComprehensionExpression.Clause clause, PrintOutputCapture

p) { visitSpace(clause.getPrefix(), PySpace.Location.COMPREHENSION_CLAUSE_PREFIX, p); p.append("for"); visit(clause.getIteratorVariable(), p); visitSpace(clause.getPadding().getIteratedList().getBefore(), PySpace.Location.COMPREHENSION_IN, p); p.append("in"); visit(clause.getIteratedList(), p); if (clause.getConditions() != null) { for (Py.ComprehensionExpression.Condition condition : clause.getConditions()) { visit(condition, p); } } return clause; } @Override public J visitComprehensionCondition(Py.ComprehensionExpression.Condition condition, PrintOutputCapture

p) { visitSpace(condition.getPrefix(), PySpace.Location.COMPREHENSION_CONDITION_PREFIX, p); p.append("if"); visit(condition.getExpression(), p); return condition; } @Override public J visitAwait(Py.Await await, PrintOutputCapture

p) { visitSpace(await.getPrefix(), PySpace.Location.AWAIT_PREFIX, p); p.append("await"); visit(await.getExpression(), p); return await; } @Override public J visitYieldFrom(Py.YieldFrom yield, PrintOutputCapture

p) { visitSpace(yield.getPrefix(), PySpace.Location.YIELD_FROM_PREFIX, p); p.append("from"); visit(yield.getExpression(), p); return yield; } @Override public J visitVariableScope(Py.VariableScope scope, PrintOutputCapture

p) { visitSpace(scope.getPrefix(), PySpace.Location.VARIABLE_SCOPE_PREFIX, p); switch (scope.getKind()) { case GLOBAL: p.append("global"); break; case NONLOCAL: p.append("nonlocal"); break; } visitRightPadded( scope.getPadding().getNames(), PyRightPadded.Location.VARIABLE_SCOPE_ELEMENT, ",", p ); return scope; } @Override public J visitDel(Py.Del del, PrintOutputCapture

p) { visitSpace(del.getPrefix(), PySpace.Location.DEL_PREFIX, p); p.append("del"); visitRightPadded( del.getPadding().getTargets(), PyRightPadded.Location.DEL_ELEMENT, ",", p ); return del; } @Override public J visitExceptionType(Py.ExceptionType type, PrintOutputCapture

p) { beforeSyntax(type, PySpace.Location.EXCEPTION_TYPE_PREFIX, p); if (type.isExceptionGroup()) { p.append("*"); } visit(type.getExpression(), p); return type; } @Override public J visitErrorFrom(Py.ErrorFrom expr, PrintOutputCapture

p) { beforeSyntax(expr, PySpace.Location.ERROR_FROM_PREFIX, p); visit(expr.getError(), p); visitSpace(expr.getPadding().getFrom().getBefore(), PySpace.Location.ERROR_FROM_SOURCE, p); p.append("from"); visit(expr.getFrom(), p); return expr; } @Override public J visitMatchCase(Py.MatchCase match, PrintOutputCapture

p) { beforeSyntax(match, PySpace.Location.MATCH_CASE_PREFIX, p); visit(match.getPattern(), p); if (match.getPadding().getGuard() != null) { visitSpace(match.getPadding().getGuard().getBefore(), PySpace.Location.MATCH_CASE_GUARD, p); p.append("if"); visit(match.getGuard(), p); } return match; } @Override public J visitMatchCasePattern(Py.MatchCase.Pattern pattern, PrintOutputCapture

p) { beforeSyntax(pattern, PySpace.Location.MATCH_PATTERN_PREFIX, p); JContainer children = pattern.getPadding().getChildren(); switch (pattern.getKind()) { case AS: visitContainer( "", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, "as", "", p ); break; case CAPTURE: case LITERAL: visitContainer( children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, p ); break; case CLASS: visitSpace(children.getBefore(), PySpace.Location.MATCH_PATTERN_ELEMENT_PREFIX, p); visitRightPadded(children.getPadding().getElements().get(0), PyRightPadded.Location.MATCH_PATTERN_ELEMENT, p); visitContainer( "(", JContainer.build(children.getPadding().getElements().subList(1, children.getElements().size())), PyContainer.Location.MATCH_PATTERN_ELEMENTS, ",", ")", p ); break; case DOUBLE_STAR: visitContainer( "**", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, "", "", p ); break; case KEY_VALUE: visitContainer( "", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, ":", "", p ); break; case KEYWORD: visitContainer( "", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, "=", "", p ); break; case MAPPING: visitContainer( "{", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, ",", "}", p ); break; case OR: visitContainer( "", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, "|", "", p ); break; case SEQUENCE: visitContainer( "", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, ",", "", p ); break; case SEQUENCE_LIST: visitContainer( "[", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, ",", "]", p ); break; case GROUP: case SEQUENCE_TUPLE: visitContainer( "(", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, ",", ")", p ); break; case STAR: visitContainer( "*", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, "", "", p ); break; case VALUE: visitContainer( "", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, "", "", p ); break; case WILDCARD: visitContainer( "_", children, PyContainer.Location.MATCH_PATTERN_ELEMENTS, "", "", p ); break; } return pattern; } @Override public J visitSpecialParameter(Py.SpecialParameter param, PrintOutputCapture

p) { beforeSyntax(param, PySpace.Location.SPECIAL_PARAM_PREFIX, p); switch (param.getKind()) { case ARGS: p.append("*"); break; case KWARGS: p.append("**"); break; } afterSyntax(param, p); return param; } @Override public J visitNamedArgument(Py.NamedArgument arg, PrintOutputCapture

p) { beforeSyntax(arg, PySpace.Location.NAMED_ARGUMENT, p); visit(arg.getName(), p); visitLeftPadded("=", arg.getPadding().getValue(), PyLeftPadded.Location.NAMED_ARGUMENT, p); return arg; } @Override public J visitSlice(Py.Slice slice, PrintOutputCapture

p) { beforeSyntax(slice, PySpace.Location.SLICE_EXPRESSION_PREFIX, p); visitRightPadded(slice.getPadding().getStart(), PyRightPadded.Location.SLICE_EXPRESSION_START, p); p.append(':'); if (slice.getPadding().getStop() != null) { visitRightPadded(slice.getPadding().getStop(), PyRightPadded.Location.SLICE_EXPRESSION_STOP, p); if (slice.getPadding().getStep() != null) { p.append(':'); visitRightPadded(slice.getPadding().getStep(), PyRightPadded.Location.SLICE_EXPRESSION_STEP, p); } } return slice; } @Override public J visitStar(Py.Star star, PrintOutputCapture

p) { beforeSyntax(star, PySpace.Location.STAR_PREFIX, p); switch (star.getKind()) { case LIST: p.append("*"); break; case DICT: p.append("**"); break; } visit(star.getExpression(), p); afterSyntax(star, p); return star; } @Override public J visitTrailingElseWrapper(Py.TrailingElseWrapper wrapper, PrintOutputCapture

p) { visit(wrapper.getStatement(), p); visitSpace( wrapper.getPadding().getElseBlock().getBefore(), Location.ELSE_PREFIX, p ); p.append("else"); visit(wrapper.getElseBlock(), p); return wrapper; } @Override public J visitTypeHint(Py.TypeHint type, PrintOutputCapture

p) { beforeSyntax(type, PySpace.Location.TYPE_HINT_PREFIX, p); J parent = getCursor().getParentTreeCursor().getValue(); if (parent instanceof J.MethodDeclaration) { p.append("->"); } else { p.append(':'); } visit(type.getTypeTree(), p); afterSyntax(type, p); return type; } @Override public J visitTypeHintedExpression(Py.TypeHintedExpression expr, PrintOutputCapture

p) { beforeSyntax(expr, PySpace.Location.TYPE_HINTED_EXPRESSION_PREFIX, p); visit(expr.getExpression(), p); visit(expr.getTypeHint(), p); afterSyntax(expr, p); return expr; } @SuppressWarnings("SameParameterValue") private static boolean lastCharIs(PrintOutputCapture p, char c) { return p.out.length() != 0 && p.out.charAt(p.out.length() - 1) == c; } private class PythonJavaPrinter extends JavaPrinter

{ @Override public J visit(@Nullable Tree tree, PrintOutputCapture

p) { if (tree instanceof Py) { // re-route printing back up to Python printer return PythonPrinter.this.visitNonNull(tree, p); } else { //noinspection DataFlowIssue return super.visit(tree, p); } } @Override public void setCursor(@Nullable Cursor cursor) { super.setCursor(cursor); PythonPrinter.this.internalSetCursor(cursor); } public void internalSetCursor(@Nullable Cursor cursor) { super.setCursor(cursor); } @Override public J visitAnnotation(J.Annotation annotation, PrintOutputCapture

p) { beforeSyntax(annotation, Space.Location.ANNOTATION_PREFIX, p); p.append("@"); visit(annotation.getAnnotationType(), p); visitContainer("(", annotation.getPadding().getArguments(), JContainer.Location.ANNOTATION_ARGUMENTS, ",", ")", p); afterSyntax(annotation, p); return annotation; } @Override public J visitArrayDimension(J.ArrayDimension arrayDimension, PrintOutputCapture

p) { beforeSyntax(arrayDimension, Space.Location.DIMENSION_PREFIX, p); p.append("["); visitRightPadded(arrayDimension.getPadding().getIndex(), JRightPadded.Location.ARRAY_INDEX, "]", p); afterSyntax(arrayDimension, p); return arrayDimension; } @Override public J visitAssert(J.Assert azzert, PrintOutputCapture

p) { beforeSyntax(azzert, Location.ASSERT_PREFIX, p); p.append("assert"); visit(azzert.getCondition(), p); if (azzert.getDetail() != null) { visitLeftPadded(",", azzert.getDetail(), JLeftPadded.Location.ASSERT_DETAIL, p); } afterSyntax(azzert, p); return azzert; } @Override public J visitAssignment(J.Assignment assignment, PrintOutputCapture

p) { final String symbol; J parentTree = getCursor().getParentTreeCursor().getValue(); if (parentTree instanceof J.Block || parentTree instanceof Py.CompilationUnit || (parentTree instanceof J.If) && ((J.If) parentTree).getThenPart() == assignment || (parentTree instanceof J.If.Else) && ((J.If.Else) parentTree).getBody() == assignment || (parentTree instanceof Loop) && ((Loop) parentTree).getBody() == assignment) { symbol = "="; } else { symbol = ":="; } beforeSyntax(assignment, Space.Location.ASSIGNMENT_PREFIX, p); visit(assignment.getVariable(), p); visitLeftPadded(symbol, assignment.getPadding().getAssignment(), JLeftPadded.Location.ASSIGNMENT, p); afterSyntax(assignment, p); return assignment; } @Override public J visitAssignmentOperation(J.AssignmentOperation assignOp, PrintOutputCapture

p) { String keyword = ""; switch (assignOp.getOperator()) { case Addition: keyword = "+="; break; case Subtraction: keyword = "-="; break; case Multiplication: keyword = "*="; break; case Division: keyword = "/="; break; case Modulo: keyword = "%="; break; case BitAnd: keyword = "&="; break; case BitOr: keyword = "|="; break; case BitXor: keyword = "^="; break; case LeftShift: keyword = "<<="; break; case RightShift: keyword = ">>="; break; case UnsignedRightShift: keyword = ">>>="; break; case Exponentiation: keyword = "**="; break; case FloorDivision: keyword = "//="; break; case MatrixMultiplication: keyword = "@="; break; } beforeSyntax(assignOp, Location.ASSIGNMENT_OPERATION_PREFIX, p); visit(assignOp.getVariable(), p); visitSpace(assignOp.getPadding().getOperator().getBefore(), Location.ASSIGNMENT_OPERATION_OPERATOR, p); p.append(keyword); visit(assignOp.getAssignment(), p); afterSyntax(assignOp, p); return assignOp; } @Override public J visitBinary(J.Binary binary, PrintOutputCapture

p) { String keyword = ""; switch (binary.getOperator()) { case Addition: keyword = "+"; break; case Subtraction: keyword = "-"; break; case Multiplication: keyword = "*"; break; case Division: keyword = "/"; break; case Modulo: keyword = "%"; break; case LessThan: keyword = "<"; break; case GreaterThan: keyword = ">"; break; case LessThanOrEqual: keyword = "<="; break; case GreaterThanOrEqual: keyword = ">="; break; case Equal: keyword = "=="; break; case NotEqual: keyword = "!="; break; case BitAnd: keyword = "&"; break; case BitOr: keyword = "|"; break; case BitXor: keyword = "^"; break; case LeftShift: keyword = "<<"; break; case RightShift: keyword = ">>"; break; case UnsignedRightShift: keyword = ">>>"; break; case Or: keyword = "or"; break; case And: keyword = "and"; break; } beforeSyntax(binary, Space.Location.BINARY_PREFIX, p); visit(binary.getLeft(), p); visitSpace(binary.getPadding().getOperator().getBefore(), Space.Location.BINARY_OPERATOR, p); p.append(keyword); visit(binary.getRight(), p); afterSyntax(binary, p); return binary; } @Override public J visitBlock(J.Block block, PrintOutputCapture

p) { beforeSyntax(block, Location.BLOCK_PREFIX, p); p.append(':'); visitStatements(block.getPadding().getStatements(), JRightPadded.Location.BLOCK_STATEMENT, p); visitSpace(block.getEnd(), Space.Location.BLOCK_END, p); afterSyntax(block, p); return block; } @Override public J visitCase(J.Case ca, PrintOutputCapture

p) { beforeSyntax(ca, Space.Location.CASE_PREFIX, p); Expression elem = ca.getExpressions().get(0); if (!(elem instanceof J.Identifier) || !((J.Identifier) elem).getSimpleName().equals("default")) { p.append("case"); } visitContainer("", ca.getPadding().getExpressions(), JContainer.Location.CASE_EXPRESSION, ",", "", p); visitSpace(ca.getPadding().getStatements().getBefore(), Space.Location.CASE, p); visitStatements(ca.getPadding().getStatements().getPadding().getElements(), JRightPadded.Location.CASE, p); if (ca.getBody() instanceof Statement) { visitRightPadded(ca.getPadding().getBody(), JRightPadded.Location.LANGUAGE_EXTENSION, p); } else { visitRightPadded(ca.getPadding().getBody(), JRightPadded.Location.CASE_BODY, ";", p); } afterSyntax(ca, p); return ca; } @Override public J visitCatch(J.Try.Catch ca, PrintOutputCapture

p) { beforeSyntax(ca, Space.Location.CATCH_PREFIX, p); p.append("except"); J.VariableDeclarations multiVariable = ca.getParameter().getTree(); beforeSyntax(multiVariable, Space.Location.VARIABLE_DECLARATIONS_PREFIX, p); visit(multiVariable.getTypeExpression(), p); for (JRightPadded paddedVariable : multiVariable.getPadding().getVariables()) { J.VariableDeclarations.NamedVariable variable = paddedVariable.getElement(); if (variable.getName().getSimpleName().isEmpty()) { continue; } visitSpace(paddedVariable.getAfter(), Location.LANGUAGE_EXTENSION, p); beforeSyntax(variable, Space.Location.VARIABLE_PREFIX, p); p.append("as"); visit(variable.getName(), p); afterSyntax(variable, p); } afterSyntax(multiVariable, p); visit(ca.getBody(), p); afterSyntax(ca, p); return ca; } @Override public J visitClassDeclaration(J.ClassDeclaration classDecl, PrintOutputCapture

p) { beforeSyntax(classDecl, Space.Location.CLASS_DECLARATION_PREFIX, p); visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); visit(classDecl.getLeadingAnnotations(), p); visit(classDecl.getPadding().getKind().getAnnotations(), p); visitSpace( classDecl.getPadding().getKind().getPrefix(), Space.Location.CLASS_KIND, p ); p.append("class"); visit(classDecl.getName(), p); if (classDecl.getPadding().getImplements() != null) { boolean omitParens = classDecl.getPadding().getImplements().getMarkers().findFirst(OmitParentheses.class).isPresent(); visitContainer(omitParens ? "" : "(", classDecl.getPadding().getImplements(), JContainer.Location.IMPLEMENTS, ",", omitParens ? "" : ")", p); } visit(classDecl.getBody(), p); afterSyntax(classDecl, p); return classDecl; } @Override public J visitControlParentheses(J.ControlParentheses controlParens, PrintOutputCapture

p) { beforeSyntax(controlParens, Space.Location.CONTROL_PARENTHESES_PREFIX, p); visitRightPadded(controlParens.getPadding().getTree(), JRightPadded.Location.PARENTHESES, "", p); afterSyntax(controlParens, p); return controlParens; } @Override public J visitElse(J.If.Else else_, PrintOutputCapture

p) { beforeSyntax(else_, Space.Location.ELSE_PREFIX, p); if (getCursor().getParentTreeCursor().getValue() instanceof J.If && else_.getBody() instanceof J.If) { p.append("el"); visit(else_.getBody(), p); } else if (else_.getBody() instanceof J.Block) { p.append("else"); visit(else_.getBody(), p); } else { p.append("else"); p.append(':'); visit(else_.getBody(), p); } afterSyntax(else_, p); return else_; } @Override public J visitForEachControl(J.ForEachLoop.Control control, PrintOutputCapture

p) { beforeSyntax(control, Space.Location.FOR_EACH_CONTROL_PREFIX, p); visitRightPadded(control.getPadding().getVariable(), JRightPadded.Location.FOREACH_VARIABLE, p); p.append("in"); visitRightPadded(control.getPadding().getIterable(), JRightPadded.Location.FOREACH_ITERABLE, p); afterSyntax(control, p); return control; } @Override public J visitForEachLoop(J.ForEachLoop forEachLoop, PrintOutputCapture

p) { beforeSyntax(forEachLoop, Space.Location.FOR_EACH_LOOP_PREFIX, p); p.append("for"); visit(forEachLoop.getControl(), p); visit(forEachLoop.getBody(), p); afterSyntax(forEachLoop, p); return forEachLoop; } @Override public J visitIdentifier(J.Identifier ident, PrintOutputCapture

p) { this.beforeSyntax(ident, Location.IDENTIFIER_PREFIX, p); Optional quoted = ident.getMarkers().findFirst(Quoted.class); quoted.ifPresent(value -> p.append(value.getStyle().getQuote())); p.append(ident.getSimpleName()); quoted.ifPresent(value -> p.append(value.getStyle().getQuote())); this.afterSyntax(ident, p); return ident; } @Override public J visitIf(J.If iff, PrintOutputCapture

p) { beforeSyntax(iff, Space.Location.IF_PREFIX, p); p.append("if"); visit(iff.getIfCondition(), p); JRightPadded thenPart = iff.getPadding().getThenPart(); if (!(thenPart.getElement() instanceof J.Block)) { p.append(":"); } visitStatement(thenPart, JRightPadded.Location.IF_THEN, p); visit(iff.getElsePart(), p); afterSyntax(iff, p); return iff; } @Override public J visitImport(Import im, PrintOutputCapture

p) { beforeSyntax(im, Space.Location.IMPORT_PREFIX, p); if (im.getQualid().getTarget() instanceof J.Empty) { visit(im.getQualid().getName(), p); } else { visit(im.getQualid(), p); } visitLeftPadded("as", im.getPadding().getAlias(), JLeftPadded.Location.IMPORT_ALIAS_PREFIX, p); afterSyntax(im, p); return im; } @Override public J visitLambda(J.Lambda lambda, PrintOutputCapture

p) { beforeSyntax(lambda, Space.Location.LAMBDA_PREFIX, p); p.append("lambda"); visitSpace(lambda.getParameters().getPrefix(), Space.Location.LAMBDA_PARAMETERS_PREFIX, p); visitMarkers(lambda.getParameters().getMarkers(), p); visitRightPadded(lambda.getParameters().getPadding().getParameters(), JRightPadded.Location.LAMBDA_PARAM, ",", p); visitSpace(lambda.getArrow(), Space.Location.LAMBDA_ARROW_PREFIX, p); p.append(":"); visit(lambda.getBody(), p); afterSyntax(lambda, p); return lambda; } @Override public J visitLiteral(J.Literal literal, PrintOutputCapture

p) { if (literal.getValue() == null && literal.getValueSource() == null) { // currently, also `...` is mapped to a `None` value literal = literal.withValueSource("None"); } beforeSyntax(literal, Space.Location.LITERAL_PREFIX, p); List unicodeEscapes = literal.getUnicodeEscapes(); if (unicodeEscapes == null) { p.append(literal.getValueSource()); } else if (literal.getValueSource() != null) { Iterator surrogateIter = unicodeEscapes.iterator(); J.Literal.UnicodeEscape surrogate = surrogateIter.hasNext() ? surrogateIter.next() : null; int i = 0; if (surrogate != null && surrogate.getValueSourceIndex() == 0) { p.append("\\u").append(surrogate.getCodePoint()); if (surrogateIter.hasNext()) { surrogate = surrogateIter.next(); } } char[] valueSourceArr = literal.getValueSource().toCharArray(); for (char c : valueSourceArr) { p.append(c); if (surrogate != null && surrogate.getValueSourceIndex() == ++i) { while (surrogate != null && surrogate.getValueSourceIndex() == i) { p.append("\\u").append(surrogate.getCodePoint()); surrogate = surrogateIter.hasNext() ? surrogateIter.next() : null; } } } } afterSyntax(literal, p); return literal; } @Override public M visitMarker(Marker marker, PrintOutputCapture

p) { if (marker instanceof Semicolon) { p.append(';'); } else if (marker instanceof TrailingComma) { p.append(','); visitSpace(((TrailingComma) marker).getSuffix(), Location.ANY, p); } //noinspection unchecked return (M) marker; } @Override public J visitMethodDeclaration(J.MethodDeclaration method, PrintOutputCapture

p) { beforeSyntax(method, Space.Location.METHOD_DECLARATION_PREFIX, p); visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); visit(method.getLeadingAnnotations(), p); for (J.Modifier m : method.getModifiers()) { visitModifier(m, p); } visit(method.getName(), p); visitContainer("(", method.getPadding().getParameters(), JContainer.Location.METHOD_DECLARATION_PARAMETERS, ",", ")", p); visit(method.getReturnTypeExpression(), p); visit(method.getBody(), p); afterSyntax(method, p); return method; } @Override public J visitMethodInvocation(J.MethodInvocation method, PrintOutputCapture

p) { beforeSyntax(method, Space.Location.METHOD_INVOCATION_PREFIX, p); visitRightPadded(method.getPadding().getSelect(), JRightPadded.Location.METHOD_SELECT, method.getSimpleName().isEmpty() ? "" : ".", p); visitContainer("<", method.getPadding().getTypeParameters(), JContainer.Location.TYPE_PARAMETERS, ",", ">", p); visit(method.getName(), p); String before = "("; String after = ")"; if (method.getMarkers().findFirst(OmitParentheses.class).isPresent()) { before = ""; after = ""; } visitContainer(before, method.getPadding().getArguments(), JContainer.Location.METHOD_INVOCATION_ARGUMENTS, ",", after, p); afterSyntax(method, p); return method; } protected void visitModifier(J.Modifier mod, PrintOutputCapture

p) { String keyword = null; switch (mod.getType()) { case Default: keyword = "def"; break; case Async: keyword = "async"; break; } if (keyword != null) { visit(mod.getAnnotations(), p); beforeSyntax(mod, Space.Location.MODIFIER_PREFIX, p); p.append(keyword); afterSyntax(mod, p); } } @Override public J visitNewArray(J.NewArray newArray, PrintOutputCapture

p) { beforeSyntax(newArray, Space.Location.NEW_ARRAY_PREFIX, p); visitContainer("[", newArray.getPadding().getInitializer(), JContainer.Location.NEW_ARRAY_INITIALIZER, ",", "]", p); afterSyntax(newArray, p); return newArray; } @Override public J visitParameterizedType(J.ParameterizedType type, PrintOutputCapture

p) { beforeSyntax(type, Space.Location.PARAMETERIZED_TYPE_PREFIX, p); visit(type.getClazz(), p); visitContainer("[", type.getPadding().getTypeParameters(), JContainer.Location.TYPE_PARAMETERS, ",", "]", p); afterSyntax(type, p); return type; } @Override public J visitSwitch(J.Switch sw, PrintOutputCapture

p) { beforeSyntax(sw, Space.Location.SWITCH_PREFIX, p); p.append("match"); visit(sw.getSelector(), p); visit(sw.getCases(), p); afterSyntax(sw, p); return sw; } @Override public J visitTernary(J.Ternary ternary, PrintOutputCapture

p) { beforeSyntax(ternary, Space.Location.TERNARY_PREFIX, p); visit(ternary.getTruePart(), p); visitSpace(ternary.getPadding().getTruePart().getBefore(), Location.TERNARY_TRUE, p); p.append("if"); visit(ternary.getCondition(), p); visitLeftPadded("else", ternary.getPadding().getFalsePart(), JLeftPadded.Location.TERNARY_FALSE, p); afterSyntax(ternary, p); return ternary; } @Override public J visitThrow(J.Throw thrown, PrintOutputCapture

p) { beforeSyntax(thrown, Space.Location.THROW_PREFIX, p); p.append("raise"); visit(thrown.getException(), p); afterSyntax(thrown, p); return thrown; } @Override public J visitTry(J.Try tryable, PrintOutputCapture

p) { boolean isWithStatement = tryable.getResources() != null && !tryable.getResources().isEmpty(); beforeSyntax(tryable, Space.Location.TRY_PREFIX, p); if (isWithStatement) { p.append("with"); } else { p.append("try"); } if (isWithStatement && tryable.getPadding().getResources() != null) { visitSpace(tryable.getPadding().getResources().getBefore(), Space.Location.TRY_RESOURCES, p); List> resources = tryable.getPadding().getResources().getPadding().getElements(); boolean first = true; for (JRightPadded resource : resources) { if (!first) { p.append(","); } else { first = false; } visitSpace(resource.getElement().getPrefix(), Space.Location.TRY_RESOURCE, p); visitMarkers(resource.getElement().getMarkers(), p); TypedTree decl = resource.getElement().getVariableDeclarations(); if (decl instanceof J.Assignment) { J.Assignment assignment = (J.Assignment) decl; visit(assignment.getAssignment(), p); if (!(assignment.getVariable() instanceof J.Empty)) { visitSpace(assignment.getPadding().getAssignment().getBefore(), Location.LANGUAGE_EXTENSION, p); p.append("as"); visit(assignment.getVariable(), p); } } else { visit(decl, p); } visitSpace(resource.getAfter(), Space.Location.TRY_RESOURCE_SUFFIX, p); } } J.Block tryBody = tryable.getBody(); JRightPadded elseBody = null; List> tryStatements = tryable.getBody().getPadding().getStatements(); if (tryStatements.get(tryStatements.size() - 1).getElement() instanceof J.Block) { tryBody = tryBody.getPadding().withStatements(tryStatements.subList(0, tryStatements.size() - 1)); elseBody = tryStatements.get(tryStatements.size() - 1); } visit(tryBody, p); visit(tryable.getCatches(), p); if (elseBody != null) { // padding is reversed for the `else` part because it's wrapped as though it were a normal statement, // so its extra padding (which acts as JLeftPadding) is stored in a JRightPadding visitSpace(elseBody.getAfter(), Location.LANGUAGE_EXTENSION, p); p.append("else"); visit(elseBody.getElement(), p); } visitLeftPadded("finally", tryable.getPadding().getFinally(), JLeftPadded.Location.TRY_FINALLY, p); afterSyntax(tryable, p); return tryable; } @Override public J visitUnary(J.Unary unary, PrintOutputCapture

p) { beforeSyntax(unary, Space.Location.UNARY_PREFIX, p); switch (unary.getOperator()) { case Not: p.append("not"); break; case Positive: p.append("+"); break; case Negative: p.append("-"); break; case Complement: p.append("~"); break; } visit(unary.getExpression(), p); afterSyntax(unary, p); return unary; } @Override public J visitVariable(J.VariableDeclarations.NamedVariable variable, PrintOutputCapture

p) { beforeSyntax(variable, Space.Location.VARIABLE_PREFIX, p); J.VariableDeclarations vd = getCursor().getParentTreeCursor().getValue(); JRightPadded padding = getCursor().getParent().getValue(); TypeTree type = vd.getTypeExpression(); if (type instanceof Py.SpecialParameter) { Py.SpecialParameter special = (Py.SpecialParameter) type; visit(special, p); type = special.getTypeHint(); } if (variable.getName().getSimpleName().isEmpty()) { visit(variable.getInitializer(), p); } else { if (vd.getVarargs() != null) { visitSpace(vd.getVarargs(), Location.VARARGS, p); p.append('*'); } if (vd.getMarkers().findFirst(KeywordArguments.class).isPresent()) { p.append("**"); } visit(variable.getName(), p); if (type != null) { visitSpace(padding.getAfter(), JRightPadded.Location.NAMED_VARIABLE.getAfterLocation(), p); p.append(':'); visit(type, p); } visitLeftPadded("=", variable.getPadding().getInitializer(), JLeftPadded.Location.VARIABLE_INITIALIZER, p); } afterSyntax(variable, p); return variable; } @Override public J visitVariableDeclarations(J.VariableDeclarations multiVariable, PrintOutputCapture

p) { beforeSyntax(multiVariable, Space.Location.VARIABLE_DECLARATIONS_PREFIX, p); visitSpace(Space.EMPTY, Space.Location.ANNOTATIONS, p); visit(multiVariable.getLeadingAnnotations(), p); for (J.Modifier m : multiVariable.getModifiers()) { visitModifier(m, p); } if (multiVariable.getMarkers().findFirst(KeywordOnlyArguments.class).isPresent()) { p.append("*"); } List> nodes = multiVariable.getPadding().getVariables(); for (int i = 0; i < nodes.size(); i++) { JRightPadded node = nodes.get(i); setCursor(new Cursor(getCursor(), node)); visit(node.getElement(), p); visitMarkers(node.getMarkers(), p); if (i < nodes.size() - 1) { p.append(","); } setCursor(getCursor().getParent()); } afterSyntax(multiVariable, p); return multiVariable; } @Override protected void printStatementTerminator(Statement s, PrintOutputCapture

p) { // optional semicolons are handled in `visitMarker()` } } @Override public M visitMarker(Marker marker, PrintOutputCapture

p) { return delegate.visitMarker(marker, p); } private static final UnaryOperator JAVA_MARKER_WRAPPER = out -> "/*~~" + out + (out.isEmpty() ? "" : "~~") + ">*/"; private void beforeSyntax(Py py, @SuppressWarnings("SameParameterValue") Space.Location loc, PrintOutputCapture

p) { beforeSyntax(py.getPrefix(), py.getMarkers(), loc, p); } private void beforeSyntax(Py py, PySpace.Location loc, PrintOutputCapture

p) { beforeSyntax(py.getPrefix(), py.getMarkers(), loc, p); } private void beforeSyntax(Space prefix, Markers markers, PySpace.@Nullable Location loc, PrintOutputCapture

p) { for (Marker marker : markers.getMarkers()) { p.append(p.getMarkerPrinter().beforePrefix(marker, new Cursor(getCursor(), marker), JAVA_MARKER_WRAPPER)); } if (loc != null) { visitSpace(prefix, loc, p); } visitMarkers(markers, p); for (Marker marker : markers.getMarkers()) { p.append(p.getMarkerPrinter().beforeSyntax(marker, new Cursor(getCursor(), marker), JAVA_MARKER_WRAPPER)); } } private void beforeSyntax(Space prefix, Markers markers, Space.@Nullable Location loc, PrintOutputCapture

p) { for (Marker marker : markers.getMarkers()) { p.append(p.getMarkerPrinter().beforePrefix(marker, new Cursor(getCursor(), marker), JAVA_MARKER_WRAPPER)); } if (loc != null) { visitSpace(prefix, loc, p); } visitMarkers(markers, p); for (Marker marker : markers.getMarkers()) { p.append(p.getMarkerPrinter().beforeSyntax(marker, new Cursor(getCursor(), marker), JAVA_MARKER_WRAPPER)); } } private void afterSyntax(Py py, PrintOutputCapture

p) { afterSyntax(py.getMarkers(), p); } private void afterSyntax(Markers markers, PrintOutputCapture

p) { for (Marker marker : markers.getMarkers()) { p.append(p.getMarkerPrinter().afterSyntax(marker, new Cursor(getCursor(), marker), JAVA_MARKER_WRAPPER)); } } @Override public Space visitSpace(Space space, PySpace.Location loc, PrintOutputCapture

p) { return delegate.visitSpace(space, Space.Location.LANGUAGE_EXTENSION, p); } @Override public Space visitSpace(Space space, Space.Location loc, PrintOutputCapture

p) { return delegate.visitSpace(space, loc, p); } protected void visitContainer(String before, @Nullable JContainer container, PyContainer.Location location, String suffixBetween, @Nullable String after, PrintOutputCapture

p) { if (container == null) { return; } visitSpace(container.getBefore(), location.getBeforeLocation(), p); p.append(before); visitRightPadded(container.getPadding().getElements(), location.getElementLocation(), suffixBetween, p); p.append(after == null ? "" : after); } private void visitLeftPadded(@SuppressWarnings("SameParameterValue") String s, JLeftPadded left, @SuppressWarnings({"SameParameterValue", "unused"}) PyLeftPadded.Location loc, PrintOutputCapture

p) { delegate.visitSpace(left.getBefore(), Location.LANGUAGE_EXTENSION, p); p.append(s); delegate.visitLeftPadded(left, JLeftPadded.Location.LANGUAGE_EXTENSION, p); } protected void visitRightPadded(List> nodes, PyRightPadded.Location location, String suffixBetween, PrintOutputCapture

p) { for (int i = 0; i < nodes.size(); i++) { JRightPadded node = nodes.get(i); visit(node.getElement(), p); visitSpace(node.getAfter(), location.getAfterLocation(), p); visitMarkers(node.getMarkers(), p); if (i < nodes.size() - 1) { p.append(suffixBetween); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy