From 10052ef9f56b68f803dfdfe5fa24a912ba030679 Mon Sep 17 00:00:00 2001 From: Kun Li <122563761+kunli2@users.noreply.github.com> Date: Tue, 9 Jan 2024 02:54:44 -0800 Subject: [PATCH] Fix Semi-colon on inline methods after property declaration disappears (#585) --- .../org/openrewrite/kotlin/KotlinVisitor.java | 2 +- .../kotlin/format/SpacesVisitor.java | 12 +++---- .../kotlin/internal/KotlinPrinter.java | 5 +++ .../internal/KotlinTreeParserVisitor.java | 16 ++++++++-- .../java/org/openrewrite/kotlin/tree/K.java | 31 ++++++++++++++++--- .../kotlin/tree/VariableDeclarationTest.java | 14 +++++++++ 6 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/openrewrite/kotlin/KotlinVisitor.java b/src/main/java/org/openrewrite/kotlin/KotlinVisitor.java index 817357d8e..cfa347835 100644 --- a/src/main/java/org/openrewrite/kotlin/KotlinVisitor.java +++ b/src/main/java/org/openrewrite/kotlin/KotlinVisitor.java @@ -289,7 +289,7 @@ public J visitProperty(K.Property property, P p) { pr = (K.Property) temp; } - pr = pr.withVariableDeclarations(visitAndCast(pr.getVariableDeclarations(), p)); + pr = pr.getPadding().withVariableDeclarations(visitRightPadded(pr.getPadding().getVariableDeclarations(), p)); pr = pr.getPadding().withReceiver(visitRightPadded(pr.getPadding().getReceiver(), p)); pr = pr.withAccessors(visitContainer(pr.getAccessors(), p)); return pr; diff --git a/src/main/java/org/openrewrite/kotlin/format/SpacesVisitor.java b/src/main/java/org/openrewrite/kotlin/format/SpacesVisitor.java index 08eed4d0d..d7370e773 100644 --- a/src/main/java/org/openrewrite/kotlin/format/SpacesVisitor.java +++ b/src/main/java/org/openrewrite/kotlin/format/SpacesVisitor.java @@ -352,13 +352,13 @@ public K.Property visitProperty(K.Property property, P p) { if (prop.getPadding().getReceiver() != null) { prop = prop.getPadding().withReceiver(prop.getPadding().getReceiver().withAfter(updateSpace(prop.getPadding().getReceiver().getAfter(), false))); } + if (prop.getVariableDeclarations() != null && !prop.getVariableDeclarations().getVariables().isEmpty()) { - prop = prop.withVariableDeclarations( - prop.getVariableDeclarations().withVariables( - ListUtils.mapFirst(prop.getVariableDeclarations().getVariables(), - v -> spaceBefore(v, false)) - ) - ); + List variables = ListUtils.mapFirst(prop.getVariableDeclarations().getVariables(), + v -> spaceBefore(v, false)); + JRightPadded rp = prop.getPadding().getVariableDeclarations(); + rp = rp.withElement(rp.getElement().withVariables(variables)); + prop = prop.getPadding().withVariableDeclarations(rp); } return prop; } diff --git a/src/main/java/org/openrewrite/kotlin/internal/KotlinPrinter.java b/src/main/java/org/openrewrite/kotlin/internal/KotlinPrinter.java index 5c3a99973..b1872f7f1 100755 --- a/src/main/java/org/openrewrite/kotlin/internal/KotlinPrinter.java +++ b/src/main/java/org/openrewrite/kotlin/internal/KotlinPrinter.java @@ -388,6 +388,11 @@ public J visitProperty(K.Property property, PrintOutputCapture

p) { delegate.visitContainer("where", property.getTypeConstraints().getPadding().getConstraints(), JContainer.Location.TYPE_PARAMETERS, ",", "", p); } + visitSpace(property.getPadding().getVariableDeclarations().getAfter(), Space.Location.VARIABLE_INITIALIZER, p); + if (property.getPadding().getVariableDeclarations().getMarkers().findFirst(Semicolon.class).isPresent()) { + p.append(";"); + } + visitContainer(property.getAccessors(), p); afterSyntax(property, p); return property; diff --git a/src/main/java/org/openrewrite/kotlin/internal/KotlinTreeParserVisitor.java b/src/main/java/org/openrewrite/kotlin/internal/KotlinTreeParserVisitor.java index daa7405b5..1a467ce25 100644 --- a/src/main/java/org/openrewrite/kotlin/internal/KotlinTreeParserVisitor.java +++ b/src/main/java/org/openrewrite/kotlin/internal/KotlinTreeParserVisitor.java @@ -2959,7 +2959,19 @@ public J visitProperty(KtProperty property, ExecutionContext data) { if (!ktPropertyAccessors.isEmpty() || receiver != null || typeConstraints != null) { List> accessors = new ArrayList<>(ktPropertyAccessors.size()); - for (KtPropertyAccessor ktPropertyAccessor : ktPropertyAccessors) { + Space beforeSemiColon = Space.EMPTY; + Markers rpMarkers = Markers.EMPTY; + for (int i = 0; i < ktPropertyAccessors.size(); i++) { + KtPropertyAccessor ktPropertyAccessor = ktPropertyAccessors.get(i); + + if (i == 0) { + PsiElement maybeSemiColon = PsiTreeUtil.findSiblingBackward(ktPropertyAccessor, KtTokens.SEMICOLON, null); + if (maybeSemiColon != null) { + beforeSemiColon = prefix(maybeSemiColon); + rpMarkers = rpMarkers.addIfAbsent(new Semicolon(randomId())); + } + } + J.MethodDeclaration accessor = (J.MethodDeclaration) ktPropertyAccessor.accept(this, data); accessors.add(maybeTrailingSemicolonInternal(accessor, ktPropertyAccessor)); } @@ -2969,7 +2981,7 @@ public J visitProperty(KtProperty property, ExecutionContext data) { deepPrefix(property), markers, typeParameters, - variableDeclarations.withPrefix(Space.EMPTY), + padRight(variableDeclarations.withPrefix(Space.EMPTY), beforeSemiColon, rpMarkers), typeConstraints, JContainer.build(accessors), receiver diff --git a/src/main/java/org/openrewrite/kotlin/tree/K.java b/src/main/java/org/openrewrite/kotlin/tree/K.java index f81cb2da3..d12f147cb 100644 --- a/src/main/java/org/openrewrite/kotlin/tree/K.java +++ b/src/main/java/org/openrewrite/kotlin/tree/K.java @@ -1504,7 +1504,7 @@ public List getTypeParameters() { return typeParameters == null ? null : typeParameters.getElements(); } - J.VariableDeclarations variableDeclarations; + JRightPadded paddedVariableDeclarations; @Nullable TypeConstraints typeConstraints; @@ -1523,7 +1523,8 @@ public Property(UUID id, Space prefix, Markers markers, JContainer typeParameters, - VariableDeclarations variableDeclarations, + @Nullable JRightPadded paddedVariableDeclarations, + @Nullable VariableDeclarations variableDeclarations, @Nullable K.TypeConstraints typeConstraints, @Nullable @JsonProperty("getter") J.MethodDeclaration getter, @Nullable @JsonProperty("setter") J.MethodDeclaration setter, @@ -1535,7 +1536,14 @@ public Property(UUID id, this.prefix = prefix; this.markers = markers; this.typeParameters = typeParameters; - this.variableDeclarations = variableDeclarations; + + if (variableDeclarations != null) { + // from old LST + this.paddedVariableDeclarations = new JRightPadded<>(variableDeclarations, Space.EMPTY, Markers.EMPTY); + } else { + this.paddedVariableDeclarations = requireNonNull(paddedVariableDeclarations); + } + this.typeConstraints = typeConstraints; if (getter != null || setter != null || isSetterFirst != null) { @@ -1561,6 +1569,10 @@ public Property(UUID id, this.receiver = receiver; } + public J.VariableDeclarations getVariableDeclarations() { + return paddedVariableDeclarations.getElement(); + } + @Nullable public Expression getReceiver() { return receiver == null ? null : receiver.getElement(); @@ -1602,6 +1614,15 @@ public String toString() { public static class Padding { private final Property t; + public JRightPadded getVariableDeclarations() { + return t.paddedVariableDeclarations; + } + + public Property withVariableDeclarations(JRightPadded variableDeclarations) { + return t.paddedVariableDeclarations == variableDeclarations ? t : new Property(t.id, t.prefix, t.markers, t.typeParameters, + variableDeclarations, t.typeConstraints, t.accessors, t.receiver); + } + @Nullable public JContainer getTypeParameters() { return t.typeParameters; @@ -1609,7 +1630,7 @@ public JContainer getTypeParameters() { public Property withTypeParameters(@Nullable JContainer typeParameters) { return t.typeParameters == typeParameters ? t : new Property(t.id, t.prefix, t.markers, typeParameters, - t.variableDeclarations, t.typeConstraints, t.accessors, t.receiver); + t.paddedVariableDeclarations, t.typeConstraints, t.accessors, t.receiver); } @Nullable @@ -1620,7 +1641,7 @@ public JRightPadded getReceiver() { @Nullable public Property withReceiver(@Nullable JRightPadded receiver) { return t.receiver == receiver ? t : new Property(t.id, t.prefix, t.markers, t.typeParameters, - t.variableDeclarations, t.typeConstraints, t.accessors, receiver); + t.paddedVariableDeclarations, t.typeConstraints, t.accessors, receiver); } } } diff --git a/src/test/java/org/openrewrite/kotlin/tree/VariableDeclarationTest.java b/src/test/java/org/openrewrite/kotlin/tree/VariableDeclarationTest.java index 499e0e354..bbab81dcc 100644 --- a/src/test/java/org/openrewrite/kotlin/tree/VariableDeclarationTest.java +++ b/src/test/java/org/openrewrite/kotlin/tree/VariableDeclarationTest.java @@ -520,6 +520,20 @@ class Test { ); } + @Issue("https://github.com/openrewrite/rewrite-kotlin/issues/560") + @Test + void accessorAfterTrailingSemiColon() { + rewriteRun( + kotlin( + """ + class Test { + var n: Int = 0 ; protected set + } + """ + ) + ); + } + @Issue("https://github.com/openrewrite/rewrite-kotlin/issues/135") @Test void checkNonNull() {