IJ-CR-162106 [java] IDEA-360079 live templates for instance main methods in implicitly declared classes

- add psvm for normal class, implicit class and normal class with instance 'main' method

GitOrigin-RevId: 46858978ef26162826e951e032d8eca4e85cac49
This commit is contained in:
Mikhail Pyltsin
2025-05-09 13:19:06 +02:00
committed by intellij-monorepo-bot
parent 6e4844b581
commit b1cfbfa235
8 changed files with 68 additions and 17 deletions

View File

@@ -1052,6 +1052,7 @@
<liveTemplateSubstitutor implementation="com.intellij.codeInsight.template.impl.JavaTemplateSubstitutor"/>
<defaultLiveTemplates file="liveTemplates/Java"/>
<defaultLiveTemplates file="liveTemplates/JavaImplicitClass"/>
<defaultLiveTemplates file="liveTemplates/JavaNormalClassesWithInstanceMain"/>
<treeStructureProvider id="ClassesTreeStructureProvider" implementation="com.intellij.ide.projectView.impl.ClassesTreeStructureProvider"
order="last, after NestingTreeStructureProvider"/>
<importFilteringRule implementation="com.intellij.usages.impl.rules.ImportFilteringRule"/>
@@ -1198,8 +1199,10 @@
implementation="com.intellij.codeInsight.template.JavaCodeContextType$Declaration"/>
<liveTemplateContext contextId="JAVA_IMPLICIT_CLASS_DECLARATION" baseContextId="JAVA_CODE"
implementation="com.intellij.codeInsight.template.JavaCodeContextType$ImplicitClassDeclaration"/>
<liveTemplateContext contextId="JAVA_NORMAL_CLASS_DECLARATION" baseContextId="JAVA_CODE"
implementation="com.intellij.codeInsight.template.JavaCodeContextType$NormalClassDeclaration"/>
<liveTemplateContext contextId="JAVA_NORMAL_CLASS_DECLARATION_WITHOUT_INSTANCE_MAIN" baseContextId="JAVA_CODE"
implementation="com.intellij.codeInsight.template.JavaCodeContextType$NormalClassDeclarationBeforeShortMainMethod"/>
<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"
implementation="com.intellij.codeInsight.template.JavaCommentContextType"/>
<liveTemplateContext contextId="JAVA_STRING" baseContextId="JAVA_CODE"

View File

