Skip to content

Commit

Permalink
Merge branch 'main' into use-java-21-toolchain
Browse files Browse the repository at this point in the history
  • Loading branch information
timtebeek authored Nov 1, 2024
2 parents 9a066b6 + f6f3a7e commit 9fc400c
Show file tree
Hide file tree
Showing 20 changed files with 733 additions and 93 deletions.
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,7 @@ java {
tasks.withType(Javadoc::class.java) {
exclude("**/PlanJavaMigration.java")
}

tasks.test {
maxHeapSize = "2g" // Set max heap size to 2GB or adjust as necessary
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import org.jspecify.annotations.Nullable;
import org.openrewrite.ExecutionContext;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.migrate.joda.templates.*;
import org.openrewrite.java.tree.*;
import org.openrewrite.java.tree.J.VariableDeclarations.NamedVariable;
Expand All @@ -31,15 +30,6 @@

public class JodaTimeVisitor extends ScopeAwareVisitor {

private final MethodMatcher anyNewDateTime = new MethodMatcher(JODA_DATE_TIME + "<constructor>(..)");
private final MethodMatcher anyDateTime = new MethodMatcher(JODA_DATE_TIME + " *(..)");
private final MethodMatcher anyBaseDateTime = new MethodMatcher(JODA_BASE_DATE_TIME + " *(..)");
private final MethodMatcher zoneFor = new MethodMatcher(JODA_DATE_TIME_ZONE + " for*(..)");
private final MethodMatcher anyTimeFormatter = new MethodMatcher(JODA_TIME_FORMAT + " *(..)");
private final MethodMatcher anyNewDuration = new MethodMatcher(JODA_DURATION + "<constructor>(..)");
private final MethodMatcher anyDuration = new MethodMatcher(JODA_DURATION + " *(..)");
private final MethodMatcher anyAbstractInstant = new MethodMatcher(JODA_ABSTRACT_INSTANT + " *(..)");

private final Set<NamedVariable> unsafeVars;

public JodaTimeVisitor(Set<NamedVariable> unsafeVars, LinkedList<VariablesInScope> scopes) {
Expand All @@ -62,6 +52,7 @@ public JodaTimeVisitor() {
maybeRemoveImport(JODA_TIME_FORMAT);
maybeRemoveImport(JODA_DURATION);
maybeRemoveImport(JODA_ABSTRACT_INSTANT);
maybeRemoveImport(JODA_INSTANT);
maybeRemoveImport("java.util.Locale");

maybeAddImport(JAVA_DATE_TIME);
Expand Down Expand Up @@ -135,11 +126,9 @@ public JodaTimeVisitor() {
if (hasJodaType(updated.getArguments())) {
return newClass;
}
if (anyNewDateTime.matches(newClass)) {
return applyTemplate(newClass, updated, DateTimeTemplates.getTemplates()).orElse(newClass);
}
if (anyNewDuration.matches(newClass)) {
return applyTemplate(newClass, updated, DurationTemplates.getTemplates()).orElse(newClass);
MethodTemplate template = AllTemplates.getTemplate(newClass);
if (template != null) {
return applyTemplate(newClass, updated, template).orElse(newClass);
}
if (areArgumentsAssignable(updated)) {
return updated;
Expand All @@ -154,24 +143,11 @@ public JodaTimeVisitor() {
if (hasJodaType(m.getArguments()) || isJodaVarRef(m.getSelect())) {
return method;
}
if (zoneFor.matches(method)) {
return applyTemplate(method, m, TimeZoneTemplates.getTemplates()).orElse(method);
}
if (anyDateTime.matches(method) || anyBaseDateTime.matches(method)) {
return applyTemplate(method, m, DateTimeTemplates.getTemplates()).orElse(method);
}
if (anyAbstractInstant.matches(method)) {
return applyTemplate(method, m, AbstractInstantTemplates.getTemplates()).orElse(method);
}
if (anyTimeFormatter.matches(method)) {
return applyTemplate(method, m, DateTimeFormatTemplates.getTemplates()).orElse(method);
}
if (anyDuration.matches(method)) {
return applyTemplate(method, m, DurationTemplates.getTemplates()).orElse(method);
MethodTemplate template = AllTemplates.getTemplate(method);
if (template != null) {
return applyTemplate(method, m, template).orElse(method);
}
if (method.getSelect() != null &&
method.getSelect().getType() != null &&
method.getSelect().getType().isAssignableFrom(JODA_CLASS_PATTERN)) {
if (method.getMethodType().getDeclaringType().isAssignableFrom(JODA_CLASS_PATTERN)) {
return method; // unhandled case
}
if (areArgumentsAssignable(m)) {
Expand Down Expand Up @@ -219,15 +195,13 @@ private boolean hasJodaType(List<Expression> exprs) {
return false;
}

private Optional<J> applyTemplate(MethodCall original, MethodCall updated, List<MethodTemplate> templates) {
for (MethodTemplate template : templates) {
if (template.getMatcher().matches(original)) {
Expression[] args = template.getTemplateArgsFunc().apply(updated);
if (args.length == 0) {
return Optional.of(template.getTemplate().apply(updateCursor(updated), updated.getCoordinates().replace()));
}
return Optional.of(template.getTemplate().apply(updateCursor(updated), updated.getCoordinates().replace(), (Object[]) args));
private Optional<J> applyTemplate(MethodCall original, MethodCall updated, MethodTemplate template) {
if (template.getMatcher().matches(original)) {
Expression[] args = template.getTemplateArgsFunc().apply(updated);
if (args.length == 0) {
return Optional.of(template.getTemplate().apply(updateCursor(updated), updated.getCoordinates().replace()));
}
return Optional.of(template.getTemplate().apply(updateCursor(updated), updated.getCoordinates().replace(), (Object[]) args));
}
return Optional.empty(); // unhandled case
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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.java.migrate.joda.templates;

import lombok.Getter;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.MethodMatcher;

import java.util.ArrayList;
import java.util.List;

import static org.openrewrite.java.migrate.joda.templates.TimeClassNames.JAVA_DATE_TIME;
import static org.openrewrite.java.migrate.joda.templates.TimeClassNames.JODA_ABSTRACT_DATE_TIME;

public class AbstractDateTimeTemplates implements Templates {
private final MethodMatcher getDayOfMonth = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getDayOfMonth()");
private final MethodMatcher getDayOfWeek = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getDayOfWeek()");
private final MethodMatcher getHourOfDay = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getHourOfDay()");
private final MethodMatcher getMillisOfSecond = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getMillisOfSecond()");
private final MethodMatcher getMinuteOfDay = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getMinuteOfDay()");
private final MethodMatcher getMinuteOfHour = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getMinuteOfHour()");
private final MethodMatcher getMonthOfYear = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getMonthOfYear()");
private final MethodMatcher getSecondOfDay = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getSecondOfDay()");
private final MethodMatcher getSecondOfMinute = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getSecondOfMinute()");
private final MethodMatcher getWeekOfWeekyear = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " getWeekOfWeekyear()");
private final MethodMatcher toString = new MethodMatcher(JODA_ABSTRACT_DATE_TIME + " toString()");

private final JavaTemplate getDayOfMonthTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.getDayOfMonth()").build();
private final JavaTemplate getDayOfWeekTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.getDayOfWeek().getValue()").build();
private final JavaTemplate getHourOfDayTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.getHour()").build();
private final JavaTemplate getMillisOfSecondTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.get(ChronoField.MILLI_OF_SECOND)").imports("java.time.temporal.ChronoField").build();
private final JavaTemplate getMinuteOfDayTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.get(ChronoField.MINUTE_OF_DAY)").imports("java.time.temporal.ChronoField").build();
private final JavaTemplate getMinuteOfHourTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.getMinute()").build();
private final JavaTemplate getMonthOfYearTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.getMonthValue()").build();
private final JavaTemplate getSecondOfDayTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.get(ChronoField.SECOND_OF_DAY)").imports("java.time.temporal.ChronoField").build();
private final JavaTemplate getSecondOfMinuteTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.getSecond()").build();
private final JavaTemplate getWeekOfWeekyearTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.get(ChronoField.ALIGNED_WEEK_OF_YEAR)").imports("java.time.temporal.ChronoField").build();
private final JavaTemplate toStringTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.toString()").build();

@Getter
private final List<MethodTemplate> templates = new ArrayList<MethodTemplate>() {
{
add(new MethodTemplate(getDayOfMonth, getDayOfMonthTemplate));
add(new MethodTemplate(getDayOfWeek, getDayOfWeekTemplate));
add(new MethodTemplate(getHourOfDay, getHourOfDayTemplate));
add(new MethodTemplate(getMillisOfSecond, getMillisOfSecondTemplate));
add(new MethodTemplate(getMinuteOfDay, getMinuteOfDayTemplate));
add(new MethodTemplate(getMinuteOfHour, getMinuteOfHourTemplate));
add(new MethodTemplate(getMonthOfYear, getMonthOfYearTemplate));
add(new MethodTemplate(getSecondOfDay, getSecondOfDayTemplate));
add(new MethodTemplate(getSecondOfMinute, getSecondOfMinuteTemplate));
add(new MethodTemplate(getWeekOfWeekyear, getWeekOfWeekyearTemplate));
add(new MethodTemplate(toString, toStringTemplate));
}
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.java.migrate.joda.templates;

import lombok.Getter;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.MethodMatcher;

import java.util.ArrayList;
import java.util.List;

import static org.openrewrite.java.migrate.joda.templates.TimeClassNames.JAVA_DURATION;
import static org.openrewrite.java.migrate.joda.templates.TimeClassNames.JODA_DURATION;

public class AbstractDurationTemplates implements Templates {
private final MethodMatcher isLongerThan = new MethodMatcher(JODA_DURATION + " isLongerThan(..)");
private final MethodMatcher toPeriod = new MethodMatcher(JODA_DURATION + " toPeriod()");

private final JavaTemplate isLongerThanTemplate = JavaTemplate.builder("#{any(" + JAVA_DURATION + ")}.compareTo(#{any(" + JAVA_DURATION + ")}) > 0").build();
private final JavaTemplate toPeriodTemplate = JavaTemplate.builder("#{any(" + JAVA_DURATION + ")}.toPeriod()").build();

@Getter
private final List<MethodTemplate> templates = new ArrayList<MethodTemplate>() {
{
add(new MethodTemplate(isLongerThan, isLongerThanTemplate));
add(new MethodTemplate(toPeriod, toPeriodTemplate));
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,98 @@
*/
package org.openrewrite.java.migrate.joda.templates;

import lombok.Getter;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.MethodCall;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

import static org.openrewrite.java.migrate.joda.templates.TimeClassNames.JAVA_UTIL_DATE;
import static org.openrewrite.java.migrate.joda.templates.TimeClassNames.JODA_ABSTRACT_INSTANT;
import static org.openrewrite.java.migrate.joda.templates.TimeClassNames.*;

public class AbstractInstantTemplates {
public class AbstractInstantTemplates implements Templates {
private final MethodMatcher equals = new MethodMatcher(JODA_ABSTRACT_INSTANT + " equals(java.lang.Object)");
private final MethodMatcher getZone = new MethodMatcher(JODA_ABSTRACT_INSTANT + " getZone()");
private final MethodMatcher isAfterLong = new MethodMatcher(JODA_ABSTRACT_INSTANT + " isAfter(long)");
private final MethodMatcher isAfter = new MethodMatcher(JODA_ABSTRACT_INSTANT + " isAfter(org.joda.time.ReadableInstant)");
private final MethodMatcher isBeforeLong = new MethodMatcher(JODA_ABSTRACT_INSTANT + " isBefore(long)");
private final MethodMatcher isBefore = new MethodMatcher(JODA_ABSTRACT_INSTANT + " isBefore(org.joda.time.ReadableInstant)");
private final MethodMatcher isBeforeNow = new MethodMatcher(JODA_ABSTRACT_INSTANT + " isBeforeNow()");
private final MethodMatcher isEqualLong = new MethodMatcher(JODA_ABSTRACT_INSTANT + " isEqual(long)");
private final MethodMatcher isEqualReadableInstant = new MethodMatcher(JODA_ABSTRACT_INSTANT + " isEqual(org.joda.time.ReadableInstant)");
private final MethodMatcher toDate = new MethodMatcher(JODA_ABSTRACT_INSTANT + " toDate()");
private final MethodMatcher toInstant = new MethodMatcher(JODA_ABSTRACT_INSTANT + " toInstant()");
private final MethodMatcher toString = new MethodMatcher(JODA_ABSTRACT_INSTANT + " toString()");
private final MethodMatcher toStringFormatter = new MethodMatcher(JODA_ABSTRACT_INSTANT + " toString(org.joda.time.format.DateTimeFormatter)");

private final JavaTemplate toDateTemplate = JavaTemplate.builder("Date.from(#{any(java.time.ZonedDateTime)}.toInstant())")
private final JavaTemplate equalsTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.equals(#{any(java.lang.Object)})").build();
private final JavaTemplate getZoneTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.getZone()").build();
private final JavaTemplate isAfterLongTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.isAfter(Instant.ofEpochMilli(#{any(long)}).atZone(ZoneId.systemDefault()))")
.imports(JAVA_INSTANT, JAVA_ZONE_ID).build();
private final JavaTemplate isAfterLongTemplateWithInstant = JavaTemplate.builder("#{any(" + JAVA_INSTANT + ")}.isAfter(Instant.ofEpochMilli(#{any(long)}))")
.imports(JAVA_INSTANT).build();
private final JavaTemplate isAfterTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.isAfter(#{any(" + JAVA_DATE_TIME + ")})").build();
private final JavaTemplate isAfterTemplateWithInstant = JavaTemplate.builder("#{any(" + JAVA_INSTANT + ")}.isAfter(#{any(" + JAVA_INSTANT + ")})").build();
private final JavaTemplate isBeforeLongTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.isBefore(Instant.ofEpochMilli(#{any(long)}).atZone(ZoneId.systemDefault()))")
.imports(JAVA_INSTANT, JAVA_ZONE_ID).build();
private final JavaTemplate isBeforeLongTemplateWithInstant = JavaTemplate.builder("#{any(" + JAVA_INSTANT + ")}.isBefore(Instant.ofEpochMilli(#{any(long)}))")
.imports(JAVA_INSTANT).build();
private final JavaTemplate isBeforTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.isBefore(#{any(" + JAVA_DATE_TIME + ")})").build();
private final JavaTemplate isBeforeTemplateWithInstant = JavaTemplate.builder("#{any(" + JAVA_INSTANT + ")}.isBefore(#{any(" + JAVA_INSTANT + ")})").build();
private final JavaTemplate isBeforeNowTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.isBefore(ZonedDateTime.now())")
.imports(JAVA_DATE_TIME).build();
private final JavaTemplate isEqualLongTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.isEqual(Instant.ofEpochMilli(#{any(long)}).atZone(ZoneId.systemDefault()))")
.imports(JAVA_INSTANT, JAVA_ZONE_ID).build();
private final JavaTemplate isEqualReadableInstantTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.isEqual(#{any(" + JAVA_DATE_TIME + ")})").build();
private final JavaTemplate toDateTemplate = JavaTemplate.builder("Date.from(#{any(" + JAVA_DATE_TIME + ")}.toInstant())")
.imports(JAVA_UTIL_DATE)
.build();
private final JavaTemplate toInstantTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.toInstant()").build();
private final JavaTemplate toStringTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.toString()").build();
private final JavaTemplate toStringFormatterTemplate = JavaTemplate.builder("#{any(" + JAVA_DATE_TIME + ")}.format(#{any(" + JAVA_TIME_FORMATTER + ")})").build();

@Getter
private final List<MethodTemplate> templates = new ArrayList<MethodTemplate>() {
{
add(new MethodTemplate(equals, equalsTemplate));
add(new MethodTemplate(getZone, getZoneTemplate));
add(new MethodTemplate(isAfterLong, isAfterLongTemplate));
add(new MethodTemplate(isAfterLong, isAfterLongTemplateWithInstant));
add(new MethodTemplate(isAfter, isAfterTemplate));
add(new MethodTemplate(isAfter, isAfterTemplateWithInstant));
add(new MethodTemplate(isBeforeLong, isBeforeLongTemplate));
add(new MethodTemplate(isBeforeLong, isBeforeLongTemplateWithInstant));
add(new MethodTemplate(isBefore, isBeforTemplate));
add(new MethodTemplate(isBefore, isBeforeTemplateWithInstant));
add(new MethodTemplate(isBeforeNow, isBeforeNowTemplate));
add(new MethodTemplate(isEqualLong, isEqualLongTemplate));
add(new MethodTemplate(isEqualReadableInstant, isEqualReadableInstantTemplate));
add(new MethodTemplate(toDate, toDateTemplate));
add(new MethodTemplate(toInstant, toInstantTemplate));
add(new MethodTemplate(toString, toStringTemplate));
add(new MethodTemplate(toStringFormatter, toStringFormatterTemplate));
}
};

public static List<MethodTemplate> getTemplates() {
return new AbstractInstantTemplates().templates;
@Override
public boolean matchesMethodCall(MethodCall method, MethodTemplate template) {
if (method instanceof J.NewClass) {
return true;
}
Expression select = ((J.MethodInvocation) method).getSelect();
if (select != null && select.getType() != null && select.getType().isAssignableFrom(Pattern.compile(JODA_INSTANT))) {
return Arrays.asList(
isAfterLongTemplateWithInstant,
isAfterTemplateWithInstant,
isBeforeLongTemplateWithInstant,
isBeforeTemplateWithInstant
).contains(template.getTemplate());
}
return true;
}
}
Loading

0 comments on commit 9fc400c

Please sign in to comment.