User: rednesto Date: 16 Dec 23 13:53 Revision: 3e28b815c5e5ba5239440e2267da8104f749da14 Summary: Fix translation notification slow access warnings Hopefully this doesn't break anything, I'll let it sit in nightly builds for now TeamCity URL: https://ci.mcdev.io/viewModification.html?tab=vcsModificationFiles&modId=8899&personal=false Index: src/main/kotlin/translations/TranslationEditorNotificationProvider.kt =================================================================== --- src/main/kotlin/translations/TranslationEditorNotificationProvider.kt (revision e9892662f1df48ceb7658bc9f7c56b0361ac17fd) +++ src/main/kotlin/translations/TranslationEditorNotificationProvider.kt (revision 3e28b815c5e5ba5239440e2267da8104f749da14) @@ -32,8 +32,9 @@ import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.fileEditor.FileEditor import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.Messages +import com.intellij.openapi.ui.MessageDialogBuilder import com.intellij.openapi.vfs.VirtualFile +import com.intellij.openapi.vfs.findPsiFile import com.intellij.psi.PsiManager import com.intellij.ui.EditorNotificationPanel import com.intellij.ui.EditorNotificationProvider @@ -49,62 +50,75 @@ override fun collectNotificationData( project: Project, file: VirtualFile, - ): Function = Function { createNotificationPanel(file, project) } - - private fun createNotificationPanel(file: VirtualFile, project: Project): InfoPanel? { - val locale = TranslationFiles.getLocale(file) - if (!show || !TranslationFiles.isTranslationFile(file) || locale == TranslationConstants.DEFAULT_LOCALE) { + ): Function? { + if (!show || !TranslationFiles.isTranslationFile(file) || TranslationFiles.isDefaultLocale(file)) { return null } val missingTranslations = getMissingTranslations(project, file) - if (missingTranslations.any()) { + if (missingTranslations.none()) { + return null + } + + val hasDefaultTranslations = TranslationIndex.hasDefaultTranslations(project, file.mcDomain) + val hasMcpModule = file.findPsiFile(project)?.findMcpModule() != null + return Function { + createNotificationPanel(missingTranslations, hasDefaultTranslations, hasMcpModule, file, project) + } + } + + private fun createNotificationPanel( + missingTranslations: Sequence, + hasDefaultTranslations: Boolean, + hasMcpModule: Boolean, + file: VirtualFile, + project: Project + ): InfoPanel { - val panel = InfoPanel() - panel.text = "Translation file doesn't match default one (${TranslationConstants.DEFAULT_LOCALE} locale)." - panel.createActionLabel( - "Add missing default entries (won't reflect changes in original English localization)", - ) { - val psi = PsiManager.getInstance(project).findFile(file) ?: return@createActionLabel - psi.applyWriteAction { - val fileEntries = missingTranslations.map { - TranslationFiles.FileEntry.Translation(it.key, it.text) - } - TranslationFiles.addAll(psi, fileEntries.asIterable()) - EditorNotifications.updateAll() - } + val panel = InfoPanel() + panel.text = "Translation file doesn't match default one (${TranslationConstants.DEFAULT_LOCALE} locale)." + panel.createActionLabel( + "Add missing default entries (won't reflect changes in original English localization)", + ) { + val psi = PsiManager.getInstance(project).findFile(file) ?: return@createActionLabel + psi.applyWriteAction { + val fileEntries = missingTranslations.map { + TranslationFiles.FileEntry.Translation(it.key, it.text) + } + TranslationFiles.addAll(psi, fileEntries.asIterable()) + EditorNotifications.updateAll() + } - if (psi.findMcpModule() == null) { + if (!hasMcpModule) { - // TranslationSorter.query requires an MCP module to work - return@createActionLabel - } + // TranslationSorter.query requires an MCP module to work + return@createActionLabel + } - val sort = Messages.showYesNoDialog( + val sort = MessageDialogBuilder.yesNo("Sort Translations", "Would you like to sort all translations now?") + .ask(project) + if (sort) { + try { + TranslationSorter.query( - project, + project, - "Would you like to sort all translations now?", - "Sort Translations", - Messages.getQuestionIcon(), + psi, + hasDefaultTranslations, + Ordering.LIKE_DEFAULT - ) + ) - if (sort == Messages.YES) { - try { - TranslationSorter.query(project, psi, Ordering.LIKE_DEFAULT) - } catch (e: Exception) { - Notification( - "Translations sorting error", - "Error sorting translations", - e.message ?: e.stackTraceToString(), - NotificationType.WARNING, - ).notify(project) - } - } - } - panel.createActionLabel("Hide notification") { - panel.isVisible = false - show = false - } - return panel - } + } catch (e: Exception) { + Notification( + "Translations sorting error", + "Error sorting translations", + e.message ?: e.stackTraceToString(), + NotificationType.WARNING, + ).notify(project) + } + } + } + panel.createActionLabel("Hide notification") { + panel.isVisible = false + show = false + } + return panel + } - return null - } private fun getMissingTranslations(project: Project, file: VirtualFile): Sequence { val domain = file.mcDomain Index: src/main/kotlin/translations/TranslationFiles.kt =================================================================== --- src/main/kotlin/translations/TranslationFiles.kt (revision e9892662f1df48ceb7658bc9f7c56b0361ac17fd) +++ src/main/kotlin/translations/TranslationFiles.kt (revision 3e28b815c5e5ba5239440e2267da8104f749da14) @@ -68,6 +68,9 @@ fun getLocale(file: VirtualFile?) = file?.nameWithoutExtension?.lowercase(Locale.ENGLISH) + fun isDefaultLocale(file: VirtualFile?) = + file?.nameWithoutExtension?.lowercase(Locale.ENGLISH) == TranslationConstants.DEFAULT_LOCALE + tailrec fun seekTranslation(element: PsiElement): PsiNamedElement? { // don't use elvis here, K2 doesn't think it's a tail recursive call if you do val res = toTranslation(element)?.let { element as? PsiNamedElement } Index: src/main/kotlin/translations/actions/SortTranslationsAction.kt =================================================================== --- src/main/kotlin/translations/actions/SortTranslationsAction.kt (revision e9892662f1df48ceb7658bc9f7c56b0361ac17fd) +++ src/main/kotlin/translations/actions/SortTranslationsAction.kt (revision 3e28b815c5e5ba5239440e2267da8104f749da14) @@ -21,7 +21,9 @@ package com.demonwav.mcdev.translations.actions import com.demonwav.mcdev.translations.TranslationFiles +import com.demonwav.mcdev.translations.index.TranslationIndex import com.demonwav.mcdev.translations.sorting.TranslationSorter +import com.demonwav.mcdev.util.mcDomain import com.intellij.notification.Notification import com.intellij.notification.NotificationType import com.intellij.openapi.actionSystem.AnAction @@ -34,7 +36,11 @@ val file = e.getData(LangDataKeys.PSI_FILE) ?: return try { - TranslationSorter.query(file.project, file) + TranslationSorter.query( + file.project, + file, + TranslationIndex.hasDefaultTranslations(file.project, file.virtualFile.mcDomain) + ) } catch (e: Exception) { Notification( "Translations sorting error", Index: src/main/kotlin/translations/index/TranslationIndex.kt =================================================================== --- src/main/kotlin/translations/index/TranslationIndex.kt (revision e9892662f1df48ceb7658bc9f7c56b0361ac17fd) +++ src/main/kotlin/translations/index/TranslationIndex.kt (revision 3e28b815c5e5ba5239440e2267da8104f749da14) @@ -63,6 +63,12 @@ fun getProjectDefaultTranslations(project: Project, domain: String? = null) = getProjectDefaultEntries(project, domain).flatten() + fun hasDefaultTranslations(project: Project, domain: String? = null): Boolean { + return !FileBasedIndex.getInstance().processValues(NAME, TranslationConstants.DEFAULT_LOCALE, null, { _, entry -> + return@processValues entry.sourceDomain == domain + }, GlobalSearchScope.projectScope(project)) + } + fun getTranslations(project: Project, file: VirtualFile): Sequence { return getEntries( GlobalSearchScope.fileScope(project, file), Index: src/main/kotlin/translations/inspections/NoTranslationInspection.kt =================================================================== --- src/main/kotlin/translations/inspections/NoTranslationInspection.kt (revision e9892662f1df48ceb7658bc9f7c56b0361ac17fd) +++ src/main/kotlin/translations/inspections/NoTranslationInspection.kt (revision 3e28b815c5e5ba5239440e2267da8104f749da14) @@ -65,6 +65,7 @@ val literalValue = literal.value as String val key = translation?.key?.copy(infix = literalValue)?.full ?: literalValue val result = Messages.showInputDialog( + project, "Enter default value for \"$key\":", "Create Translation", Messages.getQuestionIcon(), Index: src/main/kotlin/translations/sorting/TranslationSorter.kt =================================================================== --- src/main/kotlin/translations/sorting/TranslationSorter.kt (revision e9892662f1df48ceb7658bc9f7c56b0361ac17fd) +++ src/main/kotlin/translations/sorting/TranslationSorter.kt (revision 3e28b815c5e5ba5239440e2267da8104f749da14) @@ -21,15 +21,17 @@ package com.demonwav.mcdev.translations.sorting import com.demonwav.mcdev.translations.Translation -import com.demonwav.mcdev.translations.TranslationConstants import com.demonwav.mcdev.translations.TranslationFiles import com.demonwav.mcdev.translations.actions.TranslationSortOrderDialog import com.demonwav.mcdev.translations.index.TranslationIndex +import com.demonwav.mcdev.util.applyWriteAction import com.demonwav.mcdev.util.lexicographical import com.demonwav.mcdev.util.mcDomain import com.demonwav.mcdev.util.runWriteAction import com.intellij.openapi.project.Project +import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiFile +import com.intellij.psi.codeStyle.CodeStyleManager import java.util.TreeSet object TranslationSorter { @@ -39,18 +41,22 @@ private val descendingComparator = ascendingComparator.reversed() - fun query(project: Project, file: PsiFile, defaultSelection: Ordering = Ordering.ASCENDING) { - val domain = file.virtualFile.mcDomain - val defaultEntries = TranslationIndex.getProjectDefaultTranslations(project, domain) - val noDefaults = defaultEntries.none() - val isDefaultFile = TranslationFiles.getLocale(file.virtualFile) == TranslationConstants.DEFAULT_LOCALE - val (order, comments) = TranslationSortOrderDialog.show(noDefaults || isDefaultFile, defaultSelection) + fun query( + project: Project, + file: PsiFile, + hasDefaultTranslations: Boolean, + defaultSelection: Ordering = Ordering.ASCENDING + ) { + val (order, comments) = TranslationSortOrderDialog.show( + hasDefaultTranslations || TranslationFiles.isDefaultLocale(file.virtualFile), + defaultSelection + ) if (order == null) { return } - sort(project, file, order, comments) + file.applyWriteAction { sort(project, file, order, comments) } } private fun sort(project: Project, file: PsiFile, ordering: Ordering, keepComments: Int) { @@ -91,8 +97,14 @@ file.runWriteAction { TranslationFiles.replaceAll(file, sorted.asIterable()) + val documentManager = PsiDocumentManager.getInstance(project) + val document = documentManager.getDocument(file) + if (document != null) { + documentManager.commitDocument(document) + CodeStyleManager.getInstance(project).reformat(file, true) - } - } + } + } + } private fun sortByTemplate( project: Project,