mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-inspections] IDEA-313812. Support isAfter, isBefore for java.time in DFA
GitOrigin-RevId: e3ffce95ce6f888687642bbf462706bbeaadb56a
This commit is contained in:
committed by
intellij-monorepo-bot
parent
86f22bd478
commit
9f26b86c19
+26
-12
@@ -21,8 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.codeInspection.dataFlow.ContractReturnValue.*;
|
||||
import static com.intellij.codeInspection.dataFlow.MethodContract.singleConditionContract;
|
||||
import static com.intellij.codeInspection.dataFlow.MethodContract.trivialContract;
|
||||
import static com.intellij.codeInspection.dataFlow.MethodContract.*;
|
||||
import static com.intellij.codeInspection.dataFlow.StandardMethodContract.ValueConstraint.*;
|
||||
import static com.intellij.codeInspection.dataFlow.StandardMethodContract.createConstraintArray;
|
||||
import static com.intellij.psi.CommonClassNames.*;
|
||||
@@ -184,16 +183,31 @@ public final class HardcodedContracts {
|
||||
.register(enumValues(), ContractProvider.of(StandardMethodContract.fromText("->new")))
|
||||
.register(staticCall("java.lang.System", "arraycopy"), expression -> getArraycopyContract())
|
||||
.register(anyOf(
|
||||
instanceCall("java.util.Date", "before", "after"),
|
||||
instanceCall("java.time.LocalDate", "isBefore", "isAfter"),
|
||||
instanceCall("java.time.LocalDateTime", "isBefore", "isAfter"),
|
||||
instanceCall("java.time.LocalTime", "isBefore", "isAfter"),
|
||||
instanceCall("java.time.ZonedDateTime", "isBefore", "isAfter"),
|
||||
instanceCall("java.time.Year", "isBefore", "isAfter"),
|
||||
instanceCall("java.time.YearMonth", "isBefore", "isAfter")
|
||||
), ContractProvider.of(
|
||||
singleConditionContract(ContractValue.qualifier(), RelationType.EQ, ContractValue.argument(0), returnFalse())
|
||||
))
|
||||
instanceCall(JAVA_TIME_LOCAL_DATE, "isAfter"),
|
||||
instanceCall(JAVA_TIME_LOCAL_TIME, "isAfter"),
|
||||
instanceCall(JAVA_TIME_OFFSET_TIME, "isAfter"),
|
||||
instanceCall(JAVA_TIME_OFFSET_DATE_TIME, "isAfter"),
|
||||
instanceCall(JAVA_TIME_ZONED_DATE_TIME, "isAfter"),
|
||||
instanceCall(JAVA_TIME_LOCAL_DATE_TIME, "isAfter"),
|
||||
instanceCall("java.util.Date", "after"),
|
||||
instanceCall("java.time.Year", "isAfter"),
|
||||
instanceCall("java.time.YearMonth", "isAfter")),
|
||||
ContractProvider.of(
|
||||
singleConditionContract(ContractValue.qualifier(), RelationType.GT, ContractValue.argument(0), returnBoolean(true)),
|
||||
trivialContract(returnBoolean(false))))
|
||||
.register(anyOf(
|
||||
instanceCall(JAVA_TIME_LOCAL_DATE, "isBefore"),
|
||||
instanceCall(JAVA_TIME_LOCAL_TIME, "isBefore"),
|
||||
instanceCall(JAVA_TIME_OFFSET_TIME, "isBefore"),
|
||||
instanceCall(JAVA_TIME_OFFSET_DATE_TIME, "isBefore"),
|
||||
instanceCall(JAVA_TIME_ZONED_DATE_TIME, "isBefore"),
|
||||
instanceCall(JAVA_TIME_LOCAL_DATE_TIME, "isBefore"),
|
||||
instanceCall("java.util.Date", "before"),
|
||||
instanceCall("java.time.Year", "isBefore"),
|
||||
instanceCall("java.time.YearMonth", "isBefore")),
|
||||
ContractProvider.of(
|
||||
singleConditionContract(ContractValue.qualifier(), RelationType.LT, ContractValue.argument(0), returnBoolean(true)),
|
||||
trivialContract(returnBoolean(false))))
|
||||
//for propagation CONSUMED_STREAM
|
||||
.register(ConsumedStreamUtils.getSkipStreamMatchers(), ContractProvider.of(trivialContract(returnThis())))
|
||||
.register(staticCall(JAVA_LANG_CHARACTER, "isSurrogate").parameterCount(1),
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
||||
public class DateTimeComparing {
|
||||
public void testLocalDateTime() {
|
||||
LocalDateTime now1 = LocalDateTime.now();
|
||||
LocalDateTime now2 = LocalDateTime.now();
|
||||
if (now1.isAfter(now2)) {
|
||||
if (<warning descr="Condition 'now1.isBefore(now2)' is always 'false'">now1.isBefore(now2)</warning>) {
|
||||
|
||||
}
|
||||
if (<warning descr="Condition 'now2.isBefore(now1)' is always 'true'">now2.isBefore(now1)</warning>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testLocalTime() {
|
||||
LocalTime now1 = LocalTime.now();
|
||||
LocalTime now2 = LocalTime.now();
|
||||
if (now1.isAfter(now2)) {
|
||||
|
||||
if (<warning descr="Condition 'now1.isBefore(now2)' is always 'false'">now1.isBefore(now2)</warning>) {
|
||||
|
||||
}
|
||||
if (<warning descr="Condition 'now2.isBefore(now1)' is always 'true'">now2.isBefore(now1)</warning>) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -184,4 +184,29 @@ public class HardcodedContractsTest extends DataFlowInspectionTestCase {
|
||||
}
|
||||
|
||||
public void testCharacterMethods() { checkHighlighting(); }
|
||||
|
||||
@SuppressWarnings("MethodOverloadsMethodOfSuperclass")
|
||||
public void testDateTimeComparing() {
|
||||
myFixture.addClass("""
|
||||
package java.time.chrono;
|
||||
public interface ChronoLocalDateTime<T> { }""");
|
||||
myFixture.addClass("""
|
||||
package java.time;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
public final class LocalTime {
|
||||
public static LocalTime now() { return new LocalTime(); }
|
||||
public boolean isBefore(LocalTime localTime) { return false; }
|
||||
public boolean isAfter(LocalTime localTime) { return false; }
|
||||
}""");
|
||||
myFixture.addClass("""
|
||||
package java.time;
|
||||
import java.time.chrono.ChronoLocalDateTime;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
public final class LocalDateTime implements ChronoLocalDateTime<LocalDate> {
|
||||
public static LocalDateTime now() { return new LocalDateTime(); }
|
||||
public boolean isBefore(ChronoLocalDateTime<LocalDate> localDateTime2) { return false; }
|
||||
public boolean isAfter(ChronoLocalDateTime<LocalDate> localDateTime2) { return false; }
|
||||
}""");
|
||||
checkHighlighting();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user