[java] IDEA-373074 Improve SOUT templates for java 25

GitOrigin-RevId: 688a0f2ccefaa6f3f9b51c8528fa11e61d0798b0
This commit is contained in:
Mikhail Pyltsin
2025-06-19 17:14:47 +00:00
committed by intellij-monorepo-bot
parent 9d980cb2c7
commit 7b6981f118
10 changed files with 112 additions and 2 deletions
@@ -1191,6 +1191,8 @@
implementation="com.intellij.codeInsight.template.JavaCodeContextType$ImplicitClassDeclaration"/>
<liveTemplateContext contextId="JAVA_NORMAL_CLASS_DECLARATION_WITHOUT_INSTANCE_MAIN" baseContextId="JAVA_CODE"
implementation="com.intellij.codeInsight.template.JavaCodeContextType$NormalClassDeclarationBeforeShortMainMethod"/>
<liveTemplateContext contextId="JAVA_LANG_IO_STATEMENT" baseContextId="JAVA_CODE"
implementation="com.intellij.codeInsight.template.JavaCodeContextType$JavaLangIOStatement"/>
<liveTemplateContext contextId="JAVA_NORMAL_CLASS_DECLARATION_WITH_INSTANCE_MAIN" baseContextId="JAVA_CODE"
implementation="com.intellij.codeInsight.template.JavaCodeContextType$NormalClassDeclarationAfterShortMainMethod"/>
<liveTemplateContext contextId="JAVA_COMMENT" baseContextId="JAVA_CODE"
@@ -268,6 +268,18 @@ public abstract class JavaCodeContextType extends TemplateContextType {
}
}
public static final class JavaLangIOStatement extends JavaCodeContextType {
private final JavaCodeContextType statementContext = new Statement();
public JavaLangIOStatement() {
super(JavaBundle.message("live.template.context.statement.java.lang.io"));
}
@Override
protected boolean isInContext(@NotNull PsiElement element) {
return statementContext.isInContext(element) && PsiUtil.isAvailable(JavaFeature.JAVA_LANG_IO, element);
}
}
public static final class NormalClassDeclarationBeforeShortMainMethod extends JavaCodeContextType {
private final JavaCodeContextType declarationContext = new Declaration();
@@ -131,6 +131,7 @@ public final class TypeNullability {
TypeNullability::nullability, Collectors.mapping(TypeNullability::source, Collectors.toSet())));
Set<NullabilitySource> sources = map.get(Nullability.NOT_NULL);
if (sources != null) {
//todo?
return new TypeNullability(Nullability.NOT_NULL, NullabilitySource.multiSource(sources));
}
sources = map.get(Nullability.NULLABLE);
@@ -328,7 +328,7 @@ public final class GenericsUtil {
if (wildcardType.isSuper() && bound instanceof PsiIntersectionType) {
return PsiWildcardType.createUnbounded(manager);
}
//todo
final PsiType acceptedBound = bound.accept(this);
if (acceptedBound instanceof PsiWildcardType) {
if (((PsiWildcardType)acceptedBound).isExtends() != wildcardType.isExtends()) return PsiWildcardType.createUnbounded(manager);
@@ -394,6 +394,7 @@ public final class GenericsUtil {
PsiType componentType = transformed.getDeepComponentType();
if (componentType instanceof PsiWildcardType) {
componentType = ((PsiWildcardType)componentType).getExtendsBound();
//todo
return PsiTypesUtil.createArrayType(componentType, transformed.getArrayDimensions());
}
if (transformed instanceof PsiEllipsisType) {
@@ -79,6 +79,7 @@ feature.package.import.shadow.module.import=Import-on-demand over module import
feature.package.transitive.dependency.on.java.base=Transitive dependency on java.base module
feature.valhalla.value.classes=Valhalla value classes
feature.markdown.comment=Markdown Documentation Comments
feature.java.lang.io=java.lang.IO utility class
else.without.if='else' without 'if'
expected.array.initializer=Array initializer expected
@@ -131,6 +131,9 @@ enum class JavaFeature {
MARKDOWN_COMMENT(LanguageLevel.JDK_23, "feature.markdown.comment"),
PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS(LanguageLevel.JDK_24_PREVIEW, "feature.package.import.shadow.module.import"),
TRANSITIVE_DEPENDENCY_ON_JAVA_BASE(LanguageLevel.JDK_24_PREVIEW, "feature.package.transitive.dependency.on.java.base"),
JAVA_LANG_IO(LanguageLevel.JDK_25, "feature.java.lang.io"),
VALHALLA_VALUE_CLASSES(LanguageLevel.JDK_X, "feature.valhalla.value.classes"),
;
@@ -5,7 +5,6 @@ import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.daemon.impl.quickfix.EmptyExpression;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.template.*;
import com.intellij.codeInsight.template.actions.SaveAsTemplateAction;
import com.intellij.codeInsight.template.impl.*;
@@ -859,6 +858,82 @@ public class JavaLiveTemplateTest extends LiveTemplateTestCase {
);
}
public void testIOP() {
IdeaTestUtil.withLevel(
getModule(),
JavaFeature.JAVA_LANG_IO.getMinimumLevel(),
() -> {
myFixture.configureByText(
"a.java",
"""
class A{
public static void main(String[] args) {
<caret>
}
}
""");
final TemplateImpl template = TemplateSettings.getInstance().getTemplate("iop", "Java");
startTemplate(template);
myFixture.checkResult(
"""
class A{
public static void main(String[] args) {
IO.println(<caret>);
}
}
""");
}
);
}
public void testIOR() {
IdeaTestUtil.withLevel(
getModule(),
JavaFeature.JAVA_LANG_IO.getMinimumLevel(),
() -> {
myFixture.configureByText(
"a.java",
"""
class A{
public static void main(String[] args) {
<caret>
}
}""");
final TemplateImpl template = TemplateSettings.getInstance().getTemplate("ior", "Java");
startTemplate(template);
myFixture.checkResult(
"""
class A{
public static void main(String[] args) {
IO.readln(<caret>);
}
}""");
}
);
}
public void testIOPAvailable() {
final TemplateImpl template =
TemplateSettings.getInstance().getTemplate("iop", "Java");
IdeaTestUtil.withLevel(getModule(), JavaFeature.JAVA_LANG_IO.getMinimumLevel(), () -> {
assertTrue(isApplicable("class Foo {void x(){ <caret>JUNK }", template));
});
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_21, () -> {
assertFalse(isApplicable("class Foo {void x(){ <caret>JUNK }", template));
});
}
public void testIORAvailable() {
final TemplateImpl template =
TemplateSettings.getInstance().getTemplate("ior", "Java");
IdeaTestUtil.withLevel(getModule(), JavaFeature.JAVA_LANG_IO.getMinimumLevel(), () -> {
assertTrue(isApplicable("class Foo {void x(){ <caret>JUNK }", template));
});
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_21, () -> {
assertFalse(isApplicable("class Foo {void x(){ <caret>JUNK }", template));
});
}
@Override
public final String getBasePath() {
return basePath;
@@ -1320,6 +1320,7 @@ live.template.context.statement=Statement
live.template.context.else='else' position
live.template.context.expression=Expression
live.template.context.declaration=Declaration
live.template.context.statement.java.lang.io=Statement with available java.lang.IO
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 an implicitly declared class
@@ -208,6 +208,8 @@ livetemplate.description.souf=Prints a formatted string to System.out
livetemplate.description.soutm=Prints current class and method names to System.out
livetemplate.description.soutp=Prints method parameter names and values to System.out
livetemplate.description.soutv=Prints a value to System.out
livetemplate.description.iop=IO.println()
livetemplate.description.ior=IO.readln()
livetemplate.description.st=String
livetemplate.description.psf=public static final
livetemplate.description.prsf=private static final
+12
View File
@@ -268,6 +268,18 @@
<option name="JAVA_STATEMENT" value="true" />
</context>
</template>
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.iop"
name="iop" toReformat="true" toShortenFQNames="true" value="IO.println($END$);">
<context>
<option name="JAVA_LANG_IO_STATEMENT" value="true" />
</context>
</template>
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.ior"
name="ior" toReformat="true" toShortenFQNames="true" value="IO.readln($END$);">
<context>
<option name="JAVA_LANG_IO_STATEMENT" value="true" />
</context>
</template>
<template description="System.out::println" name="soutc" toReformat="true" toShortenFQNames="true" value="System.out::println">
<context>
<option name="JAVA_CODE" value="false" />