mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: Use template when generating module-info files (IDEA-184148)
This commit is contained in:
+71
-44
@@ -3,7 +3,9 @@ package com.intellij.codeInspection.java19api;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
|
||||
import com.intellij.codeInspection.AbstractDependencyVisitor;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateUtil;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -45,6 +47,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.ide.fileTemplates.JavaTemplateUtil.INTERNAL_MODULE_INFO_TEMPLATE_NAME;
|
||||
import static com.intellij.psi.PsiJavaModule.*;
|
||||
|
||||
/**
|
||||
* @author Pavel.Dolgov
|
||||
*/
|
||||
@@ -207,7 +212,7 @@ public class Java9GenerateModuleDescriptorsAction extends AnAction {
|
||||
}
|
||||
|
||||
void generate(THashMap<Module, List<File>> classFiles, int totalFiles) {
|
||||
List<GeneratedCode> generatedCode;
|
||||
List<ModuleInfo> moduleInfos;
|
||||
try {
|
||||
myProgressTracker.startPhase(RefactoringBundle.message("generate.module.descriptors.collecting.message"), totalFiles);
|
||||
Map<String, Set<ModuleNode>> packagesDeclaredInModules = collectDependencies(classFiles);
|
||||
@@ -218,22 +223,22 @@ public class Java9GenerateModuleDescriptorsAction extends AnAction {
|
||||
myProgressTracker.nextPhase();
|
||||
|
||||
myProgressTracker.startPhase(RefactoringBundle.message("generate.module.descriptors.preparing.message"), myModuleNodes.size());
|
||||
generatedCode = generateCode();
|
||||
moduleInfos = prepareModuleInfos();
|
||||
myProgressTracker.nextPhase();
|
||||
}
|
||||
finally {
|
||||
myProgressTracker.dispose();
|
||||
}
|
||||
createFilesLater(generatedCode);
|
||||
createFilesLater(moduleInfos);
|
||||
}
|
||||
|
||||
private void createFilesLater(List<GeneratedCode> generatedCode) {
|
||||
private void createFilesLater(List<ModuleInfo> moduleInfos) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
if (!myProject.isDisposed()) {
|
||||
CommandProcessor.getInstance().executeCommand(myProject, () ->
|
||||
((ApplicationImpl)ApplicationManager.getApplication()).runWriteActionWithCancellableProgressInDispatchThread(
|
||||
COMMAND_TITLE, myProject, null,
|
||||
indicator -> createFiles(myProject, generatedCode, indicator)), COMMAND_TITLE, null);
|
||||
indicator -> createFiles(myProject, moduleInfos, indicator)), COMMAND_TITLE, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -246,7 +251,12 @@ public class Java9GenerateModuleDescriptorsAction extends AnAction {
|
||||
Module module = entry.getKey();
|
||||
|
||||
ModuleVisitor visitor = new ModuleVisitor(packageNamesCache);
|
||||
for (File file : entry.getValue()) {
|
||||
List<File> files = entry.getValue();
|
||||
if (files.isEmpty()) {
|
||||
LOG.info("Output directory for module " + module.getName() + " doesn't contain .class files");
|
||||
continue;
|
||||
}
|
||||
for (File file : files) {
|
||||
visitor.processFile(file);
|
||||
myProgressTracker.increment();
|
||||
}
|
||||
@@ -285,7 +295,7 @@ public class Java9GenerateModuleDescriptorsAction extends AnAction {
|
||||
}
|
||||
else {
|
||||
if (set.size() != 1) {
|
||||
LOG.debug("Split package " + packageName + " in " + set);
|
||||
LOG.info("Split package " + packageName + " found in " + set);
|
||||
}
|
||||
moduleNode.getDependencies().addAll(set);
|
||||
}
|
||||
@@ -294,11 +304,11 @@ public class Java9GenerateModuleDescriptorsAction extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
private List<GeneratedCode> generateCode() {
|
||||
List<GeneratedCode> generatedCode = new ArrayList<>();
|
||||
private List<ModuleInfo> prepareModuleInfos() {
|
||||
List<ModuleInfo> moduleInfo = new ArrayList<>();
|
||||
for (ModuleNode moduleNode : myModuleNodes) {
|
||||
if (moduleNode.getDescriptor() != null) {
|
||||
LOG.debug("Descriptor already exists in " + moduleNode);
|
||||
LOG.info("Module descriptor already exists in " + moduleNode);
|
||||
continue;
|
||||
}
|
||||
for (String packageName : moduleNode.getDeclaredPackages()) {
|
||||
@@ -307,50 +317,60 @@ public class Java9GenerateModuleDescriptorsAction extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder text = new StringBuilder();
|
||||
text.append("module ").append(moduleNode.getName()).append(" {");
|
||||
List<ModuleNode> sortedDependencies = moduleNode.getSortedDependencies();
|
||||
List<String> sortedExports = moduleNode.getSortedExports();
|
||||
for (ModuleNode dependencyNode : sortedDependencies) {
|
||||
if (!"java.base".equals(dependencyNode.getName())) {
|
||||
text.append("\n requires ").append(dependencyNode.getName()).append(";");
|
||||
}
|
||||
}
|
||||
if (!sortedDependencies.isEmpty() && !sortedExports.isEmpty()) {
|
||||
text.append('\n');
|
||||
}
|
||||
for (String packageName : sortedExports) {
|
||||
text.append("\n exports ").append(packageName).append(";");
|
||||
}
|
||||
text.append("\n}");
|
||||
|
||||
PsiDirectory rootDir = moduleNode.getRootDir();
|
||||
if (rootDir != null) {
|
||||
generatedCode.add(new GeneratedCode(rootDir, text.toString()));
|
||||
List<String> dependencies = StreamEx.of(moduleNode.getSortedDependencies())
|
||||
.map(ModuleNode::getName)
|
||||
.filter(name -> !JAVA_BASE.equals(name))
|
||||
.toList();
|
||||
|
||||
List<String> exports = moduleNode.getSortedExports();
|
||||
moduleInfo.add(new ModuleInfo(rootDir, moduleNode.getName(), dependencies, exports));
|
||||
}
|
||||
else {
|
||||
LOG.debug("Skipped module " + moduleNode);
|
||||
LOG.info("Skipped module " + moduleNode + " because it doesn't have production source root");
|
||||
}
|
||||
myProgressTracker.increment();
|
||||
}
|
||||
return generatedCode;
|
||||
return moduleInfo;
|
||||
}
|
||||
|
||||
private static void createFiles(Project project, List<GeneratedCode> generatedCode, ProgressIndicator indicator) {
|
||||
private static void createFiles(Project project, List<ModuleInfo> moduleInfos, ProgressIndicator indicator) {
|
||||
indicator.setIndeterminate(false);
|
||||
int count = 0;
|
||||
double total = generatedCode.size();
|
||||
PsiFileFactory factory = PsiFileFactory.getInstance(project);
|
||||
for (GeneratedCode code : generatedCode) {
|
||||
ProgressManager.getInstance().executeNonCancelableSection(() -> {
|
||||
PsiFile file = factory.createFileFromText(PsiJavaModule.MODULE_INFO_FILE, JavaLanguage.INSTANCE, code.myText);
|
||||
PsiElement added = code.myRootDir.add(file);
|
||||
CodeStyleManager.getInstance(project).reformat(added);
|
||||
});
|
||||
double total = moduleInfos.size();
|
||||
FileTemplate template = FileTemplateManager.getInstance(project).getInternalTemplate(INTERNAL_MODULE_INFO_TEMPLATE_NAME);
|
||||
for (ModuleInfo moduleInfo : moduleInfos) {
|
||||
ProgressManager.getInstance().executeNonCancelableSection(() -> createFile(template, moduleInfo));
|
||||
indicator.setFraction(++count / total);
|
||||
}
|
||||
}
|
||||
|
||||
private static void createFile(FileTemplate template, ModuleInfo moduleInfo) {
|
||||
Project project = moduleInfo.myRootDir.getProject();
|
||||
Properties properties = FileTemplateManager.getInstance(project).getDefaultProperties();
|
||||
FileTemplateUtil.fillDefaultProperties(properties, moduleInfo.myRootDir);
|
||||
properties.setProperty(FileTemplate.ATTRIBUTE_NAME, MODULE_INFO_CLASS);
|
||||
try {
|
||||
PsiJavaFile moduleInfoFile =
|
||||
(PsiJavaFile)FileTemplateUtil.createFromTemplate(template, MODULE_INFO_FILE, properties, moduleInfo.myRootDir);
|
||||
PsiJavaModule javaModule = moduleInfoFile.getModuleDeclaration();
|
||||
LOG.assertTrue(javaModule != null, "module-info file should contain module declaration");
|
||||
|
||||
javaModule.setName(moduleInfo.myName);
|
||||
for (String export : moduleInfo.myExports) {
|
||||
PsiUtil.addModuleStatement(javaModule, PsiKeyword.EXPORTS + ' ' + export);
|
||||
}
|
||||
for (String dependency : moduleInfo.myRequires) {
|
||||
PsiUtil.addModuleStatement(javaModule, PsiKeyword.REQUIRES + ' ' + dependency);
|
||||
}
|
||||
CodeStyleManager.getInstance(project).reformat(moduleInfoFile);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info("Failed to create module-info.java in " + moduleInfo.myRootDir.getVirtualFile().getPath() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiJavaModule findDescriptor(PsiPackage psiPackage) {
|
||||
PsiManager psiManager = psiPackage.getManager();
|
||||
@@ -543,13 +563,20 @@ public class Java9GenerateModuleDescriptorsAction extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
private static class GeneratedCode {
|
||||
private static class ModuleInfo {
|
||||
final PsiDirectory myRootDir;
|
||||
final String myText;
|
||||
final String myName;
|
||||
final List<String> myRequires;
|
||||
final List<String> myExports;
|
||||
|
||||
private GeneratedCode(@NotNull PsiDirectory rootDir, @NotNull String text) {
|
||||
private ModuleInfo(@NotNull PsiDirectory rootDir,
|
||||
@NotNull String name,
|
||||
@NotNull List<String> requires,
|
||||
@NotNull List<String> exports) {
|
||||
myRootDir = rootDir;
|
||||
myText = text;
|
||||
myName = name;
|
||||
myRequires = requires;
|
||||
myExports = exports;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,4 +834,4 @@ generate.module.descriptors.build.required.message=Couldn't generate module desc
|
||||
generate.module.descriptors.scanning.message=Scanning Compiler Output
|
||||
generate.module.descriptors.collecting.message=Collecting Dependencies
|
||||
generate.module.descriptors.analysing.message=Analysing Dependencies
|
||||
generate.module.descriptors.preparing.message=Analysing Dependencies
|
||||
generate.module.descriptors.preparing.message=Preparing Code
|
||||
Reference in New Issue
Block a user