org.openrewrite.hcl.MoveContentToFile Maven / Gradle / Ivy
Show all versions of rewrite-hcl 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.hcl;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.jspecify.annotations.Nullable;
import org.openrewrite.*;
import org.openrewrite.hcl.tree.BodyContent;
import org.openrewrite.hcl.tree.Hcl;
import org.openrewrite.hcl.tree.Space;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.Collections;
@Value
@EqualsAndHashCode(callSuper = false)
public class MoveContentToFile extends ScanningRecipe {
@Option(displayName = "Content path",
description = "A JSONPath expression specifying the block to move.",
example = "$.provider")
String contentPath;
@Option(displayName = "From path",
description = "The source path of the file from which content is being moved.",
example = "from.tf")
String fromPath;
@Option(displayName = "To path",
description = "The source path of the file to move the content to.",
example = "to.tf")
String destinationPath;
@Override
public String getDisplayName() {
return "Move content to another file";
}
@Override
public String getDescription() {
return "Move content to another HCL file, deleting it in the original file.";
}
static class Scanned {
@Nullable
BodyContent toMove;
boolean destinationExists;
}
@Override
public Scanned getInitialValue(ExecutionContext ctx) {
return new Scanned();
}
@Override
public TreeVisitor, ExecutionContext> getScanner(Scanned acc) {
JsonPathMatcher pathMatcher = new JsonPathMatcher(contentPath);
Path from = Paths.get(fromPath);
Path dest = Paths.get(destinationPath);
return new HclIsoVisitor() {
@Override
public Hcl.ConfigFile visitConfigFile(Hcl.ConfigFile configFile, ExecutionContext ctx) {
if (configFile.getSourcePath().equals(from)) {
return super.visitConfigFile(configFile, ctx);
} else if (configFile.getSourcePath().equals(dest)) {
acc.destinationExists = true;
}
return configFile;
}
@Override
public BodyContent visitBodyContent(BodyContent bodyContent, ExecutionContext ctx) {
BodyContent b = super.visitBodyContent(bodyContent, ctx);
if (pathMatcher.matches(getCursor())) {
acc.toMove = bodyContent;
//noinspection ConstantConditions
}
return b;
}
};
}
@Override
public Collection generate(Scanned acc, ExecutionContext ctx) {
if (acc.destinationExists || acc.toMove == null) {
return Collections.emptyList();
}
Hcl.ConfigFile configFile = HclParser.builder().build().parse("")
.findFirst()
.map(Hcl.ConfigFile.class::cast)
.orElseThrow(() -> new IllegalArgumentException("Could not parse as HCL"));
configFile = configFile.withBody(Collections.singletonList(acc.toMove.withPrefix(Space.EMPTY)))
.withSourcePath(Paths.get(destinationPath));
return Collections.singletonList(configFile);
}
@Override
public TreeVisitor, ExecutionContext> getVisitor(Scanned acc) {
JsonPathMatcher pathMatcher = new JsonPathMatcher(contentPath);
Path from = Paths.get(fromPath);
Path dest = Paths.get(destinationPath);
return Preconditions.check(acc.toMove != null, new HclIsoVisitor() {
@Override
public @Nullable BodyContent visitBodyContent(BodyContent bodyContent, ExecutionContext ctx) {
BodyContent b = super.visitBodyContent(bodyContent, ctx);
Path sourcePath = getCursor().firstEnclosingOrThrow(Hcl.ConfigFile.class).getSourcePath();
if (sourcePath.equals(from) && pathMatcher.matches(getCursor())) {
// delete the block from the original file
//noinspection ConstantConditions
return null;
} else if (sourcePath.equals(dest) && pathMatcher.matches(getCursor())) {
return acc.toMove;
}
return b;
}
});
}
}