diff --git a/java/java-analysis-api/src/com/intellij/openapi/module/JdkApiCompatibilityService.java b/java/java-analysis-api/src/com/intellij/openapi/module/JdkApiCompatibilityService.java index 2e2d120eb0b8..bbfd828a8d16 100644 --- a/java/java-analysis-api/src/com/intellij/openapi/module/JdkApiCompatibilityService.java +++ b/java/java-analysis-api/src/com/intellij/openapi/module/JdkApiCompatibilityService.java @@ -9,6 +9,7 @@ import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -116,10 +117,16 @@ public final class JdkApiCompatibilityService { * @return The newly introduced API if it appears after or including {@code languageLevel}, or null if it was introduced before * {@code languageLevel}. */ - private LanguageLevel getIntroducedApiLevel(@NotNull String signature, @Nullable LanguageLevel languageLevel) { + @Contract("_, null -> null") + private @Nullable LanguageLevel getIntroducedApiLevel(@NotNull String signature, @Nullable LanguageLevel languageLevel) { if (languageLevel == null) return null; - if (getIntroducedApis(languageLevel).contains(signature)) return languageLevel; - return getIntroducedApiLevel(signature, languageLevel.next()); + LanguageLevel curLevel = LanguageLevel.HIGHEST; + while (true) { + if (getIntroducedApis(curLevel).contains(signature)) return curLevel; + if (languageLevel == curLevel) return null; + curLevel = curLevel.previous(); + if (curLevel == null) return null; + } } /** diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/ResolveWithLanguageLevelMismatchTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/ResolveWithLanguageLevelMismatchTest.java index 5866b76a2339..3204559c05b2 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/ResolveWithLanguageLevelMismatchTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/ResolveWithLanguageLevelMismatchTest.java @@ -49,7 +49,7 @@ public final class ResolveWithLanguageLevelMismatchTest extends LightJavaCodeIns import com.example.*; class MyClass { - int a = Record.x; + int a = Record.x; }"""); myFixture.enableInspections(new JavaApiUsageInspection()); myFixture.checkHighlighting(); diff --git a/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/tests/java/JavaJavaApiUsageInspectionTest.kt b/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/tests/java/JavaJavaApiUsageInspectionTest.kt index 3f4c0fda0a96..d00e11bd5e12 100644 --- a/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/tests/java/JavaJavaApiUsageInspectionTest.kt +++ b/jvm/jvm-analysis-java-tests/testSrc/com/intellij/codeInspection/tests/java/JavaJavaApiUsageInspectionTest.kt @@ -310,6 +310,18 @@ class JavaJavaApiUsageInspectionTest : JavaApiUsageInspectionTestBase() { } """.trimIndent()) } + + fun `test non preview level suggested`() { + myFixture.setLanguageLevel(LanguageLevel.JDK_11) + // Expect 15+, not 13+, as it was in preview in JDK 13 + myFixture.testHighlighting(JvmLanguage.JAVA, """ + class X { + void test() { + "xyz".translateEscapes(); + } + } + """) + } fun `test language level 24 with JDK 25`() { myFixture.setLanguageLevel(LanguageLevel.JDK_24)