[devkit] suggest module name prefix in 'IJ Module' action based on the selected directory (IJPL-182501)

GitOrigin-RevId: 33f346eb7332c3dae5530e6b0e0599b475e468fc
This commit is contained in:
Nikolay Chashnikov
2025-05-20 17:00:12 +00:00
committed by intellij-monorepo-bot
parent a78c1b6cca
commit 2e311368af
2 changed files with 37 additions and 3 deletions
@@ -6,10 +6,13 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.EDT
import com.intellij.openapi.progress.currentThreadCoroutineScope
import com.intellij.openapi.project.DumbAware
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
internal class NewIjModuleAction : AnAction(), DumbAware {
@@ -33,6 +36,11 @@ internal class NewIjModuleAction : AnAction(), DumbAware {
private suspend fun actionPerformed(dc: DataContext) {
val project = dc.getData(CommonDataKeys.PROJECT) ?: return
val root = dc.getData(CommonDataKeys.VIRTUAL_FILE) ?: return
val name = askForModuleName(project)
val suggestedNamePrefix = withContext(Dispatchers.IO) {
suggestModuleNamePrefix(root, project)
}
val name = withContext(Dispatchers.EDT) {
askForModuleName(project, suggestedNamePrefix)
}
createIjModule(root, name)
}
@@ -7,6 +7,7 @@ import com.intellij.lang.LangBundle
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.application.backgroundWriteAction
import com.intellij.openapi.application.readAction
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.IntelliJProjectUtil.isIntelliJPlatformProject
import com.intellij.openapi.project.Project
@@ -45,10 +46,10 @@ internal fun isActionEnabled(dc: DataContext): Boolean {
return !ProjectFileIndex.getInstance(project).isInSource(virtualFile)
}
internal suspend fun askForModuleName(project: Project): @Nls String {
internal suspend fun askForModuleName(project: Project, suggestedNamePrefix: String): @Nls String {
val contentPanel = NewItemSimplePopupPanel()
val nameField: JTextField = contentPanel.textField
nameField.text = "intellij."
nameField.text = suggestedNamePrefix
val popup: JBPopup = NewItemPopupUtil.createNewItemPopup(message("scaffolding.new.ij.module"), contentPanel, nameField)
return suspendCancellableCoroutine { continuation ->
contentPanel.applyAction = Consumer { event: InputEvent? ->
@@ -76,6 +77,31 @@ internal suspend fun askForModuleName(project: Project): @Nls String {
}
}
internal suspend fun suggestModuleNamePrefix(parentDir: VirtualFile, project: Project): String {
return readAction {
val fileIndex = ProjectFileIndex.getInstance(project)
val parentContentRoot = fileIndex.getContentRootForFile(parentDir)
if (parentContentRoot == parentDir) {
val module = fileIndex.getModuleForFile(parentContentRoot)
if (module != null) {
return@readAction "${module.name.removeSuffix(".plugin").removeSuffix(".main").removeSuffix(".core")}."
}
}
if (parentDir.isDirectory) {
val siblingModuleNames = parentDir.children
.asSequence()
.filter { fileIndex.getContentRootForFile(it) == it }
.mapNotNull { fileIndex.getModuleForFile(it)?.name }
val commonPrefix = siblingModuleNames.reduceOrNull { acc, item -> acc.commonPrefixWith(item) } ?: ""
val suggestion = commonPrefix.substringBeforeLast('.', "")
if (suggestion.isNotEmpty()) {
return@readAction "$suggestion."
}
}
"intellij."
}
}
internal suspend fun createIjModule(vRoot: VirtualFile, moduleName: String) {
val project = instance<Project>()
val files = prepareFiles(vRoot.toNioPath(), moduleName)