diff --git a/java/java-backend/resources/META-INF/JavaPlugin.xml b/java/java-backend/resources/META-INF/JavaPlugin.xml index 2364bf7fa558..43ceeb05a993 100644 --- a/java/java-backend/resources/META-INF/JavaPlugin.xml +++ b/java/java-backend/resources/META-INF/JavaPlugin.xml @@ -675,6 +675,7 @@ + @@ -827,6 +828,8 @@ implementation="com.intellij.codeInsight.template.JavaCodeContextType$JavaStructuredConcurrencyConstructors" /> + - - - - - diff --git a/java/java-backend/resources/liveTemplates/JavaPreviousPreview.xml b/java/java-backend/resources/liveTemplates/JavaPreviousPreview.xml new file mode 100644 index 000000000000..5cf8f9b842b1 --- /dev/null +++ b/java/java-backend/resources/liveTemplates/JavaPreviousPreview.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java index fecca46e39ca..1527e33fe122 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java @@ -1,4 +1,4 @@ -// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.codeInsight.template; import com.intellij.codeInsight.completion.JavaCompletionUtil; @@ -381,7 +381,22 @@ public abstract class JavaCodeContextType extends TemplateContextType { @Override protected boolean isInContext(@NotNull PsiElement element) { return statementContext.isInContext(element) && - PsiUtil.isAvailable(JavaFeature.STRUCTURED_CONCURRENCY_TASK_SCOPE_STATIC_FACTORY_METHODS, element); + PsiUtil.isAvailable(JavaFeature.STRUCTURED_CONCURRENCY_TASK_SCOPE_STATIC_FACTORY_METHODS, element) && + !PsiUtil.isAvailable(JavaFeature.STRUCTURED_CONCURRENCY_TASK_SCOPE_STATIC_FACTORY_METHODS_WITH_EXEC_EXCEPTION, element); + } + } + + public static final class JavaStructuredConcurrencyStaticFactoryMethodsWithExecExceptionType extends JavaCodeContextType { + private final JavaCodeContextType statementContext = new Statement(); + + JavaStructuredConcurrencyStaticFactoryMethodsWithExecExceptionType() { + super(JavaBundle.message("live.template.context.statement.java.structured.concurrency.static.factory.methods.with.exec.exception")); + } + + @Override + protected boolean isInContext(@NotNull PsiElement element) { + return statementContext.isInContext(element) && + PsiUtil.isAvailable(JavaFeature.STRUCTURED_CONCURRENCY_TASK_SCOPE_STATIC_FACTORY_METHODS_WITH_EXEC_EXCEPTION, element); } } } diff --git a/java/java-syntax/gen/com/intellij/java/syntax/DefaultJavaSyntaxResources.kt b/java/java-syntax/gen/com/intellij/java/syntax/DefaultJavaSyntaxResources.kt index b39219ddeda7..a0fb5ef30432 100644 --- a/java/java-syntax/gen/com/intellij/java/syntax/DefaultJavaSyntaxResources.kt +++ b/java/java-syntax/gen/com/intellij/java/syntax/DefaultJavaSyntaxResources.kt @@ -1,3 +1,4 @@ +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.syntax // To regenerate the file, please run `GenerateBundleMapping` run configuration with the following parameters: ") @@ -126,6 +127,7 @@ internal object DefaultJavaSyntaxResources { "feature.structured.concurrency" to "Structured Concurrency", "feature.structured.concurrency.constructors" to "Structured Concurrency (StructuredTaskScope with constructors)", "feature.structured.concurrency.static.factory.methods" to "Structured Concurrency (StructuredTaskScope with static factory methods)", + "feature.structured.concurrency.static.factory.methods.with.execution.exception" to "Structured Concurrency (StructuredTaskScope with static factory methods and ExecutionException)", "feature.switch.expressions" to "'switch' expressions", "feature.text.block.escape.sequences" to "'\\s' escape sequences", "feature.text.blocks" to "Text block literals", diff --git a/java/java-syntax/resources/messages/JavaSyntaxBundle.properties b/java/java-syntax/resources/messages/JavaSyntaxBundle.properties index 256955d69183..c91454c4a3ee 100644 --- a/java/java-syntax/resources/messages/JavaSyntaxBundle.properties +++ b/java/java-syntax/resources/messages/JavaSyntaxBundle.properties @@ -73,6 +73,7 @@ feature.stable.values=Stable Values feature.structured.concurrency=Structured Concurrency feature.structured.concurrency.constructors=Structured Concurrency (StructuredTaskScope with constructors) feature.structured.concurrency.static.factory.methods=Structured Concurrency (StructuredTaskScope with static factory methods) +feature.structured.concurrency.static.factory.methods.with.execution.exception=Structured Concurrency (StructuredTaskScope with static factory methods and ExecutionException) feature.sequenced.collections=Sequenced Collections feature.pem.api=PEM Encodings API feature.classfile.api=ClassFile API diff --git a/java/java-syntax/src/com/intellij/pom/java/JavaFeature.kt b/java/java-syntax/src/com/intellij/pom/java/JavaFeature.kt index aeba32b53557..888fcef5c5aa 100644 --- a/java/java-syntax/src/com/intellij/pom/java/JavaFeature.kt +++ b/java/java-syntax/src/com/intellij/pom/java/JavaFeature.kt @@ -154,8 +154,17 @@ enum class JavaFeature { } }, + /** + * JEP 525 + */ STRUCTURED_CONCURRENCY_TASK_SCOPE_STATIC_FACTORY_METHODS(LanguageLevel.JDK_25_PREVIEW, "feature.structured.concurrency.static.factory.methods"), + + /** + * JEP 533 + */ + STRUCTURED_CONCURRENCY_TASK_SCOPE_STATIC_FACTORY_METHODS_WITH_EXEC_EXCEPTION(LanguageLevel.JDK_27_PREVIEW, "feature.structured.concurrency.static.factory.methods.with.execution.exception"), + PEM_API(LanguageLevel.JDK_25_PREVIEW, "feature.pem.api"), /** diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/template/JavaLiveTemplateTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/template/JavaLiveTemplateTest.java index 0617d7bf227d..5b10853d1eef 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/template/JavaLiveTemplateTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/template/JavaLiveTemplateTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.java.codeInsight.template; import com.intellij.JavaTestUtil; @@ -939,7 +939,7 @@ public class JavaLiveTemplateTest extends LiveTemplateTestCase { } public void testSTSSAvailable() { - final TemplateImpl template = TemplateSettings.getInstance().getTemplate("stss", "Java"); + final TemplateImpl template = TemplateSettings.getInstance().getTemplate("stss", "Java//Previous preview templates"); IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_20, () -> { assertFalse(isApplicable("class Foo {void x(){ JUNK }", template)); }); @@ -961,25 +961,34 @@ public class JavaLiveTemplateTest extends LiveTemplateTestCase { } public void testSTSAvailable() { - final TemplateImpl template = TemplateSettings.getInstance().getTemplate("sts", "Java"); + final TemplateImpl previousTemplate = TemplateSettings.getInstance().getTemplate("sts", "Java//Previous preview templates"); IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_20, () -> { - assertFalse(isApplicable("class Foo {void x(){ JUNK }", template)); + assertFalse(isApplicable("class Foo {void x(){ JUNK }", previousTemplate)); }); IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_21, () -> { - assertFalse(isApplicable("class Foo {void x(){ JUNK }", template)); + assertFalse(isApplicable("class Foo {void x(){ JUNK }", previousTemplate)); }); IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_21_PREVIEW, () -> { - assertFalse(isApplicable("class Foo {void x(){ JUNK }", template)); + assertFalse(isApplicable("class Foo {void x(){ JUNK }", previousTemplate)); }); IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_24_PREVIEW, () -> { - assertFalse(isApplicable("class Foo {void x(){ JUNK }", template)); + assertFalse(isApplicable("class Foo {void x(){ JUNK }", previousTemplate)); }); IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_25, () -> { - assertFalse(isApplicable("class Foo {void x(){ JUNK }", template)); + assertFalse(isApplicable("class Foo {void x(){ JUNK }", previousTemplate)); }); IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_25_PREVIEW, () -> { + assertTrue(isApplicable("class Foo {void x(){ JUNK }", previousTemplate)); + }); + + TemplateImpl template = TemplateSettings.getInstance().getTemplate("sts", "Java"); + IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_26_PREVIEW, () -> { + assertFalse(isApplicable("class Foo {void x(){ JUNK }", template)); + }); + IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_27_PREVIEW, () -> { assertTrue(isApplicable("class Foo {void x(){ JUNK }", template)); }); + } public void testIOPAvailable() { diff --git a/java/openapi/resources/messages/JavaBundle.properties b/java/openapi/resources/messages/JavaBundle.properties index 5653576d1177..8c4d639267b0 100644 --- a/java/openapi/resources/messages/JavaBundle.properties +++ b/java/openapi/resources/messages/JavaBundle.properties @@ -1362,6 +1362,7 @@ live.template.context.declaration=Declaration live.template.context.statement.java.lang.io=Statement with available java.lang.IO live.template.context.statement.java.structured.concurrency.constructors=Statement with available StructuredTaskScope with constructors live.template.context.statement.java.structured.concurrency.static.factory.methods=Statement with available StructuredTaskScope with static factory methods +live.template.context.statement.java.structured.concurrency.static.factory.methods.with.exec.exception=Statement with available StructuredTaskScope with ExecutionException live.template.context.normal.class.before.instance.main.declaration=Declaration inside a normal class without instance 'main' method live.template.context.normal.class.after.instance.main.declaration=Declaration inside a normal class with instance 'main' method live.template.context.implicit.class.declaration=Declaration inside a compact source file