@@ -268,17 +268,32 @@ public abstract class JavaCodeContextType extends TemplateContextType {
}
}
public static final class NormalClassDeclaration extends JavaCodeContextType {
public static final class NormalClassDeclarationBeforeShortMainMethod extends JavaCodeContextType {
private final JavaCodeContextType declarationContext = new Declaration();
private final JavaCodeContextType implicitClassContext = new ImplicitClassDeclaration();
public NormalClassDeclaration() {
super(JavaBundle.message("live.template.context.normal.class.declaration"));
public NormalClassDeclarationBeforeShortMainMethod() {
super(JavaBundle.message("live.template.context.normal.class.before.instance.main.declaration"));
}
@Override
protected boolean isInContext(@NotNull PsiElement element) {
return declarationContext.isInContext(element) && !implicitClassContext.isInContext(element);
return declarationContext.isInContext(element) && !PsiUtil.isAvailable(JavaFeature.IMPLICIT_CLASSES, element);
}
}
public static final class NormalClassDeclarationAfterShortMainMethod extends JavaCodeContextType {
private final JavaCodeContextType declarationContext = new Declaration();
private final JavaCodeContextType implicitClassContext = new ImplicitClassDeclaration();
public NormalClassDeclarationAfterShortMainMethod() {
super(JavaBundle.message("live.template.context.normal.class.after.instance.main.declaration"));
}
@Override
protected boolean isInContext(@NotNull PsiElement element) {
return PsiUtil.isAvailable(JavaFeature.IMPLICIT_CLASSES, element) &&
declarationContext.isInContext(element) &&
!implicitClassContext.isInContext(element);
}
}
}

View File

@@ -12,6 +12,7 @@ import com.intellij.codeInsight.template.macro.*;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.pom.java.JavaFeature;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.LightProjectDescriptor;
@@ -297,7 +298,7 @@ public class JavaLiveTemplateTest extends LiveTemplateTestCase {
Set<TemplateContextType> contextTypeSet = TemplateManagerImpl
.getApplicableContextTypes(TemplateActionContext.expanding(myFixture.getFile(), myFixture.getEditor()));
List<Class<? extends TemplateContextType>> applicableContextTypesClasses = ContainerUtil.map(contextTypeSet, TemplateContextType::getClass);
List<Class<? extends JavaCodeContextType>> declarationTypes = Arrays.asList(JavaCodeContextType.Declaration.class, JavaCodeContextType.NormalClassDeclaration.class);
List<Class<? extends JavaCodeContextType>> declarationTypes = Arrays.asList(JavaCodeContextType.Declaration.class, JavaCodeContextType.NormalClassDeclarationBeforeShortMainMethod.class);
assertEquals(applicableContextTypesClasses, declarationTypes);
}
@@ -337,14 +338,30 @@ public class JavaLiveTemplateTest extends LiveTemplateTestCase {
assertTrue(isApplicable("class Foo {{ \"\"\"<caret>\"\"\" }}", template));
}
public void testJavaNormalClassDeclarationContext() {
final TemplateImpl template = TemplateSettings.getInstance().getTemplate("psvm", "Java");
IdeaTestUtil.withLevel(getModule(), JavaFeature.IMPLICIT_CLASSES.getMinimumLevel(), ()->{
public void testJavaNormalClassDeclarationContextWithInstanceMethod() {
final TemplateImpl template = TemplateSettings.getInstance().getTemplate("psvm", "Java//Instance 'main' methods for normal classes");
IdeaTestUtil.withLevel(getModule(), JavaFeature.IMPLICIT_CLASSES.getMinimumLevel(), () -> {
assertTrue(isApplicable("class Foo { <caret>xxx }", template));
assertTrue(isApplicable("class Foo { <caret>xxx String[] foo(String[] bar) {} }", template));
assertFalse(isApplicable("<caret>", template));
assertFalse(isApplicable("int a = 1; <caret>", template));
});
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_1_8, () -> {
assertFalse(isApplicable("class Foo { <caret>xxx }", template));
});
}
public void testJavaNormalClassDeclarationContextWithoutInstanceMethod() {
final TemplateImpl template = TemplateSettings.getInstance().getTemplate("psvm", "Java");
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_1_8, () -> {
assertTrue(isApplicable("class Foo { <caret>xxx }", template));
assertTrue(isApplicable("class Foo { <caret>xxx String[] foo(String[] bar) {} }", template));
assertFalse(isApplicable("<caret>", template));
assertFalse(isApplicable("int a = 1; <caret>", template));
});
IdeaTestUtil.withLevel(getModule(), JavaFeature.IMPLICIT_CLASSES.getMinimumLevel(), () -> {
assertFalse(isApplicable("class Foo { <caret>xxx }", template));
});
}
public void testImplicitClassDeclarationContext() {

View File

@@ -361,7 +361,7 @@ public class LiveTemplateTest extends LiveTemplateTestCase {
TemplateManagerImpl.getApplicableContextTypes(TemplateActionContext.expanding(myFixture.getFile(), getEditor()));
assertEquals(2, types.size());
assertTrue(types.contains(TemplateContextTypes.getByClass(JavaCodeContextType.Declaration.class)));
assertTrue(types.contains(TemplateContextTypes.getByClass(JavaCodeContextType.NormalClassDeclaration.class)));
assertTrue(types.contains(TemplateContextTypes.getByClass(JavaCodeContextType.NormalClassDeclarationBeforeShortMainMethod.class)));
configureFromFileText("a.txt", "class Foo { <caret>xxx }");
assertInstanceOf(assertOneElement(

View File

@@ -1317,7 +1317,8 @@ live.template.context.statement=Statement
live.template.context.else='else' position
live.template.context.expression=Expression
live.template.context.declaration=Declaration
live.template.context.normal.class.declaration=Declaration inside a normal class
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
inspection.unused.display.name=Unused declaration
inspection.unused.assignment.display.name=Unused assignment

View File

@@ -152,13 +152,13 @@
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.psvm"
name="psvm" toReformat="true" toShortenFQNames="true" value="public static void main(String[] args){&#13;&#10; $END$&#13;&#10;}">
<context>
<option name="JAVA_NORMAL_CLASS_DECLARATION" value="true" />
<option name="JAVA_NORMAL_CLASS_DECLARATION_WITHOUT_INSTANCE_MAIN" value="true" />
</context>
</template>
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.psvm"
name="main" toReformat="true" toShortenFQNames="true" value="public static void main(String[] args){&#13;&#10; $END$&#13;&#10;}">
<context>
<option name="JAVA_NORMAL_CLASS_DECLARATION" value="true" />
<option name="JAVA_NORMAL_CLASS_DECLARATION_WITHOUT_INSTANCE_MAIN" value="true" />
</context>
</template>
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.toar"

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<templateSet group="Java//Implicitly declared classes">
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.short.psvm"
name="psvm" toReformat="true" toShortenFQNames="true" value="void main(){&#13;&#10; $END$&#13;&#10;}">
name="psvm" toReformat="true" toShortenFQNames="true" value="void main($END$){&#13;&#10; &#13;&#10;}">
<context>
<option name="JAVA_IMPLICIT_CLASS_DECLARATION" value="true" />
</context>
</template>
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.short.psvm"
name="main" toReformat="true" toShortenFQNames="true" value="void main(){&#13;&#10; $END$&#13;&#10;}">
name="main" toReformat="true" toShortenFQNames="true" value="void main($END$){&#13;&#10; &#13;&#10;}">
<context>
<option name="JAVA_IMPLICIT_CLASS_DECLARATION" value="true" />
</context>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<templateSet group="Java//Instance 'main' methods for normal classes">
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.short.psvm"
name="psvm" toReformat="true" toShortenFQNames="true" value="static void main($END$){&#13;&#10; &#13;&#10;}">
<context>
<option name="JAVA_NORMAL_CLASS_DECLARATION_WITH_INSTANCE_MAIN" value="true" />
</context>
</template>
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.short.psvm"
name="main" toReformat="true" toShortenFQNames="true" value="static void main($END$){&#13;&#10; &#13;&#10;}">
<context>
<option name="JAVA_NORMAL_CLASS_DECLARATION_WITH_INSTANCE_MAIN" value="true" />
</context>
</template>
</templateSet>