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(); } }