[java] IDEA-360079 add simple source file

GitOrigin-RevId: 16e846dabdf1235053f53ac95e5c0183e74ec3e0
This commit is contained in:
Mikhail Pyltsin
2025-05-08 17:52:28 +02:00
committed by intellij-monorepo-bot
parent 2f53c07260
commit b2368cb44b
8 changed files with 135 additions and 5 deletions

View File

@@ -240,6 +240,7 @@ node.exception.tooltip=Exception
node.field.tooltip=Field
node.final.flag.tooltip=Final
node.interface.tooltip=Interface
node.simple.source.file.tooltip=Simple source file
node.junit.test.tooltip=JUnit Test
node.method.tooltip=Method
node.record.tooltip=Record

View File

@@ -839,6 +839,7 @@
<internalFileTemplate name="Interface"/>
<internalFileTemplate name="Enum"/>
<internalFileTemplate name="Record"/>
<internalFileTemplate name="SimpleSourceFile"/>
<internalFileTemplate name="AnnotationType" subject="@interface"/>
<internalFileTemplate name="Exception"/>
<internalFileTemplate name="package-info"/>

View File

@@ -0,0 +1,4 @@
#parse("File Header.java")
void main(#[[$END$]]#) {
}

View File

@@ -0,0 +1,92 @@
<html>
<body>
<table width="100%" border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse">
<tr>
<td><font face="verdana" size="-1">Applies to Java simple source files that are created by invoking
<b>New | Java Class/File | Simple source file</b> in the <b>Project</b> tool window.<br><br>
This built-in template is editable. Along with Java expressions and comments, you can also use the predefined variables
(listed below) that will then be expanded like macros into corresponding values.<br><br>
It is also possible to specify custom variables. Custom variables use the following format: <i>${VARIABLE_NAME}</i>, where
<i>VARIABLE_NAME</i> is a name for your variable (for example, <i>${MY_CUSTOM_FUNCTION_NAME}</i>).
Before the IDE creates a new file with custom variables, you see a dialog where you can define values for custom variables in the
template.<br><br>
By using the <i>#parse</i> directive, you can include templates from the <b>Includes</b> tab. To include a template,
specify the full name of the template as a parameter in quotation marks (for example, <i>#parse("File Header.java")</i>.
</font></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="5" cellspacing="0" style="border-collapse: collapse">
<tr>
<td colspan="3"><font face="verdana" size="-1">Predefined variables take the following values:</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${PACKAGE_NAME}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Name of the package in which a new record is created</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${NAME}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Name of the new record specified by you in the <b>Create New Class</b> dialog</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${USER}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">System login name of the current user</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${DATE}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Current system date</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${TIME}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Current system time</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${YEAR}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Current year</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${MONTH}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">current month</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${MONTH_NAME_SHORT}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">First 3 letters of the current month name (Jan, Feb, and so on)</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${MONTH_NAME_FULL}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Full name of the current month (January, February, and so on)</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${DAY}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Current day of the month</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${HOUR}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Current hour</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${MINUTE}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Current minute</font></td>
</tr>
<tr>
<td valign="top"><nobr><font face="verdana" size="-2"><b>${PROJECT_NAME}</b></font></nobr></td>
<td width="10">&nbsp;</td>
<td width="100%" valign="top"><font face="verdana" size="-1">Name of the current project</font></td>
</tr>
</table>
</body>
</html>

View File

@@ -54,6 +54,12 @@ public class CreateClassAction extends JavaCreateTemplateInPackageAction<PsiClas
builder.addKind(JavaPsiBundle.message("node.exception.tooltip"), PlatformIcons.EXCEPTION_CLASS_ICON,
JavaTemplateUtil.INTERNAL_EXCEPTION_TYPE_TEMPLATE_NAME);
if (JavaFeature.IMPLICIT_CLASSES.isSufficient(level)) {
builder.addKind(JavaPsiBundle.message("node.simple.source.file.tooltip"),
IconManager.getInstance().getPlatformIcon(com.intellij.ui.PlatformIcons.JavaFileType),
JavaTemplateUtil.INTERNAL_SIMPLE_SOURCE_FILE);
}
PsiDirectory[] dirs = {directory};
for (FileTemplate template : FileTemplateManager.getInstance(project).getAllTemplates()) {
@NotNull CreateFromTemplateHandler handler = FileTemplateUtil.findHandler(template);

View File

@@ -7,6 +7,7 @@ import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.JavaFeature;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
@@ -15,6 +16,7 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
@@ -25,10 +27,23 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler
String content,
boolean reformat,
String extension) throws IncorrectOperationException {
return createClassOrInterface(project, directory, content, reformat, extension, null);
}
private static PsiClass createClassOrInterface(Project project,
PsiDirectory directory,
String content,
boolean reformat,
String extension, @Nullable String optionalClassName) throws IncorrectOperationException {
if (extension == null) extension = JavaFileType.INSTANCE.getDefaultExtension();
final String name = "myClass" + "." + extension;
final PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText(name, JavaLanguage.INSTANCE, content, false, false);
psiFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, LanguageLevel.JDK_16);
LanguageLevel highest = LanguageLevel.HIGHEST;
LanguageLevel implicitClassesMinimumLevel = JavaFeature.IMPLICIT_CLASSES.getMinimumLevel();
if (highest.isLessThan(implicitClassesMinimumLevel)) {
highest = implicitClassesMinimumLevel;
}
psiFile.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, highest);
if (!(psiFile instanceof PsiJavaFile psiJavaFile)){
throw new IncorrectOperationException("This template did not produce a Java class or an interface\n"+psiFile.getText());
@@ -38,7 +53,13 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler
throw new IncorrectOperationException("This template did not produce a Java class or an interface\n"+psiFile.getText());
}
PsiClass createdClass = classes[0];
String className = createdClass.getName();
String className;
if (optionalClassName != null && createdClass instanceof PsiImplicitClass) {
className = optionalClassName;
}
else {
className = createdClass.getName();
}
JavaDirectoryServiceImpl.checkCreateClassOrInterface(directory, className);
final LanguageLevel ll = JavaDirectoryService.getInstance().getLanguageLevel(directory);
@@ -94,7 +115,11 @@ public class JavaCreateFromTemplateHandler implements CreateFromTemplateHandler
@NotNull String templateText,
@NotNull Map<String, Object> props) throws IncorrectOperationException {
String extension = template.getExtension();
PsiElement result = createClassOrInterface(project, directory, templateText, template.isReformatCode(), extension);
String name = null;
if (props.get(FileTemplate.ATTRIBUTE_NAME) instanceof String optionalName) {
name = optionalName;
}
PsiElement result = createClassOrInterface(project, directory, templateText, template.isReformatCode(), extension, name);
hackAwayEmptyPackage((PsiJavaFile)result.getContainingFile(), template, props);
return result;
}

