org.openrewrite.test.SourceSpec Maven / Gradle / Ivy
Show all versions of rewrite-test Show documentation
/*
* Copyright 2022 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.test;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.jspecify.annotations.Nullable;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Parser;
import org.openrewrite.SourceFile;
import org.openrewrite.internal.ThrowingConsumer;
import org.openrewrite.marker.Marker;
import org.openrewrite.marker.Markers;
import org.openrewrite.test.internal.ThrowingUnaryOperator;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.function.UnaryOperator;
@RequiredArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Getter
public class SourceSpec implements SourceSpecs {
@EqualsAndHashCode.Include
final UUID id = UUID.randomUUID();
final Class sourceFileType;
@Nullable
final String dsl;
final Parser.Builder parser;
@Nullable
final String before;
@Nullable
UnaryOperator after;
/**
* Apply a function to each SourceFile (before and after) recipe execution.
* Useful for validating the AST or its metadata.
*/
final ValidateSource validateSource;
public interface ValidateSource {
ValidateSource noop = (sourceFile, typeValidation) -> sourceFile;
SourceFile accept(SourceFile sourceFile, TypeValidation typeValidation);
}
final ThrowingConsumer customizeExecutionContext;
public SourceSpec(Class sourceFileType, @Nullable String dsl,
Parser.Builder parser, @Nullable String before, @Nullable UnaryOperator after) {
this.sourceFileType = sourceFileType;
this.dsl = dsl;
this.parser = parser;
this.before = before;
this.after = after;
this.validateSource = ValidateSource.noop;
this.customizeExecutionContext = (ctx) -> {
};
}
protected Path dir = Paths.get("");
@Nullable
protected Path sourcePath;
protected Markers markers = Markers.EMPTY;
public List getMarkers() {
return markers.getMarkers();
}
@Nullable
Path getSourcePath() {
return sourcePath == null ? null : dir.resolve(sourcePath);
}
protected ThrowingUnaryOperator beforeRecipe = t -> t;
protected ThrowingConsumer afterRecipe = t -> {
};
protected boolean skip = false;
protected boolean noTrim = false;
/**
* @param sourcePath The source path before the recipe is run.
* @return This source spec.
*/
public SourceSpec path(Path sourcePath) {
this.sourcePath = sourcePath;
return this;
}
/**
* @param sourcePath The source path before the recipe is run.
* @return This source spec.
*/
public SourceSpec path(String sourcePath) {
this.sourcePath = Paths.get(sourcePath);
return this;
}
public SourceSpec markers(Marker... markers) {
for (Marker marker : markers) {
this.markers = this.markers.computeByType(marker, (existing, replacement) -> existing);
}
return this;
}
/**
* Apply a function to specify what the after text of a recipe run should be.
*
* @param after A unary operator that takes the actual result and returns the expected result.
* The actual result can be used to pull out things that are dynamic, like timestamps or
* dependency versions that may change between runs.
* @return This source spec.
*/
public SourceSpec after(UnaryOperator after) {
this.after = after;
return this;
}
public SourceSpec mapBeforeRecipe(ThrowingUnaryOperator beforeRecipe) {
this.beforeRecipe = beforeRecipe;
return this;
}
public SourceSpec beforeRecipe(ThrowingConsumer beforeRecipe) {
return mapBeforeRecipe(t -> {
beforeRecipe.accept(t);
return t;
});
}
public SourceSpec afterRecipe(ThrowingConsumer afterRecipe) {
this.afterRecipe = afterRecipe;
return this;
}
public SourceSpec skip() {
return skip(true);
}
public SourceSpec skip(@Nullable Boolean skip) {
this.skip = Boolean.TRUE.equals(skip);
return this;
}
public SourceSpec noTrim() {
return noTrim(true);
}
public SourceSpec noTrim(@Nullable Boolean noTrim) {
this.noTrim = Boolean.TRUE.equals(noTrim);
return this;
}
@Override
public Iterator> iterator() {
return new Iterator>() {
boolean next = true;
@Override
public boolean hasNext() {
return next;
}
@Override
public SourceSpec> next() {
next = false;
return SourceSpec.this;
}
};
}
}