diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java
index 38a06438960b..5c3148bf084b 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/HardcodedContracts.java
@@ -197,7 +197,38 @@ public final class HardcodedContracts {
singleConditionContract(ContractValue.qualifier(), RelationType.EQ, ContractValue.argument(0), returnFalse())
))
//for propagation CONSUMED_STREAM
- .register(ConsumedStreamUtils.getSkipStreamMatchers(), ContractProvider.of(trivialContract(returnThis())));
+ .register(ConsumedStreamUtils.getSkipStreamMatchers(), ContractProvider.of(trivialContract(returnThis())))
+ .register(staticCall(JAVA_LANG_CHARACTER, "isSurrogate").parameterCount(1),
+ ContractProvider.of(
+ singleConditionContract(ContractValue.argument(0), RelationType.LT, ContractValue.constant(Character.MIN_SURROGATE, PsiType.CHAR), returnFalse()),
+ singleConditionContract(ContractValue.argument(0), RelationType.GT, ContractValue.constant(Character.MAX_SURROGATE, PsiType.CHAR), returnFalse()),
+ trivialContract(returnTrue())))
+ .register(staticCall(JAVA_LANG_CHARACTER, "isHighSurrogate").parameterCount(1),
+ ContractProvider.of(
+ singleConditionContract(ContractValue.argument(0), RelationType.LT, ContractValue.constant(Character.MIN_HIGH_SURROGATE, PsiType.CHAR), returnFalse()),
+ singleConditionContract(ContractValue.argument(0), RelationType.GT, ContractValue.constant(Character.MAX_HIGH_SURROGATE, PsiType.CHAR), returnFalse()),
+ trivialContract(returnTrue())))
+ .register(staticCall(JAVA_LANG_CHARACTER, "isLowSurrogate").parameterCount(1),
+ ContractProvider.of(
+ singleConditionContract(ContractValue.argument(0), RelationType.LT, ContractValue.constant(Character.MIN_LOW_SURROGATE, PsiType.CHAR), returnFalse()),
+ singleConditionContract(ContractValue.argument(0), RelationType.GT, ContractValue.constant(Character.MAX_LOW_SURROGATE, PsiType.CHAR), returnFalse()),
+ trivialContract(returnTrue())))
+ .register(staticCall(JAVA_LANG_CHARACTER, "isSupplementaryCodePoint").parameterCount(1),
+ ContractProvider.of(
+ singleConditionContract(ContractValue.argument(0), RelationType.LT, ContractValue.constant(Character.MIN_SUPPLEMENTARY_CODE_POINT, PsiType.INT), returnFalse()),
+ singleConditionContract(ContractValue.argument(0), RelationType.GT, ContractValue.constant(Character.MAX_CODE_POINT, PsiType.INT), returnFalse()),
+ trivialContract(returnTrue())))
+ .register(staticCall(JAVA_LANG_CHARACTER, "isValidCodePoint").parameterCount(1),
+ ContractProvider.of(
+ singleConditionContract(ContractValue.argument(0), RelationType.LT, ContractValue.constant(Character.MIN_CODE_POINT, PsiType.INT), returnFalse()),
+ singleConditionContract(ContractValue.argument(0), RelationType.GT, ContractValue.constant(Character.MAX_CODE_POINT, PsiType.INT), returnFalse()),
+ trivialContract(returnTrue())))
+ .register(staticCall(JAVA_LANG_CHARACTER, "isBmpCodePoint").parameterCount(1),
+ ContractProvider.of(
+ singleConditionContract(ContractValue.argument(0), RelationType.LT, ContractValue.constant(Character.MIN_CODE_POINT, PsiType.INT), returnFalse()),
+ singleConditionContract(ContractValue.argument(0), RelationType.GE, ContractValue.constant(Character.MIN_SUPPLEMENTARY_CODE_POINT, PsiType.INT), returnFalse()),
+ trivialContract(returnTrue())))
+ ;
private static @NotNull ContractProvider getArraycopyContract() {
ContractValue src = ContractValue.argument(0);
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CharacterMethods.java b/java/java-tests/testData/inspection/dataFlow/fixture/CharacterMethods.java
new file mode 100644
index 000000000000..0eb334d04342
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/CharacterMethods.java
@@ -0,0 +1,18 @@
+import java.util.*;
+
+class X {
+ void test(char ch, int codePoint) {
+ if (Character.isHighSurrogate(ch) && Character.isLowSurrogate(ch)) {
+
+ }
+ if (Character.isBmpCodePoint(codePoint) && Character.isSupplementaryCodePoint(codePoint)) {
+
+ }
+ if (!Character.isValidCodePoint(codePoint)) {
+ if (Character.isBmpCodePoint(codePoint)) {
+ }
+ if (Character.isSupplementaryCodePoint(codePoint)) {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/HardcodedContractsTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/HardcodedContractsTest.java
index 056c771b318a..08e25274a508 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInspection/HardcodedContractsTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/HardcodedContractsTest.java
@@ -183,4 +183,5 @@ public class HardcodedContractsTest extends DataFlowInspectionTestCase {
checkHighlighting();
}
+ public void testCharacterMethods() { checkHighlighting(); }
}