diff --git a/CHANGELOG.md b/CHANGELOG.md index d8d3f0633..6f24c227a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). ## 5.4.0 +### Added + +- Clear notifications for the process status of URN generation [#2486](https://github.com/magento/magento2-phpstorm-plugin/pull/2486) + ### Fixed - Fixed Upgrade Compatibility Tool [#2482](https://github.com/magento/magento2-phpstorm-plugin/pull/2482) @@ -13,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). Fixed UI icon references. Updated Run command. - java.lang.Throwable: Assertion failed: Do not use PsiElement for popup model. See PsiTargetNavigator [#2485](https://github.com/magento/magento2-phpstorm-plugin/pull/2485) +- Slow operations are prohibited on EDT [#2486](https://github.com/magento/magento2-phpstorm-plugin/pull/2486) ### Changed diff --git a/src/main/java/com/magento/idea/magento2plugin/project/RegenerateUrnMapListener.java b/src/main/java/com/magento/idea/magento2plugin/project/RegenerateUrnMapListener.java index 704239db7..908067823 100644 --- a/src/main/java/com/magento/idea/magento2plugin/project/RegenerateUrnMapListener.java +++ b/src/main/java/com/magento/idea/magento2plugin/project/RegenerateUrnMapListener.java @@ -7,6 +7,8 @@ import com.intellij.javaee.ExternalResourceManager; import com.intellij.javaee.ExternalResourceManagerEx; +import com.intellij.notification.NotificationGroupManager; +import com.intellij.notification.NotificationType; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; @@ -20,8 +22,9 @@ import com.magento.idea.magento2plugin.magento.packages.MagentoModule; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.ArrayDeque; import java.util.Collection; -import java.util.Stack; +import java.util.Deque; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,6 +32,7 @@ class RegenerateUrnMapListener extends MouseAdapter { protected final Project project; private static final String FRAMEWORK = "urn:magento:framework:"; private static final String MODULE = "urn:magento:module:"; + private static final String COMPOSER_MODEL = "magento2-library"; public RegenerateUrnMapListener(final @NotNull Project project) { @@ -43,51 +47,31 @@ public RegenerateUrnMapListener(final @NotNull Project project) { */ @Override public void mouseClicked(final MouseEvent event) { - final ExternalResourceManager externalResourceManager = + final ExternalResourceManager manager = ExternalResourceManager.getInstance(); final PsiManager psiManager = PsiManager.getInstance(project); final MagentoComponentManager componentManager = MagentoComponentManager.getInstance(project); - final Collection<VirtualFile> xsdFiles = FilenameIndex.getAllFilesByExt(project, "xsd"); - final Collection<MagentoComponent> components = componentManager.getAllComponents(); - ApplicationManager.getApplication().runWriteAction( new Runnable() { @Override public void run() { - - for (final VirtualFile virtualFile: xsdFiles) { - final PsiFile psiFile = psiManager.findFile(virtualFile); - if (psiFile == null) { - continue; - } - - final MagentoComponent xsdOwner = - findComponentForXsd(psiFile, components); - if (xsdOwner == null) { - continue; - } - - final String urnKey = buildUrnKeyForFile(psiFile, xsdOwner); - if (urnKey == null) { + final Collection<VirtualFile> xsdFiles + = FilenameIndex.getAllFilesByExt(project, "xsd"); + final Collection<MagentoComponent> components + = componentManager.getAllComponents(); + int processedFileCount = 0; + + for (final VirtualFile file : xsdFiles) { + if (handleXsdFile(file, components, psiManager, manager)) { continue; } - // we need to attach resource to a project scope - // but with ExternalResourceManager itself it's not - // possible unfortunately - if (externalResourceManager instanceof ExternalResourceManagerEx) { - ((ExternalResourceManagerEx)externalResourceManager).addResource( - urnKey, virtualFile.getCanonicalPath(), project - ); - } else { - externalResourceManager.addResource( - urnKey, - virtualFile.getCanonicalPath() - ); - } + processedFileCount++; } + + showNotification(processedFileCount); } } ); @@ -95,6 +79,87 @@ public void run() { super.mouseClicked(event); } + /** + * Handles an XSD file by associating it with a resource in the ExternalResourceManager + * and resolves its context with relevant components. + * + * @param virtualFile The virtual file representing the XSD file to be handled. + * @param components A collection of MagentoComponent objects used to determine the + * component context for the XSD file. + * @param psiManager The PsiManager used to resolve the virtual file into a PsiFile. + * @param externalResourceManager The manager used to add or map external resources. + * @return {@code true} if the XSD file was processed successfully or required no actions; + * {@code false} if the file was successfully associated with a URN resource. + */ + private boolean handleXsdFile( + final VirtualFile virtualFile, + final Collection<MagentoComponent> components, + final PsiManager psiManager, + final ExternalResourceManager externalResourceManager + ) { + final PsiFile psiFile = psiManager.findFile(virtualFile); + if (psiFile == null) { + return true; + } + + final MagentoComponent xsdOwner = + findComponentForXsd(psiFile, components); + if (xsdOwner == null) { + return true; + } + + final String urnKey = buildUrnKeyForFile(psiFile, xsdOwner); + if (urnKey == null) { + return true; + } + + // we need to attach resource to a project scope + // but with ExternalResourceManager itself it's not + // possible unfortunately + if (externalResourceManager instanceof ExternalResourceManagerEx) { + ((ExternalResourceManagerEx) externalResourceManager).addResource( + urnKey, virtualFile.getCanonicalPath(), project + ); + } else { + externalResourceManager.addResource( + urnKey, + virtualFile.getCanonicalPath() + ); + } + return false; + } + + /** + * Displays a notification based on the number of processed files for URN mapping generation. + * If the {@code processedFileCount} is greater than zero, an information notification is shown + * indicating the successful completion of URN map generation. Otherwise, a warning notification + * is displayed indicating the failure of URN map generation. + * + * @param processedFileCount The number of files successfully processed for URN map generation. + */ + @SuppressWarnings("PMD.UseNotifyAllInsteadOfNotify") + private void showNotification(final int processedFileCount) { + if (processedFileCount > 0) { + NotificationGroupManager.getInstance() + .getNotificationGroup("Magento Notifications") + .createNotification( + "URN map generation completed", + "Processed " + processedFileCount + " URN mappings.", + NotificationType.INFORMATION + ) + .notify(project); + } else { + NotificationGroupManager.getInstance() + .getNotificationGroup("Magento Notifications") + .createNotification( + "URN map generation failed", + "No URN mappings were generated. Check your configuration.", + NotificationType.WARNING + ) + .notify(project); + } + } + @Nullable protected MagentoComponent findComponentForXsd( final @NotNull PsiFile psiFile, @@ -120,7 +185,7 @@ protected String buildUrnKeyForFile( prefix = MODULE + ((MagentoModule)magentoComponent).getMagentoName() + ":"; } else { final ComposerPackageModel composerPackageModel = magentoComponent.getComposerModel(); - if ("magento2-library".equals(composerPackageModel.getType())) { + if (COMPOSER_MODEL.equals(composerPackageModel.getType())) { prefix = FRAMEWORK; } } @@ -129,7 +194,7 @@ protected String buildUrnKeyForFile( return null; } - final Stack<String> relativePath = new Stack<>(); + final Deque<String> relativePath = new ArrayDeque<>(); relativePath.push(psiFile.getName()); final PsiManager psiManager = magentoComponent.getDirectory().getManager(); @@ -144,7 +209,7 @@ protected String buildUrnKeyForFile( } final StringBuilder stringBuilder = new StringBuilder(prefix); - while (!relativePath.empty()) { + while (!relativePath.isEmpty()) { stringBuilder.append(relativePath.pop()); } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index e49617b2a..70db1c7fb 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -688,6 +688,10 @@ <searchScopesProvider implementation="com.magento.idea.magento2plugin.lang.psi.search.MagentoSearchScopesProvider"/> <multiHostInjector implementation="com.magento.idea.magento2plugin.lang.injection.UiComponentSyntaxInjector"/> + + <notificationGroup + id="Magento Notifications" + displayType="BALLOON" /> </extensions> <extensions defaultExtensionNs="com.jetbrains.php">