View File

@@ -30,10 +30,11 @@ public final class JavaTemplateUtil {
public static final String INTERNAL_EXCEPTION_TYPE_TEMPLATE_NAME = "Exception";
public static final String INTERNAL_ENUM_TEMPLATE_NAME = "Enum";
public static final String INTERNAL_RECORD_TEMPLATE_NAME = "Record";
public static final String INTERNAL_SIMPLE_SOURCE_FILE = "SimpleSourceFile";
public static final String[] INTERNAL_CLASS_TEMPLATES = {
INTERNAL_CLASS_TEMPLATE_NAME, INTERNAL_INTERFACE_TEMPLATE_NAME, INTERNAL_ANNOTATION_TYPE_TEMPLATE_NAME, INTERNAL_ENUM_TEMPLATE_NAME,
INTERNAL_RECORD_TEMPLATE_NAME, INTERNAL_EXCEPTION_TYPE_TEMPLATE_NAME};
INTERNAL_RECORD_TEMPLATE_NAME, INTERNAL_EXCEPTION_TYPE_TEMPLATE_NAME, INTERNAL_SIMPLE_SOURCE_FILE};
public static final String INTERNAL_PACKAGE_INFO_TEMPLATE_NAME = "package-info";
public static final String INTERNAL_MODULE_INFO_TEMPLATE_NAME = "module-info";

View File

@@ -1,7 +1,7 @@
abstract.class.not.allowed=Abstract class is not allowed
access.static.via.instance=Access static member via instance reference
action.analyzing.cyclic.dependencies.in.scope=Cyclic Dependencies of {0}
action.create.new.class=New Java Class
action.create.new.class=New Java Class/File
action.create.new.class.description=Create new Java class
action.create.new.module-info.description=Create new module-info.java
action.create.new.module-info.title=module-info.java