Skip to content

Commit

Permalink
Fix assorted groovy parsing errors around labels, parentheses, and wh…
Browse files Browse the repository at this point in the history
…itespace.

Added verification that only whitespace is present within Spaces within parser tests.

Parentheses fixes:
* Type casts inside parentheses
* Constructor invocations inside parentheses

Label fixes:
* Labeled For loops
* Labeled For-each loops

Other whitespace:
* Quoted method declarations
* Semicolon-terminated statements inside switch
* Numeric literals that use 'L', 'd', or 'f' suffixes to specify their type left the specifier in whitespace
  • Loading branch information
sambsnyd committed Feb 2, 2024
1 parent 53f421e commit 6963029
Show file tree
Hide file tree
Showing 33 changed files with 458 additions and 294 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -15,108 +15,56 @@
*/
package org.openrewrite.groovy;

import org.junit.jupiter.api.Test;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.groovy.tree.GSpace;
import org.openrewrite.java.tree.Space;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.groovy.Assertions.groovy;
public interface GroovyParserTest extends RewriteTest {
@Override
default void defaults(RecipeSpec spec) {
spec.recipe(new SpaceContainsOnlyWhitespace());
}
}

public class GroovyParserTest implements RewriteTest {
@Value
@EqualsAndHashCode(callSuper = false)
class SpaceContainsOnlyWhitespace extends Recipe {

@Test
void jenkinsfile() {
// the Jenkinsfile from spring-projects/spring-data-release
rewriteRun(
groovy(
"""
def p = [:]
node {
checkout scm
p = readProperties interpolate: true, file: 'ci/release.properties'
}
pipeline {
agent none
triggers {
pollSCM 'H/10 * * * *'
}
options {
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '14'))
}
stages {
stage('Build the Spring Data release tools container') {
when {
anyOf {
changeset 'ci/Dockerfile'
changeset 'ci/java-tools.properties'
}
}
agent {
label 'data'
}
steps {
script {
def image = docker.build("springci/spring-data-release-tools:0.12", "ci")
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
image.push()
}
}
}
}
stage('Ship It') {
when {
branch 'release'
}
agent {
docker {
image 'springci/spring-data-release-tools:0.12'
}
}
options { timeout(time: 4, unit: 'HOURS') }
environment {
GITHUB = credentials('3a20bcaa-d8ad-48e3-901d-9fbc941376ee')
GITHUB_TOKEN = credentials('7b3ebbea-7001-479b-8578-b8c464dab973')
REPO_SPRING_IO = credentials('repo_spring_io-jenkins-release-token')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
STAGING_PROFILE_ID = credentials('spring-data-release-deployment-maven-central-staging-profile-id')
MAVEN_SIGNING_KEY = credentials('spring-gpg-private-key')
MAVEN_SIGNING_KEY_PASSWORD = credentials('spring-gpg-passphrase')
GIT_SIGNING_KEY = credentials('spring-gpg-github-private-key-jenkins')
GIT_SIGNING_KEY_PASSWORD = credentials('spring-gpg-github-passphrase-jenkins')
SONATYPE = credentials('oss-login')
}
steps {
script {
sh "ci/build-spring-data-release-cli.bash"
sh "ci/build-and-distribute.bash ${p['release.version']}"
slackSend(
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
channel: '#spring-data-dev',
message: (currentBuild.currentResult == 'SUCCESS')
? "`${env.BUILD_URL}` - Build and distribute ${p['release.version']} passed! Release the build (if needed)."
: "`${env.BUILD_URL}` - Build and distribute ${p['release.version']} failed!")
}
}
}
@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.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return new GroovyVisitor<>() {
@Override
public Space visitSpace(Space space, GSpace.Location loc, ExecutionContext executionContext) {
if(!space.getWhitespace().isBlank()) {
return space.withWhitespace("~~(non-whitespace)~~>" + space.getWhitespace() + "<~~");
}
post {
changed {
script {
slackSend(
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
channel: '#spring-data-dev',
message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\\n${env.BUILD_URL}")
emailext(
subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}",
mimeType: 'text/html',
recipientProviders: [[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']],
body: "<a href=\\"${env.BUILD_URL}\\">${currentBuild.fullDisplayName} is reported as ${currentBuild.currentResult}</a>")
}
}
return space;
}

@Override
public Space visitSpace(Space space, Space.Location loc, ExecutionContext executionContext) {
if(!space.getWhitespace().isBlank()) {
return space.withWhitespace("~~(non-whitespace)~~>" + space.getWhitespace() + "<~~");
}
}
""",
spec -> spec.path("Jenkinsfile")
)
);
return space;
}
};

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.groovy;

import org.junit.jupiter.api.Test;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.groovy.Assertions.groovy;

public class JenkinsFileTest implements RewriteTest {

@Test
void jenkinsfile() {
// the Jenkinsfile from spring-projects/spring-data-release
rewriteRun(
groovy(
"""
def p = [:]
node {
checkout scm
p = readProperties interpolate: true, file: 'ci/release.properties'
}
pipeline {
agent none
triggers {
pollSCM 'H/10 * * * *'
}
options {
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '14'))
}
stages {
stage('Build the Spring Data release tools container') {
when {
anyOf {
changeset 'ci/Dockerfile'
changeset 'ci/java-tools.properties'
}
}
agent {
label 'data'
}
steps {
script {
def image = docker.build("springci/spring-data-release-tools:0.12", "ci")
docker.withRegistry('', 'hub.docker.com-springbuildmaster') {
image.push()
}
}
}
}
stage('Ship It') {
when {
branch 'release'
}
agent {
docker {
image 'springci/spring-data-release-tools:0.12'
}
}
options { timeout(time: 4, unit: 'HOURS') }
environment {
GITHUB = credentials('3a20bcaa-d8ad-48e3-901d-9fbc941376ee')
GITHUB_TOKEN = credentials('7b3ebbea-7001-479b-8578-b8c464dab973')
REPO_SPRING_IO = credentials('repo_spring_io-jenkins-release-token')
ARTIFACTORY = credentials('02bd1690-b54f-4c9f-819d-a77cb7a9822c')
STAGING_PROFILE_ID = credentials('spring-data-release-deployment-maven-central-staging-profile-id')
MAVEN_SIGNING_KEY = credentials('spring-gpg-private-key')
MAVEN_SIGNING_KEY_PASSWORD = credentials('spring-gpg-passphrase')
GIT_SIGNING_KEY = credentials('spring-gpg-github-private-key-jenkins')
GIT_SIGNING_KEY_PASSWORD = credentials('spring-gpg-github-passphrase-jenkins')
SONATYPE = credentials('oss-login')
}
steps {
script {
sh "ci/build-spring-data-release-cli.bash"
sh "ci/build-and-distribute.bash ${p['release.version']}"
slackSend(
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
channel: '#spring-data-dev',
message: (currentBuild.currentResult == 'SUCCESS')
? "`${env.BUILD_URL}` - Build and distribute ${p['release.version']} passed! Release the build (if needed)."
: "`${env.BUILD_URL}` - Build and distribute ${p['release.version']} failed!")
}
}
}
}
post {
changed {
script {
slackSend(
color: (currentBuild.currentResult == 'SUCCESS') ? 'good' : 'danger',
channel: '#spring-data-dev',
message: "${currentBuild.fullDisplayName} - `${currentBuild.currentResult}`\\n${env.BUILD_URL}")
emailext(
subject: "[${currentBuild.fullDisplayName}] ${currentBuild.currentResult}",
mimeType: 'text/html',
recipientProviders: [[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']],
body: "<a href=\\"${env.BUILD_URL}\\">${currentBuild.fullDisplayName} is reported as ${currentBuild.currentResult}</a>")
}
}
}
}
""",
spec -> spec.path("Jenkinsfile")
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

import org.junit.jupiter.api.Test;
import org.openrewrite.Issue;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.groovy.GroovyParserTest;

import static org.openrewrite.groovy.Assertions.groovy;

@SuppressWarnings({"GroovyUnusedAssignment", "GrUnnecessarySemicolon"})
class AssertTest implements RewriteTest {
class AssertTest implements GroovyParserTest {

@Issue("https://github.com/openrewrite/rewrite/issues/3473")
@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

import org.junit.jupiter.api.Test;
import org.openrewrite.Issue;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.groovy.GroovyParserTest;

import static org.openrewrite.groovy.Assertions.groovy;

@SuppressWarnings({"GroovyUnusedAssignment", "GrUnnecessarySemicolon"})
class AssignmentTest implements RewriteTest {
class AssignmentTest implements GroovyParserTest {

@Test
void concat() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

import org.junit.jupiter.api.Test;
import org.openrewrite.Issue;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.groovy.GroovyParserTest;

import static org.openrewrite.groovy.Assertions.groovy;

@SuppressWarnings({"GroovyUnusedAssignment", "GrUnnecessarySemicolon", "UnnecessaryQualifiedReference"})
class BinaryTest implements RewriteTest {
class BinaryTest implements GroovyParserTest {

@SuppressWarnings("GroovyConstantConditional")
@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
package org.openrewrite.groovy.tree;

import org.junit.jupiter.api.Test;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.groovy.GroovyParserTest;

import static org.openrewrite.groovy.Assertions.groovy;

@SuppressWarnings("GrUnnecessarySemicolon")
class BlockTest implements RewriteTest {
class BlockTest implements GroovyParserTest {

@Test
void block() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,26 @@ def foo(String[][] a) {
)
);
}

@Test
void groovyCastAndInvokeMethod() {
rewriteRun(
groovy(
"""
( "" as String ).toString()
"""
)
);
}

@Test
void javaCastAndInvokeMethod() {
rewriteRun(
groovy(
"""
( (String) "" ).toString()
"""
)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@

import org.junit.jupiter.api.Test;
import org.openrewrite.Issue;
import org.openrewrite.groovy.GroovyParserTest;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.TypeUtils;
import org.openrewrite.test.RewriteTest;

import static java.util.Objects.requireNonNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.openrewrite.groovy.Assertions.groovy;

@SuppressWarnings("GrUnnecessaryPublicModifier")
class ClassDeclarationTest implements RewriteTest {
class ClassDeclarationTest implements GroovyParserTest {

@Test
void multipleClassDeclarationsInOneCompilationUnit() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
package org.openrewrite.groovy.tree;

import org.junit.jupiter.api.Test;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.groovy.GroovyParserTest;

import static org.openrewrite.groovy.Assertions.groovy;

class ClassExpressionTest implements RewriteTest {
class ClassExpressionTest implements GroovyParserTest {

@Test
void classExpressions() {
Expand Down
Loading

0 comments on commit 6963029

Please sign in to comment.