Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.NameExpr;
import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;
import com.google.common.annotations.VisibleForTesting;
Expand All @@ -33,6 +34,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand All @@ -51,6 +53,8 @@ public class UpdateVersionsTask extends AbstractVersionsTask {
private boolean setCurrent;
@Nullable
private Version removeVersion;
@Nullable
private String addTransportVersion;

@Inject
public UpdateVersionsTask(BuildLayout layout) {
Expand All @@ -62,6 +66,11 @@ public void addVersion(String version) {
this.addVersion = Version.fromString(version);
}

@Option(option = "add-transport-version", description = "Specifies transport version to add")
public void addTransportVersion(String transportVersion) {
this.addTransportVersion = transportVersion;
}

@Option(option = "set-current", description = "Set the 'current' constant to the new version")
public void setCurrent(boolean setCurrent) {
this.setCurrent = setCurrent;
Expand All @@ -87,15 +96,18 @@ static Optional<Version> parseVersionField(CharSequence field) {

@TaskAction
public void executeTask() throws IOException {
if (addVersion == null && removeVersion == null) {
if (addVersion == null && removeVersion == null && addTransportVersion == null) {
throw new IllegalArgumentException("No versions to add or remove specified");
}
if (setCurrent && addVersion == null) {
throw new IllegalArgumentException("No new version added to set as the current version");
}
if (Objects.equals(addVersion, removeVersion)) {
if (addVersion != null && removeVersion != null && Objects.equals(addVersion, removeVersion)) {
throw new IllegalArgumentException("Same version specified to add and remove");
}
if (addTransportVersion != null && addTransportVersion.split(":").length != 2) {
throw new IllegalArgumentException("Transport version specified must be in the format '<constant>:<version-id>'");
}

Path versionJava = rootDir.resolve(VERSION_FILE_PATH);
CompilationUnit file = LexicalPreservingPrinter.setup(StaticJavaParser.parse(versionJava));
Expand All @@ -115,6 +127,18 @@ public void executeTask() throws IOException {
modifiedFile = removed;
}
}
if (addTransportVersion != null) {
var constant = addTransportVersion.split(":")[0];
var versionId = Integer.parseInt(addTransportVersion.split(":")[1]);
LOGGER.lifecycle("Adding transport version constant [{}] with id [{}]", constant, versionId);

var transportVersionsFile = rootDir.resolve(TRANSPORT_VERSIONS_FILE_PATH);
var transportVersions = LexicalPreservingPrinter.setup(StaticJavaParser.parse(transportVersionsFile));
var modified = addTransportVersionConstant(transportVersions, constant, versionId);
if (modified.isPresent()) {
writeOutNewContents(transportVersionsFile, modified.get());
}
}

if (modifiedFile.isPresent()) {
writeOutNewContents(versionJava, modifiedFile.get());
Expand Down Expand Up @@ -161,6 +185,51 @@ static Optional<CompilationUnit> addVersionConstant(CompilationUnit versionJava,
return Optional.of(versionJava);
}

@VisibleForTesting
static Optional<CompilationUnit> addTransportVersionConstant(CompilationUnit transportVersions, String constant, int versionId) {
ClassOrInterfaceDeclaration transportVersionsClass = transportVersions.getClassByName("TransportVersions").get();
if (transportVersionsClass.getFieldByName(constant).isPresent()) {
LOGGER.lifecycle("New transport version constant [{}] already present, skipping", constant);
return Optional.empty();
}

TreeMap<Integer, FieldDeclaration> versions = transportVersionsClass.getFields()
.stream()
.filter(f -> f.getElementType().asString().equals("TransportVersion"))
.filter(
f -> f.getVariables().stream().limit(1).allMatch(v -> v.getInitializer().filter(Expression::isMethodCallExpr).isPresent())
)
.filter(f -> f.getVariable(0).getInitializer().get().asMethodCallExpr().getNameAsString().endsWith("def"))
.collect(
Collectors.toMap(
f -> f.getVariable(0)
.getInitializer()
.get()
.asMethodCallExpr()
.getArgument(0)
.asIntegerLiteralExpr()
.asNumber()
.intValue(),
Function.identity(),
(f1, f2) -> {
throw new IllegalStateException("Duplicate version constant " + f1);
},
TreeMap::new
)
);

// find the version this should be inserted after
Map.Entry<Integer, FieldDeclaration> previousVersion = versions.lowerEntry(versionId);
if (previousVersion == null) {
throw new IllegalStateException(String.format("Could not find previous version to [%s]", versionId));
}

FieldDeclaration newTransportVersion = createNewTransportVersionConstant(previousVersion.getValue(), constant, versionId);
transportVersionsClass.getMembers().addAfter(newTransportVersion, previousVersion.getValue());

return Optional.of(transportVersions);
}

private static FieldDeclaration createNewVersionConstant(FieldDeclaration lastVersion, String newName, String newExpr) {
return new FieldDeclaration(
new NodeList<>(lastVersion.getModifiers()),
Expand All @@ -172,6 +241,29 @@ private static FieldDeclaration createNewVersionConstant(FieldDeclaration lastVe
);
}

private static FieldDeclaration createNewTransportVersionConstant(FieldDeclaration lastVersion, String newName, int newId) {
return new FieldDeclaration(
new NodeList<>(lastVersion.getModifiers()),
new VariableDeclarator(
lastVersion.getCommonType(),
newName,
StaticJavaParser.parseExpression(String.format("def(%s)", formatTransportVersionId(newId)))
)
);
}

private static String formatTransportVersionId(int id) {
String idString = Integer.toString(id);

return new StringBuilder(idString.substring(idString.length() - 2, idString.length())).insert(0, "_")
.insert(0, idString.substring(idString.length() - 3, idString.length() - 2))
.insert(0, "_")
.insert(0, idString.substring(idString.length() - 6, idString.length() - 3))
.insert(0, "_")
.insert(0, idString.substring(0, idString.length() - 6))
.toString();
}

@VisibleForTesting
static Optional<CompilationUnit> removeVersionConstant(CompilationUnit versionJava, Version version) {
String removeFieldName = toVersionField(version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,96 @@ public void updateVersionFile_removesCorrectly() throws Exception {
assertThat(field.isPresent(), is(false));
}

@Test
public void addTransportVersion() throws Exception {
var transportVersions = """
public class TransportVersions {
public static final TransportVersion V_1_0_0 = def(1_000_0_00);
public static final TransportVersion V_1_1_0 = def(1_001_0_00);
public static final TransportVersion V_1_2_0 = def(1_002_0_00);
public static final TransportVersion V_1_2_1 = def(1_002_0_01);
public static final TransportVersion V_1_2_2 = def(1_002_0_02);
public static final TransportVersion SOME_OTHER_VERSION = def(1_003_0_00);
public static final TransportVersion YET_ANOTHER_VERSION = def(1_004_0_00);
public static final TransportVersion MINIMUM_COMPATIBLE = V_1_0_0;
}
""";

var expectedTransportVersions = """
public class TransportVersions {
public static final TransportVersion V_1_0_0 = def(1_000_0_00);
public static final TransportVersion V_1_1_0 = def(1_001_0_00);
public static final TransportVersion V_1_2_0 = def(1_002_0_00);
public static final TransportVersion V_1_2_1 = def(1_002_0_01);
public static final TransportVersion V_1_2_2 = def(1_002_0_02);
public static final TransportVersion SOME_OTHER_VERSION = def(1_003_0_00);
public static final TransportVersion YET_ANOTHER_VERSION = def(1_004_0_00);
public static final TransportVersion NEXT_TRANSPORT_VERSION = def(1_005_0_00);
public static final TransportVersion MINIMUM_COMPATIBLE = V_1_0_0;
}
""";

var unit = StaticJavaParser.parse(transportVersions);
var result = UpdateVersionsTask.addTransportVersionConstant(unit, "NEXT_TRANSPORT_VERSION", 1_005_0_00);

assertThat(result.isPresent(), is(true));
assertThat(result.get(), hasToString(expectedTransportVersions));
}

@Test
public void addTransportVersionPatch() throws Exception {
var transportVersions = """
public class TransportVersions {
public static final TransportVersion V_1_0_0 = def(1_000_0_00);
public static final TransportVersion V_1_1_0 = def(1_001_0_00);
public static final TransportVersion V_1_2_0 = def(1_002_0_00);
public static final TransportVersion V_1_2_1 = def(1_002_0_01);
public static final TransportVersion V_1_2_2 = def(1_002_0_02);
public static final TransportVersion SOME_OTHER_VERSION = def(1_003_0_00);
public static final TransportVersion YET_ANOTHER_VERSION = def(1_004_0_00);
public static final TransportVersion MINIMUM_COMPATIBLE = V_1_0_0;
}
""";

var expectedTransportVersions = """
public class TransportVersions {
public static final TransportVersion V_1_0_0 = def(1_000_0_00);
public static final TransportVersion V_1_1_0 = def(1_001_0_00);
public static final TransportVersion V_1_2_0 = def(1_002_0_00);
public static final TransportVersion V_1_2_1 = def(1_002_0_01);
public static final TransportVersion V_1_2_2 = def(1_002_0_02);
public static final TransportVersion SOME_OTHER_VERSION = def(1_003_0_00);
public static final TransportVersion PATCH_TRANSPORT_VERSION = def(1_003_0_01);
public static final TransportVersion YET_ANOTHER_VERSION = def(1_004_0_00);
public static final TransportVersion MINIMUM_COMPATIBLE = V_1_0_0;
}
""";

var unit = StaticJavaParser.parse(transportVersions);
var result = UpdateVersionsTask.addTransportVersionConstant(unit, "PATCH_TRANSPORT_VERSION", 1_003_0_01);

assertThat(result.isPresent(), is(true));
assertThat(result.get(), hasToString(expectedTransportVersions));
}

private static Optional<FieldDeclaration> findFirstField(Node node, String name) {
return node.findFirst(FieldDeclaration.class, f -> f.getVariable(0).getName().getIdentifier().equals(name));
}
Expand Down