mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] IDEA-327241 Enable compilation and running Java projects with configured unsupported preview versions
GitOrigin-RevId: df85f51ac1d4249ec3baf34f5ce7d150e06d2a13
This commit is contained in:
committed by
intellij-monorepo-bot
parent
3d075de8e5
commit
2a4fc312fb
@@ -664,6 +664,7 @@ label.select.project.type.to.configure=Select project type to configure
|
||||
language.level.combo.lts.versions=LTS Versions
|
||||
language.level.combo.other.versions=Other Versions
|
||||
language.level.combo.experimental.versions=Experimental Versions
|
||||
language.level.combo.unsupported.versions=Unsupported Versions
|
||||
project.or.module.jdk.misconfigured={0, choice, 0#Project|1#Module} JDK is misconfigured
|
||||
notification.group.build.script.found=Build script found
|
||||
|
||||
|
||||
@@ -11,12 +11,16 @@ import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.openapi.ui.popup.ListSeparator
|
||||
import com.intellij.pom.java.AcceptedLanguageLevelsSettings
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.ui.ColoredText
|
||||
import com.intellij.ui.GroupedComboBoxRenderer
|
||||
import com.intellij.ui.SimpleColoredComponent
|
||||
import com.intellij.ui.SimpleTextAttributes
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.annotations.Nls
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import javax.swing.DefaultComboBoxModel
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
abstract class LanguageLevelCombo @JvmOverloads constructor(
|
||||
defaultItem: @Nls String?,
|
||||
// It could be an open method but since we use it in constructor we have a leaking this problem
|
||||
@@ -37,13 +41,22 @@ abstract class LanguageLevelCombo @JvmOverloads constructor(
|
||||
val otherItems = items.filterAndAdd(buildList {
|
||||
LanguageLevel.entries
|
||||
.sortedBy { it.toJavaVersion().feature }
|
||||
.filter { level: LanguageLevel -> level <= highestWithPreview && (level.isPreview || !ArrayUtil.contains(level, *LTS)) }
|
||||
.filter { level: LanguageLevel -> level <= highestWithPreview && !level.isUnsupported &&
|
||||
(level.isPreview || !ArrayUtil.contains(level, *LTS)) }
|
||||
.forEach { level: LanguageLevel -> add(level) }
|
||||
})
|
||||
|
||||
val experimentalItems = items.filterAndAdd(buildList {
|
||||
for (level in LanguageLevel.entries) {
|
||||
if (level > highestWithPreview) {
|
||||
if (level > highestWithPreview && !level.isUnsupported) {
|
||||
add(level)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
val unsupportedItems = items.filterAndAdd(buildList {
|
||||
for (level in LanguageLevel.entries) {
|
||||
if (level.isUnsupported) {
|
||||
add(level)
|
||||
}
|
||||
}
|
||||
@@ -52,7 +65,8 @@ abstract class LanguageLevelCombo @JvmOverloads constructor(
|
||||
val separatorsMap: Map<Any?, ListSeparator> = listOf(
|
||||
ltsItems.firstOrNull() to ListSeparator(JavaUiBundle.message("language.level.combo.lts.versions")),
|
||||
otherItems.firstOrNull() to ListSeparator(JavaUiBundle.message("language.level.combo.other.versions")),
|
||||
experimentalItems.firstOrNull() to ListSeparator(JavaUiBundle.message("language.level.combo.experimental.versions"))
|
||||
experimentalItems.firstOrNull() to ListSeparator(JavaUiBundle.message("language.level.combo.experimental.versions")),
|
||||
unsupportedItems.firstOrNull() to ListSeparator(JavaUiBundle.message("language.level.combo.unsupported.versions")),
|
||||
).filter { it.first != null }.toMap()
|
||||
|
||||
isSwingPopup = false
|
||||
@@ -64,6 +78,14 @@ abstract class LanguageLevelCombo @JvmOverloads constructor(
|
||||
else -> ""
|
||||
}
|
||||
|
||||
override fun customize(item: SimpleColoredComponent, value: Any, index: Int, isSelected: Boolean, cellHasFocus: Boolean) {
|
||||
if (value is LanguageLevel && value.isUnsupported) {
|
||||
item.append(ColoredText.singleFragment(value.presentableText, SimpleTextAttributes.ERROR_ATTRIBUTES))
|
||||
} else {
|
||||
super.customize(item, value, index, isSelected, cellHasFocus)
|
||||
}
|
||||
}
|
||||
|
||||
override fun separatorFor(value: Any): ListSeparator? = separatorsMap[value]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,13 +25,20 @@ import static com.intellij.reference.SoftReference.dereference;
|
||||
|
||||
public final class LanguageLevelUtil {
|
||||
/**
|
||||
* Returns explicitly specified custom language level for {@code module}, or {@code null} if the module uses 'Project default' language level
|
||||
* Returns explicitly specified custom language level for {@code module}, or {@code null} if the module uses 'Project default' language level.
|
||||
* May return {@linkplain LanguageLevel#isUnsupported() unsupported} language level.
|
||||
* @param module to get the language level for.
|
||||
*/
|
||||
public static @Nullable LanguageLevel getCustomLanguageLevel(@NotNull Module module) {
|
||||
LanguageLevelModuleExtension moduleExtension = ModuleRootManager.getInstance(module).getModuleExtension(LanguageLevelModuleExtension.class);
|
||||
return moduleExtension != null ? moduleExtension.getLanguageLevel() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns effective language level for the module (either custom module level, or project level if module level is not specified).
|
||||
* May return {@linkplain LanguageLevel#isUnsupported() unsupported} language level.
|
||||
* @param module to get the language level for.
|
||||
*/
|
||||
@NotNull
|
||||
public static LanguageLevel getEffectiveLanguageLevel(@NotNull final Module module) {
|
||||
ApplicationManager.getApplication().assertReadAccessAllowed();
|
||||
@@ -73,7 +80,7 @@ public final class LanguageLevelUtil {
|
||||
|
||||
@Nullable
|
||||
public static String getShortMessage(@NotNull LanguageLevel languageLevel) {
|
||||
return ourPresentableShortMessage.get(languageLevel);
|
||||
return ourPresentableShortMessage.get(languageLevel.getSupportedLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +143,9 @@ public final class LanguageLevelUtil {
|
||||
if (forbiddenApi == null) return null;
|
||||
if (forbiddenApi.contains(signature)) return languageLevel;
|
||||
if (languageLevel.compareTo(LanguageLevel.HIGHEST) == 0) return null;
|
||||
LanguageLevel nextLanguageLevel = LanguageLevel.values()[languageLevel.ordinal() + 1];
|
||||
LanguageLevel[] values = LanguageLevel.values();
|
||||
if (languageLevel.ordinal() == values.length - 1) return null;
|
||||
LanguageLevel nextLanguageLevel = values[languageLevel.ordinal() + 1];
|
||||
return getLastIncompatibleLanguageLevelForSignature(signature, nextLanguageLevel);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -121,6 +121,7 @@ public enum HighlightingFeature {
|
||||
}
|
||||
|
||||
boolean isSufficient(@NotNull LanguageLevel useSiteLevel) {
|
||||
useSiteLevel = useSiteLevel.getSupportedLevel();
|
||||
return useSiteLevel.isAtLeast(level) &&
|
||||
(!level.isPreview() || useSiteLevel.isPreview());
|
||||
}
|
||||
@@ -128,6 +129,7 @@ public enum HighlightingFeature {
|
||||
boolean isLimited() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if feature was preview and then accepted as standard
|
||||
*/
|
||||
|
||||
@@ -138,6 +138,7 @@ jdk.21.preview.language.level.description=21 (Preview) - String templates, unnam
|
||||
jdk.22.language.level.description=22 - Unnamed variables and patterns
|
||||
jdk.22.preview.language.level.description=22 (Preview) - Statements before super(), string templates (2nd preview) etc.
|
||||
jdk.X.language.level.description=X - Experimental features
|
||||
jdk.unsupported.preview.language.level.description={0} (Preview) - Unsupported
|
||||
|
||||
local.class.preposition=local
|
||||
method.context.display={0}() in {1}
|
||||
|
||||
+4
@@ -18,6 +18,10 @@ public abstract class LanguageLevelProjectExtension {
|
||||
return project.getService(LanguageLevelProjectExtension.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return configured project language level.
|
||||
* May return {@linkplain LanguageLevel#isUnsupported() unsupported} language level.
|
||||
*/
|
||||
@NotNull
|
||||
public abstract LanguageLevel getLanguageLevel();
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@ package com.intellij.pom.java;
|
||||
import com.intellij.core.JavaPsiBundle;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.lang.JavaVersion;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -43,7 +45,19 @@ public enum LanguageLevel {
|
||||
JDK_21_PREVIEW(JavaPsiBundle.messagePointer("jdk.21.preview.language.level.description"), 21),
|
||||
JDK_22(JavaPsiBundle.messagePointer("jdk.22.language.level.description"), 22),
|
||||
JDK_22_PREVIEW(JavaPsiBundle.messagePointer("jdk.22.preview.language.level.description"), 22),
|
||||
JDK_X(JavaPsiBundle.messagePointer("jdk.X.language.level.description"), 23),;
|
||||
JDK_X(JavaPsiBundle.messagePointer("jdk.X.language.level.description"), 23),
|
||||
|
||||
// Unsupported
|
||||
// Marked as obsolete to draw attention, as they should not be normally used in code or in tests,
|
||||
// except the tests that explicitly test the obsolete levels
|
||||
|
||||
@ApiStatus.Obsolete
|
||||
JDK_17_PREVIEW(17, JDK_20_PREVIEW),
|
||||
@ApiStatus.Obsolete
|
||||
JDK_18_PREVIEW(18, JDK_20_PREVIEW),
|
||||
@ApiStatus.Obsolete
|
||||
JDK_19_PREVIEW(19, JDK_20_PREVIEW),
|
||||
;
|
||||
|
||||
/**
|
||||
* Should point to the latest released JDK.
|
||||
@@ -53,10 +67,23 @@ public enum LanguageLevel {
|
||||
private final Supplier<@Nls String> myPresentableText;
|
||||
private final JavaVersion myVersion;
|
||||
private final boolean myPreview;
|
||||
private final @Nullable LanguageLevel myAlias;
|
||||
|
||||
LanguageLevel(Supplier<@Nls String> presentableTextSupplier, int major) {
|
||||
this(presentableTextSupplier, major, null);
|
||||
}
|
||||
|
||||
LanguageLevel(int major, @NotNull LanguageLevel alias) {
|
||||
this(JavaPsiBundle.messagePointer("jdk.unsupported.preview.language.level.description", major), major, alias);
|
||||
}
|
||||
|
||||
LanguageLevel(Supplier<@Nls String> presentableTextSupplier, int major, @Nullable LanguageLevel alias) {
|
||||
myPresentableText = presentableTextSupplier;
|
||||
myVersion = JavaVersion.compose(major);
|
||||
if (alias != null && alias.isUnsupported()) {
|
||||
throw new IllegalArgumentException("Cannot alias to unsupported version");
|
||||
}
|
||||
myAlias = alias;
|
||||
myPreview = name().endsWith("_PREVIEW") || name().endsWith("_X");
|
||||
}
|
||||
|
||||
@@ -64,6 +91,24 @@ public enum LanguageLevel {
|
||||
return myPreview;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this language level is not supported anymore. It's still possible to invoke compiler or launch the program
|
||||
* using this language level. However, it's not guaranteed that the code insight features will work correctly.
|
||||
* All the code insight features will use the {@linkplain #getSupportedLevel() alias level} instead
|
||||
*/
|
||||
public boolean isUnsupported() {
|
||||
return myAlias != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the closest supported language level for the unsupported level;
|
||||
* returns this for supported level
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public @NotNull LanguageLevel getSupportedLevel() {
|
||||
return myAlias == null ? this : myAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return corresponding preview level, or {@code null} if level has no paired preview level
|
||||
*/
|
||||
@@ -77,6 +122,14 @@ public enum LanguageLevel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return corresponding non-preview level; this if this level is non-preview already
|
||||
*/
|
||||
public @NotNull LanguageLevel getNonPreviewLevel() {
|
||||
if (!myPreview) return this;
|
||||
return valueOf(StringUtil.substringBefore(name(), "_PREVIEW"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nls
|
||||
public String getPresentableText() {
|
||||
|
||||
+4
-2
@@ -2,6 +2,7 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -94,7 +95,7 @@ public class CapturingCleanerInspection extends AbstractBaseJavaLocalInspectionT
|
||||
}
|
||||
if (runnableExpr instanceof PsiNewExpression newExpression) {
|
||||
if (newExpression.getAnonymousClass() != null) {
|
||||
if (PsiUtil.isLanguageLevel18OrHigher(trackedClass)) {
|
||||
if (PsiUtil.getDeclaredLanguageLevel(trackedClass).isAtLeast(LanguageLevel.JDK_18)) {
|
||||
PsiElement elementCapturingThis = getLambdaOrInnerClassElementCapturingThis(newExpression, trackedClass);
|
||||
if (elementCapturingThis != null) {
|
||||
return elementCapturingThis;
|
||||
@@ -109,7 +110,8 @@ public class CapturingCleanerInspection extends AbstractBaseJavaLocalInspectionT
|
||||
if (aClass == null) return null;
|
||||
if (aClass.getContainingClass() != trackedClass) return null;
|
||||
if (aClass.hasModifierProperty(PsiModifier.STATIC)) return null;
|
||||
if (PsiUtil.isLanguageLevel18OrHigher(trackedClass) && getLambdaOrInnerClassElementCapturingThis(newExpression, trackedClass) == null) return null;
|
||||
if (PsiUtil.getDeclaredLanguageLevel(trackedClass).isAtLeast(LanguageLevel.JDK_18) &&
|
||||
getLambdaOrInnerClassElementCapturingThis(newExpression, trackedClass) == null) return null;
|
||||
return classReference;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -63,25 +63,38 @@ public final class AcceptedLanguageLevelsSettings implements PersistentStateComp
|
||||
showNotificationToAccept(project, unacceptedLevels, level);
|
||||
}
|
||||
}
|
||||
if (!previewLevels.isEmpty() && !PropertiesComponent.getInstance(project).getBoolean(IGNORE_USED_PREVIEW_FEATURES, false)) {
|
||||
if (!previewLevels.isEmpty()) {
|
||||
LanguageLevel languageLevel = previewLevels.first();
|
||||
if (languageLevel == LanguageLevel.JDK_X) {
|
||||
return;
|
||||
}
|
||||
|
||||
int previewFeature = languageLevel.toJavaVersion().feature;
|
||||
PREVIEW_NOTIFICATION_GROUP.createNotification(
|
||||
JavaBundle.message("java.preview.features.notification.title"),
|
||||
JavaBundle.message("java.preview.features.warning", previewFeature + 1, previewFeature),
|
||||
NotificationType.WARNING)
|
||||
.addAction(new NotificationAction(IdeBundle.message("action.Anonymous.text.do.not.show.again")) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
|
||||
PropertiesComponent.getInstance(project).setValue(IGNORE_USED_PREVIEW_FEATURES, true);
|
||||
notification.expire();
|
||||
}
|
||||
})
|
||||
.notify(project);
|
||||
if (languageLevel.isUnsupported()) {
|
||||
LanguageLevel supportedLevel = languageLevel.getSupportedLevel();
|
||||
String supportedLevelPresentation = supportedLevel.isPreview()
|
||||
? JavaBundle.message("java.preview.level", supportedLevel.toJavaVersion().feature)
|
||||
: String.valueOf(supportedLevel.toJavaVersion().feature);
|
||||
PREVIEW_NOTIFICATION_GROUP.createNotification(
|
||||
JavaBundle.message("java.preview.features.unsupported.title"),
|
||||
JavaBundle.message("java.preview.features.unsupported", previewFeature, supportedLevelPresentation),
|
||||
NotificationType.ERROR)
|
||||
.notify(project);
|
||||
}
|
||||
else if (!PropertiesComponent.getInstance(project).getBoolean(IGNORE_USED_PREVIEW_FEATURES, false)) {
|
||||
PREVIEW_NOTIFICATION_GROUP.createNotification(
|
||||
JavaBundle.message("java.preview.features.notification.title"),
|
||||
JavaBundle.message("java.preview.features.warning", previewFeature + 1, previewFeature),
|
||||
NotificationType.WARNING)
|
||||
.addAction(new NotificationAction(IdeBundle.message("action.Anonymous.text.do.not.show.again")) {
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) {
|
||||
PropertiesComponent.getInstance(project).setValue(IGNORE_USED_PREVIEW_FEATURES, true);
|
||||
notification.expire();
|
||||
}
|
||||
})
|
||||
.notify(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@
|
||||
package com.siyeh.ig.memory;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -55,7 +56,7 @@ public class AnonymousInnerClassMayBeStaticInspection extends BaseInspection {
|
||||
if (anonymousClass instanceof PsiEnumConstantInitializer) {
|
||||
return;
|
||||
}
|
||||
if (PsiUtil.isLanguageLevel18OrHigher(anonymousClass) &&
|
||||
if (PsiUtil.getDeclaredLanguageLevel(anonymousClass).isAtLeast(LanguageLevel.JDK_18) &&
|
||||
!InheritanceUtil.isInheritor(anonymousClass, CommonClassNames.JAVA_IO_SERIALIZABLE)) {
|
||||
// Since Java 18, non-serializable anonymous classes don't capture 'this' reference
|
||||
return;
|
||||
|
||||
@@ -20,6 +20,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface LanguageLevelModuleExtension {
|
||||
void setLanguageLevel(LanguageLevel languageLevel);
|
||||
|
||||
/**
|
||||
* Returns explicitly specified custom language level for {@code module}, or {@code null} if the module uses 'Project default' language level.
|
||||
* May return {@linkplain LanguageLevel#isUnsupported() unsupported} language level.
|
||||
*/
|
||||
@Nullable
|
||||
LanguageLevel getLanguageLevel();
|
||||
}
|
||||
|
||||
@@ -32,10 +32,7 @@ import com.intellij.util.TimeoutUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.JBIterable;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
@@ -1078,12 +1075,23 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
return getLanguageLevel(element).isAtLeast(LanguageLevel.JDK_17);
|
||||
}
|
||||
|
||||
public static boolean isLanguageLevel18OrHigher(@NotNull PsiElement element) {
|
||||
return getLanguageLevel(element).isAtLeast(LanguageLevel.JDK_18);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element element to get Java language level for
|
||||
* @return the language level. If {@linkplain LanguageLevel#isUnsupported() unsupported} language level
|
||||
* is selected for project or module, this method returns the supported alias.
|
||||
*/
|
||||
@NotNull
|
||||
public static LanguageLevel getLanguageLevel(@NotNull PsiElement element) {
|
||||
return getDeclaredLanguageLevel(element).getSupportedLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element element to get Java language level for
|
||||
* @return the language level. May return {@linkplain LanguageLevel#isUnsupported() unsupported} level.
|
||||
*/
|
||||
@NotNull
|
||||
@ApiStatus.Experimental
|
||||
public static LanguageLevel getDeclaredLanguageLevel(@NotNull PsiElement element) {
|
||||
if (element instanceof PsiDirectory) {
|
||||
return JavaDirectoryService.getInstance().getLanguageLevel((PsiDirectory)element);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java;
|
||||
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public final class LanguageLevelTest {
|
||||
@Test
|
||||
public void unsupported() {
|
||||
@SuppressWarnings("UsagesOfObsoleteApi")
|
||||
LanguageLevel jdk17Preview = LanguageLevel.JDK_17_PREVIEW;
|
||||
assertTrue(jdk17Preview.isUnsupported());
|
||||
assertEquals(LanguageLevel.JDK_20_PREVIEW, jdk17Preview.getSupportedLevel());
|
||||
assertEquals(LanguageLevel.JDK_17, jdk17Preview.getNonPreviewLevel());
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInsight;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.configurations.JavaParameters;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class UnsupportedVersionHighlightingTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_17;
|
||||
}
|
||||
|
||||
public void testPatternInSwitch() {
|
||||
//noinspection UsagesOfObsoleteApi
|
||||
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_17_PREVIEW, () -> {
|
||||
doTestPatternInSwitch();
|
||||
});
|
||||
}
|
||||
|
||||
private void doTestPatternInSwitch() {
|
||||
myFixture.configureByText("Test.java", """
|
||||
class X {
|
||||
void test(Object obj) {
|
||||
switch(obj) {
|
||||
// Simple patterns are supported due to aliasing
|
||||
case String s -> System.out.println("hello");
|
||||
// guards with && are not supported anymore
|
||||
case Integer i<error descr="':' or '->' expected"> </error><error descr="Unexpected token">&&</error> <error descr="Not a statement">i > 0</error> <error descr="Unexpected token">-></error> System.out.println("oops");
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
""");
|
||||
myFixture.checkHighlighting();
|
||||
JavaParameters javaParameters = new JavaParameters();
|
||||
try {
|
||||
javaParameters.configureByModule(getModule(), JavaParameters.CLASSES_ONLY);
|
||||
}
|
||||
catch (CantRunException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
assertEquals("--enable-preview", javaParameters.getVMParametersList().getParametersString());
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public class JavaElementFactoryTest extends LightJavaCodeInsightFixtureTestCase
|
||||
|
||||
public void testArrayClassLanguageLevel() {
|
||||
for (LanguageLevel level : LanguageLevel.values()) {
|
||||
assertEquals(level, PsiUtil.getLanguageLevel(myFactory.getArrayClass(level)));
|
||||
assertEquals(level, PsiUtil.getDeclaredLanguageLevel(myFactory.getArrayClass(level)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -941,8 +941,13 @@ java.preview.features.accept.notification.link=Accept
|
||||
java.preview.features.alert.title=Experimental Feature Alert
|
||||
java.preview.features.legal.notice=You must accept the terms of legal notice of the beta Java specification to enable support for "{0}".<br/><br/>\
|
||||
<b>The implementation of an early-draft specification developed under the Java Community Process (JCP) is made available for testing and evaluation purposes only and is not compatible with any specification of the JCP.</b>{1}
|
||||
java.preview.level={0} (Preview)
|
||||
java.preview.features.notification.title=Java preview features
|
||||
java.preview.features.warning=Newer IDE versions may discontinue support for Java preview features. When Java {0} is released, support for the {1} (Preview) language level may be dropped.
|
||||
java.preview.features.unsupported.title=Unsupported Java preview features
|
||||
java.preview.features.unsupported=Java language level <b>{0} (Preview)</b> used in this project is not supported anymore. \
|
||||
The code insight features will assume language level {1} instead.<br>\
|
||||
It''s strongly encouraged to migrate to newer Java version or stop using preview features.
|
||||
java.terms.exception=exception
|
||||
java.terms.region=region
|
||||
java.terms.instance.initializer=instance initializer
|
||||
|
||||
@@ -28,7 +28,13 @@ public enum LanguageLevel {
|
||||
JDK_20(20), JDK_20_PREVIEW(20),
|
||||
JDK_21(21), JDK_21_PREVIEW(21),
|
||||
JDK_22(22), JDK_22_PREVIEW(22),
|
||||
JDK_X(23);
|
||||
JDK_X(23),
|
||||
|
||||
// Unsupported in IDE
|
||||
JDK_17_PREVIEW(17),
|
||||
JDK_18_PREVIEW(18),
|
||||
JDK_19_PREVIEW(19),
|
||||
;
|
||||
|
||||
public static final LanguageLevel HIGHEST = JDK_21;
|
||||
|
||||
|
||||
@@ -167,7 +167,10 @@ class JavaApiUsageInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
val sourcePsi = sourceNode.sourcePsi ?: return
|
||||
if (target !is PsiMember) return
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(sourcePsi) ?: return
|
||||
val languageLevel = getEffectiveLanguageLevel(module)
|
||||
var languageLevel = getEffectiveLanguageLevel(module)
|
||||
if (languageLevel.isUnsupported) {
|
||||
languageLevel = languageLevel.nonPreviewLevel
|
||||
}
|
||||
val lastIncompatibleLevel = LanguageLevelUtil.getLastIncompatibleLanguageLevel(target, languageLevel)
|
||||
if (lastIncompatibleLevel != null) {
|
||||
if (shouldReportSinceLevelForElement(lastIncompatibleLevel, sourcePsi) == true) return
|
||||
|
||||
Reference in New Issue
Block a user