From 33d8f7d42f9bd6749ab93171fad31289b0e2bc97 Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Fri, 2 Feb 2024 18:53:07 -0800 Subject: [PATCH] Add whitespace validation to RewriteTest --- .../main/java/org/openrewrite/SourceFile.java | 5 + .../internal/WhitespaceValidationService.java | 27 ++++ .../GroovyWhitespaceValidationService.java} | 41 ++---- .../groovy/internal/package-info.java | 19 +++ .../java/org/openrewrite/groovy/tree/G.java | 11 ++ .../openrewrite/groovy/tree/AssertTest.java | 4 +- .../groovy/tree/AssignmentTest.java | 4 +- .../openrewrite/groovy/tree/BinaryTest.java | 4 +- .../openrewrite/groovy/tree/BlockTest.java | 4 +- .../groovy/tree/ClassDeclarationTest.java | 4 +- .../groovy/tree/ClassExpressionTest.java | 4 +- .../groovy/tree/CompilationUnitTest.java | 4 +- .../groovy/tree/ConstructorTest.java | 4 +- .../org/openrewrite/groovy/tree/EnumTest.java | 4 +- .../groovy/tree/FieldAccessTest.java | 4 +- .../openrewrite/groovy/tree/ForLoopTest.java | 4 +- .../org/openrewrite/groovy/tree/IfTest.java | 4 +- .../openrewrite/groovy/tree/ImportTest.java | 4 +- .../openrewrite/groovy/tree/LabelsTest.java | 4 +- .../openrewrite/groovy/tree/LambdaTest.java | 4 +- .../org/openrewrite/groovy/tree/ListTest.java | 4 +- .../openrewrite/groovy/tree/LiteralTest.java | 4 +- .../openrewrite/groovy/tree/MapEntryTest.java | 4 +- .../groovy/tree/MethodDeclarationTest.java | 4 +- .../groovy/tree/MethodInvocationTest.java | 4 +- .../openrewrite/groovy/tree/RangeTest.java | 4 +- .../openrewrite/groovy/tree/SwitchTest.java | 4 +- .../groovy/tree/SynchronizedTest.java | 4 +- .../openrewrite/groovy/tree/TernaryTest.java | 4 +- .../openrewrite/groovy/tree/ThrowTest.java | 4 +- .../org/openrewrite/groovy/tree/TryTest.java | 4 +- .../openrewrite/groovy/tree/UnaryTest.java | 4 +- .../groovy/tree/VariableDeclarationsTest.java | 4 +- .../groovy/tree/WhileLoopTest.java | 4 +- .../openrewrite/java/tree/AnnotationTest.java | 4 +- .../format/RemoveTrailingWhitespaceTest.java | 2 + .../JavaWhitespaceValidationService.java | 38 ++++++ .../openrewrite/java/tree/JavaSourceFile.java | 20 ++- .../org/openrewrite/test/RewriteTest.java | 14 ++- .../XmlWhitespaceValidationService.java | 117 ++++++++++++++++++ .../java/org/openrewrite/xml/tree/Xml.java | 11 ++ 41 files changed, 326 insertions(+), 99 deletions(-) create mode 100644 rewrite-core/src/main/java/org/openrewrite/internal/WhitespaceValidationService.java rename rewrite-groovy/src/{test/java/org/openrewrite/groovy/GroovyParserTest.java => main/java/org/openrewrite/groovy/internal/GroovyWhitespaceValidationService.java} (59%) create mode 100644 rewrite-groovy/src/main/java/org/openrewrite/groovy/internal/package-info.java create mode 100644 rewrite-java/src/main/java/org/openrewrite/java/internal/JavaWhitespaceValidationService.java create mode 100644 rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlWhitespaceValidationService.java diff --git a/rewrite-core/src/main/java/org/openrewrite/SourceFile.java b/rewrite-core/src/main/java/org/openrewrite/SourceFile.java index cb626690210..5c7b4c5dc59 100644 --- a/rewrite-core/src/main/java/org/openrewrite/SourceFile.java +++ b/rewrite-core/src/main/java/org/openrewrite/SourceFile.java @@ -112,6 +112,11 @@ default

