org.openrewrite.RefactorVisitorTest.kt Maven / Gradle / Ivy
Show all versions of rewrite-test Show documentation
/*
* Copyright 2020 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
import org.junit.jupiter.api.BeforeEach
import java.io.File
import java.lang.RuntimeException
/**
* Provides a standardized shape for test classes that exercise refactoring visitors to take.
*/
interface RefactorVisitorTest {
val visitors: Iterable>
get() = emptyList()
private fun assertBeforeAndAfterAreDifferent(before: String, after:String) {
if(before.trimIndent() == after.trimIndent()) {
throw RuntimeException(
"'before' and 'after' are equal. " +
"Looks like you're trying to assert that the visitors should make no changes. " +
"Instead of RefactorVisitorTest.assertRefactored(), use RefactorVisitorTest.assertUnchanged()")
}
}
/**
* Parse the "before" text, apply the visitors, assert that the result is "after"
*/
fun assertRefactored(
parser: Parser,
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: String,
after: String) {
assertBeforeAndAfterAreDifferent(before, after)
before.trimIndent()
.whenParsedBy(parser)
.whichDependsOn(*dependencies.toTypedArray())
.whenVisitedBy(visitors)
.let { visitorsMapped.fold(it) { acc, visitorMapping -> acc.whenVisitedByMapped(visitorMapping) } }
.let { visitorsMappedToMany.fold(it) { acc, visitorMapping -> acc.whenVisitedByMany(visitorMapping) } }
.isRefactoredTo(after.trimIndent())
}
/**
* Just like the other assertRefactored, but for when you want "after" to be lazily-evaluated.
* This is niche, for those situations where the result should depend on something figured out during refactoring
*/
fun assertRefactored(
parser: Parser,
visitors: Iterable>,
visitorsMapped: Iterable<(S) -> RefactorVisitor>,
visitorsMappedToMany: Iterable<(S) -> Iterable>>,
dependencies: List,
before: String,
after: () -> String) {
// To lazily evaluate after() and maintain consistency with the other versions of assertRefactored,
// curry in a trimIndent() and assertBeforeAndAfterAreDifferent() to be evaluated no sooner than after() is
val afterTrimmed: ()->String = {
val afterText = after().trimIndent()
assertBeforeAndAfterAreDifferent(before, afterText)
afterText
}
before.trimIndent()
.whenParsedBy(parser)
.whichDependsOn(*dependencies.toTypedArray())
.whenVisitedBy(visitors)
.let { visitorsMapped.fold(it) { acc, visitorMapping -> acc.whenVisitedByMapped(visitorMapping) } }
.let { visitorsMappedToMany.fold(it) { acc, visitorMapping -> acc.whenVisitedByMany(visitorMapping) } }
.isRefactoredTo(afterTrimmed)
}
/**
* Parse the "before" text, apply the visitors, assert that there are no changes
*/
fun assertUnchanged(parser: Parser,
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: String) {
before.trimIndent()
.whenParsedBy(parser)
.whichDependsOn(*dependencies.toTypedArray())
.whenVisitedBy(visitors)
.let { visitorsMapped.fold(it) { acc, visitorMapping -> acc.whenVisitedByMapped(visitorMapping) } }
.let { visitorsMappedToMany.fold(it) { acc, visitorMapping -> acc.whenVisitedByMany(visitorMapping) } }
.isUnchanged
}
/**
* Parse the "before" text, apply the visitors, assert that the result is "after"
*/
fun assertRefactored(
parser: Parser,
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: File,
after: String) {
assertBeforeAndAfterAreDifferent(before.readText(), after)
before.toPath()
.whenParsedBy(parser)
.whichDependsOn(*dependencies.map { it.toPath() }.toTypedArray())
.whenVisitedBy(visitors)
.let { visitorsMapped.fold(it) { acc, visitorMapping -> acc.whenVisitedByMapped(visitorMapping) } }
.let { visitorsMappedToMany.fold(it) { acc, visitorMapping -> acc.whenVisitedByMany(visitorMapping) } }
.isRefactoredTo(after.trimIndent())
}
/**
* Parse the "before" text, apply the visitors, assert that there are no changes
*/
fun assertUnchanged(
parser: Parser,
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: File) {
before.toPath()
.whenParsedBy(parser)
.whichDependsOn(*dependencies.map { it.toPath() }.toTypedArray())
.whenVisitedBy(visitors)
.let { visitorsMapped.fold(it) { acc, visitorMapping -> acc.whenVisitedByMapped(visitorMapping) } }
.let { visitorsMappedToMany.fold(it) { acc, visitorMapping -> acc.whenVisitedByMany(visitorMapping) } }
.isUnchanged
}
}
interface RefactorVisitorTestForParser : RefactorVisitorTest {
val parser: Parser
fun assertRefactored(
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: String,
after: String) {
return assertRefactored(parser, visitors, visitorsMapped, visitorsMappedToMany, dependencies, before, after)
}
fun assertRefactored(
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: String,
after: ()->String) {
return assertRefactored(parser, visitors, visitorsMapped, visitorsMappedToMany, dependencies, before, after)
}
fun assertRefactored(
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: File,
after: String) {
return assertRefactored(parser, visitors, visitorsMapped, visitorsMappedToMany, dependencies, before, after)
}
fun assertUnchanged(
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: String
) {
return assertUnchanged(parser, visitors, visitorsMapped, visitorsMappedToMany, dependencies, before)
}
fun assertUnchanged(
visitors: Iterable> = this.visitors,
visitorsMapped: Iterable<(S) -> RefactorVisitor> = emptyList(),
visitorsMappedToMany: Iterable<(S) -> Iterable>> = emptyList(),
dependencies: List = listOf(),
before: File
) {
return assertUnchanged(parser, visitors, visitorsMapped, visitorsMappedToMany, dependencies, before)
}
@BeforeEach
fun beforeEach() {
parser.reset()
}
}