TreeVisitor> printer(Cursor cursor) { throw new UnsupportedOperationException("SourceFile implementations should override this method"); } + @Incubating(since = "8.2.0") + default T service(Class service) { + throw new UnsupportedOperationException("Service " + service + " not supported"); + } + /** * A measure of the size of the AST by count of number of AST nodes or some other similar measure. Because perfect referential * uniqueness is space inefficient, this weight will always be approximate and is best used for comparative size between two ASTs diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/WhitespaceValidationService.java b/rewrite-core/src/main/java/org/openrewrite/internal/WhitespaceValidationService.java new file mode 100644 index 00000000000..ef1a9fd9630 --- /dev/null +++ b/rewrite-core/src/main/java/org/openrewrite/internal/WhitespaceValidationService.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024 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.internal; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.TreeVisitor; + +/** + * Return a visitor suitable for use by the test framework to validate that whitespace contains no non-whitespace characters. + */ +public interface WhitespaceValidationService { + + TreeVisitor getVisitor(); +} diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/GroovyParserTest.java b/rewrite-groovy/src/main/java/org/openrewrite/groovy/internal/GroovyWhitespaceValidationService.java similarity index 59% rename from rewrite-groovy/src/test/java/org/openrewrite/groovy/GroovyParserTest.java rename to rewrite-groovy/src/main/java/org/openrewrite/groovy/internal/GroovyWhitespaceValidationService.java index 1bbd60f1df5..1d9569887c5 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/GroovyParserTest.java +++ b/rewrite-groovy/src/main/java/org/openrewrite/groovy/internal/GroovyWhitespaceValidationService.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2024 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. @@ -13,45 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.openrewrite.groovy; +package org.openrewrite.groovy.internal; -import lombok.EqualsAndHashCode; -import lombok.Value; import org.openrewrite.ExecutionContext; -import org.openrewrite.Recipe; import org.openrewrite.TreeVisitor; +import org.openrewrite.groovy.GroovyVisitor; import org.openrewrite.groovy.tree.GSpace; +import org.openrewrite.internal.StringUtils; +import org.openrewrite.internal.WhitespaceValidationService; import org.openrewrite.java.tree.Space; -import org.openrewrite.test.RecipeSpec; -import org.openrewrite.test.RewriteTest; - -public interface GroovyParserTest extends RewriteTest { - @Override - default void defaults(RecipeSpec spec) { - spec.recipe(new SpaceContainsOnlyWhitespace()); - } -} - -@Value -@EqualsAndHashCode(callSuper = false) -class SpaceContainsOnlyWhitespace extends Recipe { - - @Override - public String getDisplayName() { - return "Space contains only whitespace"; - } - - @Override - public String getDescription() { - return "Spaces containing non-whitespace characters is a common parser failure mode not otherwise detected."; - } +public class GroovyWhitespaceValidationService implements WhitespaceValidationService { @Override public TreeVisitor getVisitor() { - return new GroovyVisitor<>() { + return new GroovyVisitor() { @Override public Space visitSpace(Space space, GSpace.Location loc, ExecutionContext executionContext) { - if(!space.getWhitespace().isBlank()) { + if(!StringUtils.isBlank(space.getWhitespace())) { return space.withWhitespace("~~(non-whitespace)~~>" + space.getWhitespace() + "<~~"); } return space; @@ -59,12 +37,11 @@ public Space visitSpace(Space space, GSpace.Location loc, ExecutionContext execu @Override public Space visitSpace(Space space, Space.Location loc, ExecutionContext executionContext) { - if(!space.getWhitespace().isBlank()) { + if(!StringUtils.isBlank(space.getWhitespace())) { return space.withWhitespace("~~(non-whitespace)~~>" + space.getWhitespace() + "<~~"); } return space; } }; - } } diff --git a/rewrite-groovy/src/main/java/org/openrewrite/groovy/internal/package-info.java b/rewrite-groovy/src/main/java/org/openrewrite/groovy/internal/package-info.java new file mode 100644 index 00000000000..87c80ab28b5 --- /dev/null +++ b/rewrite-groovy/src/main/java/org/openrewrite/groovy/internal/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright 2024 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. + */ +@NonNullApi +package org.openrewrite.groovy.internal; + +import org.openrewrite.internal.lang.NonNullApi; diff --git a/rewrite-groovy/src/main/java/org/openrewrite/groovy/tree/G.java b/rewrite-groovy/src/main/java/org/openrewrite/groovy/tree/G.java index b6cb704d6fd..31b10b7e0e8 100644 --- a/rewrite-groovy/src/main/java/org/openrewrite/groovy/tree/G.java +++ b/rewrite-groovy/src/main/java/org/openrewrite/groovy/tree/G.java @@ -21,6 +21,8 @@ import org.openrewrite.*; import org.openrewrite.groovy.GroovyPrinter; import org.openrewrite.groovy.GroovyVisitor; +import org.openrewrite.groovy.internal.GroovyWhitespaceValidationService; +import org.openrewrite.internal.WhitespaceValidationService; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.internal.TypesInUse; import org.openrewrite.java.tree.*; @@ -136,6 +138,15 @@ public G.CompilationUnit withPackageDeclaration(Package packageDeclaration) { return getPadding().withPackageDeclaration(JRightPadded.withElement(this.packageDeclaration, packageDeclaration)); } + @SuppressWarnings("unchecked") + @Override + public T service(Class service) { + if(WhitespaceValidationService.class.getName().equals(service.getName())) { + return (T) new GroovyWhitespaceValidationService(); + } + return JavaSourceFile.super.service(service); + } + List> statements; public List getStatements() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssertTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssertTest.java index 9aac71cacb6..8312f0ade47 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssertTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssertTest.java @@ -17,12 +17,12 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyUnusedAssignment", "GrUnnecessarySemicolon"}) -class AssertTest implements GroovyParserTest { +class AssertTest implements RewriteTest { @Issue("https://github.com/openrewrite/rewrite/issues/3473") @Test diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssignmentTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssignmentTest.java index e82d1636ffb..8a15073a41b 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssignmentTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/AssignmentTest.java @@ -17,12 +17,12 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyUnusedAssignment", "GrUnnecessarySemicolon"}) -class AssignmentTest implements GroovyParserTest { +class AssignmentTest implements RewriteTest { @Test void concat() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BinaryTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BinaryTest.java index 6c38d187684..05d62e5b00f 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BinaryTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BinaryTest.java @@ -17,12 +17,12 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyUnusedAssignment", "GrUnnecessarySemicolon", "UnnecessaryQualifiedReference"}) -class BinaryTest implements GroovyParserTest { +class BinaryTest implements RewriteTest { @SuppressWarnings("GroovyConstantConditional") @Test diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BlockTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BlockTest.java index 908f35186ef..fcedd859f00 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BlockTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/BlockTest.java @@ -16,12 +16,12 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GrUnnecessarySemicolon") -class BlockTest implements GroovyParserTest { +class BlockTest implements RewriteTest { @Test void block() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassDeclarationTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassDeclarationTest.java index 74ae4259d57..122b5f862f4 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassDeclarationTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassDeclarationTest.java @@ -18,7 +18,7 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import org.openrewrite.java.tree.J; import org.openrewrite.java.tree.JavaType; import org.openrewrite.java.tree.TypeUtils; @@ -28,7 +28,7 @@ import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GrUnnecessaryPublicModifier") -class ClassDeclarationTest implements GroovyParserTest { +class ClassDeclarationTest implements RewriteTest { @Test void multipleClassDeclarationsInOneCompilationUnit() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassExpressionTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassExpressionTest.java index 68e71da97f5..1596d050290 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassExpressionTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ClassExpressionTest.java @@ -16,11 +16,11 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class ClassExpressionTest implements GroovyParserTest { +class ClassExpressionTest implements RewriteTest { @Test void classExpressions() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java index 808d4be3d18..23534b40563 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/CompilationUnitTest.java @@ -19,12 +19,12 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; import org.openrewrite.groovy.GroovyParser; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GroovyUnusedAssignment") -class CompilationUnitTest implements GroovyParserTest { +class CompilationUnitTest implements RewriteTest { @SuppressWarnings("GrPackage") @Test diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ConstructorTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ConstructorTest.java index 44cba6f354b..82b2df6321e 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ConstructorTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ConstructorTest.java @@ -16,11 +16,11 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -public class ConstructorTest implements GroovyParserTest { +public class ConstructorTest implements RewriteTest { @Test void inParens() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/EnumTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/EnumTest.java index 09c3bb0953c..438fc53d27f 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/EnumTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/EnumTest.java @@ -17,11 +17,11 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class EnumTest implements GroovyParserTest { +class EnumTest implements RewriteTest { @Disabled @Test diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/FieldAccessTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/FieldAccessTest.java index c850524ae92..b64c3f203dd 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/FieldAccessTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/FieldAccessTest.java @@ -16,11 +16,11 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class FieldAccessTest implements GroovyParserTest { +class FieldAccessTest implements RewriteTest { @Test void starAccess() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ForLoopTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ForLoopTest.java index 90552e7c611..a1432f73256 100755 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ForLoopTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ForLoopTest.java @@ -17,12 +17,12 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyEmptyStatementBody", "GroovyUnusedAssignment", "GrUnnecessarySemicolon", "GroovyUnnecessaryContinue"}) -class ForLoopTest implements GroovyParserTest { +class ForLoopTest implements RewriteTest { @Test void forLoopMultipleInit() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/IfTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/IfTest.java index 8faf7b5d036..4942076dff9 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/IfTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/IfTest.java @@ -16,12 +16,12 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyIfStatementWithIdenticalBranches", "GroovyConstantIfStatement", "GrUnnecessarySemicolon", "GroovyUnusedIncOrDec", "GroovyEmptyStatementBody"}) -class IfTest implements GroovyParserTest { +class IfTest implements RewriteTest { @Test void ifElse() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ImportTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ImportTest.java index 383a870200d..98927015c41 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ImportTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ImportTest.java @@ -16,13 +16,13 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import org.openrewrite.java.tree.Space; import static org.assertj.core.api.Assertions.assertThat; import static org.openrewrite.groovy.Assertions.groovy; -class ImportTest implements GroovyParserTest { +class ImportTest implements RewriteTest { @Test void classImport() { rewriteRun( diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LabelsTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LabelsTest.java index c4124e5dd9c..ab9536f8f6a 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LabelsTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LabelsTest.java @@ -16,11 +16,11 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class LabelsTest implements GroovyParserTest { +class LabelsTest implements RewriteTest { @Test void singleLabel() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LambdaTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LambdaTest.java index 549a73408ec..5ae92dce556 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LambdaTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LambdaTest.java @@ -17,12 +17,12 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GroovyUnusedAssignment") -class LambdaTest implements GroovyParserTest { +class LambdaTest implements RewriteTest { @Test void lambdaExpressionNoParens() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ListTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ListTest.java index 749373c5b7c..b42f9579fd4 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ListTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ListTest.java @@ -16,12 +16,12 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GroovyUnusedAssignment") -class ListTest implements GroovyParserTest { +class ListTest implements RewriteTest { @Test void listLiteral() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LiteralTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LiteralTest.java index f7339afc2d9..81207f15598 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LiteralTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/LiteralTest.java @@ -16,7 +16,7 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import org.openrewrite.java.tree.J; import org.openrewrite.java.tree.JavaType; import org.openrewrite.java.tree.TypeUtils; @@ -28,7 +28,7 @@ import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GroovyUnusedAssignment") -class LiteralTest implements GroovyParserTest { +class LiteralTest implements RewriteTest { @SuppressWarnings("GroovyConstantConditional") @Test diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MapEntryTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MapEntryTest.java index c56ea0c4391..4f5212baa16 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MapEntryTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MapEntryTest.java @@ -18,12 +18,12 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GroovyUnusedAssignment") -class MapEntryTest implements GroovyParserTest { +class MapEntryTest implements RewriteTest { @Test void mapEntryMethodArguments() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodDeclarationTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodDeclarationTest.java index d988eb54649..afee310c39a 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodDeclarationTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodDeclarationTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.tree.J; import org.openrewrite.java.tree.JavaType; @@ -27,7 +27,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.openrewrite.groovy.Assertions.groovy; -class MethodDeclarationTest implements GroovyParserTest { +class MethodDeclarationTest implements RewriteTest { @Test void methodDeclarationDeclaringType() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodInvocationTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodInvocationTest.java index 2d665c083b2..e22c1e08d46 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodInvocationTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/MethodInvocationTest.java @@ -17,11 +17,11 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class MethodInvocationTest implements GroovyParserTest { +class MethodInvocationTest implements RewriteTest { @Test void gradle() { rewriteRun( diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/RangeTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/RangeTest.java index de1c1766b8e..bdea313eb33 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/RangeTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/RangeTest.java @@ -16,11 +16,11 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class RangeTest implements GroovyParserTest { +class RangeTest implements RewriteTest { @Test void rangeExpression() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SwitchTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SwitchTest.java index 0d7dfc688c8..dcdc8e460b7 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SwitchTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SwitchTest.java @@ -16,14 +16,14 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import org.openrewrite.java.tree.J; import static org.assertj.core.api.Assertions.assertThat; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GrUnnecessarySemicolon", "GroovyVariableNotAssigned", "GroovyFallthrough"}) -class SwitchTest implements GroovyParserTest { +class SwitchTest implements RewriteTest { @Test void basicSwitch() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SynchronizedTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SynchronizedTest.java index 5ed03773fcc..4b5c61d2a2c 100755 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SynchronizedTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/SynchronizedTest.java @@ -16,12 +16,12 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GrUnnecessarySemicolon", "GroovySynchronizationOnVariableInitializedWithLiteral"}) -class SynchronizedTest implements GroovyParserTest { +class SynchronizedTest implements RewriteTest { @Test void synchronizedBlock() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TernaryTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TernaryTest.java index 9e56516e789..4a88cbfd2af 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TernaryTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TernaryTest.java @@ -16,11 +16,11 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class TernaryTest implements GroovyParserTest { +class TernaryTest implements RewriteTest { @SuppressWarnings("GroovyConstantConditional") @Test diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ThrowTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ThrowTest.java index efdd3c48883..2c71f9452d1 100755 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ThrowTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/ThrowTest.java @@ -16,11 +16,11 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; -class ThrowTest implements GroovyParserTest { +class ThrowTest implements RewriteTest { @Test void throwException() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TryTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TryTest.java index 6f453387a43..d580583b017 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TryTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/TryTest.java @@ -18,12 +18,12 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyUnusedCatchParameter", "GroovyUnusedAssignment"}) -class TryTest implements GroovyParserTest { +class TryTest implements RewriteTest { @Test void severalCatchBlocks() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/UnaryTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/UnaryTest.java index e1ee1d779e3..9679431bd63 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/UnaryTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/UnaryTest.java @@ -17,12 +17,12 @@ import org.junit.jupiter.api.Test; import org.openrewrite.Issue; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyUnusedAssignment", "GroovyUnusedIncOrDec", "GrUnnecessarySemicolon"}) -class UnaryTest implements GroovyParserTest { +class UnaryTest implements RewriteTest { @Test void format() { rewriteRun( diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/VariableDeclarationsTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/VariableDeclarationsTest.java index d08bfb62af5..b2ef1fb90a8 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/VariableDeclarationsTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/VariableDeclarationsTest.java @@ -20,7 +20,7 @@ import org.openrewrite.ExecutionContext; import org.openrewrite.Issue; import org.openrewrite.TreeVisitor; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.tree.J; import org.openrewrite.marker.SearchResult; @@ -33,7 +33,7 @@ import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings("GroovyUnusedAssignment") -class VariableDeclarationsTest implements GroovyParserTest { +class VariableDeclarationsTest implements RewriteTest { @Test void varKeyword() { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/WhileLoopTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/WhileLoopTest.java index c5b70f98aa8..7f3f8643806 100755 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/WhileLoopTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/tree/WhileLoopTest.java @@ -16,12 +16,12 @@ package org.openrewrite.groovy.tree; import org.junit.jupiter.api.Test; -import org.openrewrite.groovy.GroovyParserTest; +import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @SuppressWarnings({"GroovyEmptyStatementBody", "GroovyInfiniteLoopStatement"}) -class WhileLoopTest implements GroovyParserTest { +class WhileLoopTest implements RewriteTest { @Test void whileLoop() { diff --git a/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/AnnotationTest.java b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/AnnotationTest.java index 17855dffbfd..9a89ce50b27 100644 --- a/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/AnnotationTest.java +++ b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/AnnotationTest.java @@ -216,7 +216,7 @@ public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext p) import java.lang.annotation.*; public class TypeAnnotationTest { - public @Deprecated @A TypeAnnotationTests() { + public @Deprecated @A TypeAnnotationTest() { } @Target({ ElementType.TYPE, ElementType.TYPE_USE, ElementType.TYPE_PARAMETER }) @@ -228,7 +228,7 @@ public class TypeAnnotationTest { import java.lang.annotation.*; public class TypeAnnotationTest { - public @Deprecated TypeAnnotationTests() { + public @Deprecated TypeAnnotationTest() { } @Target({ ElementType.TYPE, ElementType.TYPE_USE, ElementType.TYPE_PARAMETER }) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/format/RemoveTrailingWhitespaceTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/format/RemoveTrailingWhitespaceTest.java index 3171ea49c58..8a4474a0fe3 100644 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/format/RemoveTrailingWhitespaceTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/format/RemoveTrailingWhitespaceTest.java @@ -15,6 +15,7 @@ */ package org.openrewrite.java.format; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.openrewrite.DocumentExample; import org.openrewrite.Issue; @@ -56,6 +57,7 @@ public void method(Test t) { ); } + @Disabled // TODO: This exposes bug around trailing commas in the parser @Issue("https://github.com/openrewrite/rewrite/issues/1053") @Test void doNotRemoveTrailingComma() { diff --git a/rewrite-java/src/main/java/org/openrewrite/java/internal/JavaWhitespaceValidationService.java b/rewrite-java/src/main/java/org/openrewrite/java/internal/JavaWhitespaceValidationService.java new file mode 100644 index 00000000000..4810e07cae0 --- /dev/null +++ b/rewrite-java/src/main/java/org/openrewrite/java/internal/JavaWhitespaceValidationService.java @@ -0,0 +1,38 @@ +/* + * Copyright 2024 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.java.internal; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.StringUtils; +import org.openrewrite.internal.WhitespaceValidationService; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.tree.Space; + +public class JavaWhitespaceValidationService implements WhitespaceValidationService { + @Override + public TreeVisitor getVisitor() { + return new JavaIsoVisitor() { + @Override + public Space visitSpace(Space space, Space.Location loc, ExecutionContext executionContext) { + if(!StringUtils.isBlank(space.getWhitespace())) { + return space.withWhitespace("~~(non-whitespace)~~>" + space.getWhitespace() + "<~~"); + } + return space; + } + }; + } +} diff --git a/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java b/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java index 25b77e67481..9320228d85c 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/tree/JavaSourceFile.java @@ -17,7 +17,9 @@ import org.openrewrite.Incubating; import org.openrewrite.SourceFile; +import org.openrewrite.internal.WhitespaceValidationService; import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.java.internal.JavaWhitespaceValidationService; import org.openrewrite.java.internal.TypesInUse; import org.openrewrite.java.service.AnnotationService; import org.openrewrite.java.service.AutoFormatService; @@ -27,7 +29,7 @@ import java.nio.file.Path; import java.util.List; -public interface JavaSourceFile extends J { +public interface JavaSourceFile extends J, SourceFile { TypesInUse getTypesInUse(); @Nullable @@ -54,18 +56,24 @@ public interface JavaSourceFile extends J { */ Path getSourcePath(); - SourceFile withSourcePath(Path path); + @SuppressWarnings("unchecked") + JavaSourceFile withSourcePath(Path path); + @SuppressWarnings("unchecked") + @Override @Incubating(since = "8.2.0") - default S service(Class service) { + default T service(Class service) { try { // use name indirection due to possibility of multiple class loaders being used if (ImportService.class.getName().equals(service.getName())) { - return service.getConstructor().newInstance(); + return (T) service.getConstructor().newInstance(); } else if (AutoFormatService.class.getName().equals(service.getName())) { - return service.getConstructor().newInstance(); + return (T) service.getConstructor().newInstance(); } else if (AnnotationService.class.getName().equals(service.getName())) { - return service.getConstructor().newInstance(); + return (T) service.getConstructor().newInstance(); + } else if (WhitespaceValidationService.class.getName().equals(service.getName())) { + // Only unit tests should need to use this service, so no classloading concerns + return (T) new JavaWhitespaceValidationService(); } else { throw new UnsupportedOperationException("Service " + service + " not supported"); } diff --git a/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java b/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java index 47c9ac30c64..1bbadf5d8c1 100644 --- a/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java +++ b/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java @@ -25,6 +25,7 @@ import org.openrewrite.internal.InMemoryDiffEntry; import org.openrewrite.internal.RecipeIntrospectionUtils; import org.openrewrite.internal.StringUtils; +import org.openrewrite.internal.WhitespaceValidationService; import org.openrewrite.internal.lang.NonNull; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.marker.Marker; @@ -303,7 +304,8 @@ default void rewriteRun(Consumer spec, SourceSpec... sourceSpecs) // Validate before source nextSpec.validateSource.accept(sourceFile, TypeValidation.before(testMethodSpec, testClassSpec)); - // Validate that printing a parsed AST yields the same source text + // Validate that printing the LST yields the same source text + // Validate that the LST whitespace do not contain any non-whitespace characters int j = 0; for (Parser.Input input : inputs.values()) { if (j++ == i && !(sourceFile instanceof Quark)) { @@ -316,6 +318,16 @@ default void rewriteRun(Consumer spec, SourceSpec... sourceSpecs) "parser implementation itself. Please open an issue to report this, providing a sample of the " + "code that generated this error for" ); + try { + WhitespaceValidationService service = sourceFile.service(WhitespaceValidationService.class); + SourceFile whitespaceValidated = (SourceFile) service.getVisitor().visit(sourceFile, ctx); + if(whitespaceValidated != null && whitespaceValidated != sourceFile) { + fail("Source file was parsed into an LST that contains non-whitespace characters in its whitespace. " + + "This is indicative of a bug in the parser. \n" + whitespaceValidated.printAll()); + } + } catch (UnsupportedOperationException e) { + // Language/parser does not provide whitespace validation and that's OK for now + } } } diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlWhitespaceValidationService.java b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlWhitespaceValidationService.java new file mode 100644 index 00000000000..d480db75679 --- /dev/null +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/internal/XmlWhitespaceValidationService.java @@ -0,0 +1,117 @@ +/* + * Copyright 2024 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.xml.internal; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.StringUtils; +import org.openrewrite.internal.WhitespaceValidationService; +import org.openrewrite.xml.XmlIsoVisitor; +import org.openrewrite.xml.tree.Xml; + +public class XmlWhitespaceValidationService implements WhitespaceValidationService { + @Override + public TreeVisitor getVisitor() { + return new XmlIsoVisitor() { + @Override + public Xml.Attribute visitAttribute(Xml.Attribute attribute, ExecutionContext executionContext) { + Xml.Attribute a = super.visitAttribute(attribute, executionContext); + a = a.withPrefix(withNonWhitespaceWarning(a.getPrefix())); + return a; + } + + @Override + public Xml.CharData visitCharData(Xml.CharData charData, ExecutionContext executionContext) { + Xml.CharData c = super.visitCharData(charData, executionContext); + c = c.withPrefix(withNonWhitespaceWarning(c.getPrefix())); + c = c.withAfterText(withNonWhitespaceWarning(c.getAfterText())); + return c; + } + + @Override + public Xml.Comment visitComment(Xml.Comment comment, ExecutionContext executionContext) { + Xml.Comment c = super.visitComment(comment, executionContext); + c = c.withPrefix(withNonWhitespaceWarning(c.getPrefix())); + return c; + } + + @Override + public Xml.DocTypeDecl visitDocTypeDecl(Xml.DocTypeDecl docTypeDecl, ExecutionContext executionContext) { + Xml.DocTypeDecl d = super.visitDocTypeDecl(docTypeDecl, executionContext); + d = d.withPrefix(withNonWhitespaceWarning(d.getPrefix())); + return d; + } + + // Document can start with a byte order marker, which is not technically whitespace + // There should probably be some special handling of this, but it hasn't caused a problem so ignoring for now +// @Override +// public Xml.Document visitDocument(Xml.Document document, ExecutionContext executionContext) { +// Xml.Document d = super.visitDocument(document, executionContext); +// d = d.withPrefix(withNonWhitespaceWarning(d.getPrefix())); +// return d; +// } + + @Override + public Xml.Element visitElement(Xml.Element element, ExecutionContext executionContext) { + Xml.Element e = super.visitElement(element, executionContext); + e = e.withPrefix(withNonWhitespaceWarning(e.getPrefix())); + return e; + } + + @Override + public Xml.Ident visitIdent(Xml.Ident ident, ExecutionContext executionContext) { + Xml.Ident i = super.visitIdent(ident, executionContext); + i = i.withPrefix(withNonWhitespaceWarning(i.getPrefix())); + return i; + } + + @Override + public Xml.XmlDecl visitXmlDecl(Xml.XmlDecl xmlDecl, ExecutionContext executionContext) { + Xml.XmlDecl x = super.visitXmlDecl(xmlDecl, executionContext); + x = x.withPrefix(withNonWhitespaceWarning(x.getPrefix())); + return x; + } + + @Override + public Xml.ProcessingInstruction visitProcessingInstruction(Xml.ProcessingInstruction processingInstruction, ExecutionContext executionContext) { + Xml.ProcessingInstruction p = super.visitProcessingInstruction(processingInstruction, executionContext); + p = p.withPrefix(withNonWhitespaceWarning(p.getPrefix())); + return p; + } + + @Override + public Xml.Prolog visitProlog(Xml.Prolog prolog, ExecutionContext executionContext) { + Xml.Prolog p = super.visitProlog(prolog, executionContext); + p = p.withPrefix(withNonWhitespaceWarning(p.getPrefix())); + return p; + } + + @Override + public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext executionContext) { + Xml.Tag t = super.visitTag(tag, executionContext); + t = t.withPrefix(withNonWhitespaceWarning(t.getPrefix())); + return t; + } + }; + } + + private static String withNonWhitespaceWarning(String s) { + if(StringUtils.isBlank(s)) { + return s; + } + return "~~(non-whitespace)~~>" + s + "<~~"; + } +} diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java index 9dbd8869b1c..b07dd105877 100755 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java @@ -20,12 +20,14 @@ import org.apache.commons.text.StringEscapeUtils; import org.intellij.lang.annotations.Language; import org.openrewrite.*; +import org.openrewrite.internal.WhitespaceValidationService; import org.openrewrite.internal.lang.Nullable; import org.openrewrite.marker.Markers; import org.openrewrite.xml.XmlParser; import org.openrewrite.xml.XmlVisitor; import org.openrewrite.xml.internal.WithPrefix; import org.openrewrite.xml.internal.XmlPrinter; +import org.openrewrite.xml.internal.XmlWhitespaceValidationService; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -156,6 +158,15 @@ public

Xml acceptXml(XmlVisitor

v, P p) { public

TreeVisitor> printer(Cursor cursor) { return new XmlPrinter<>(); } + + @SuppressWarnings("unchecked") + @Override + public T service(Class service) { + if(WhitespaceValidationService.class.getName().equals(service.getName())) { + return (T) new XmlWhitespaceValidationService(); + } + return SourceFile.super.service(service); + } } @Value