diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageAction.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageAction.java index 052af274048a..dc2c7bab1b2e 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageAction.java @@ -55,10 +55,11 @@ import java.awt.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.function.Consumer; public class CreateDirectoryOrPackageAction extends AnAction implements DumbAware { - private static final ExtensionPointName EP = new ExtensionPointName<>("com.intellij.createDirectoryCompletionContributor"); + public static final ExtensionPointName EP = new ExtensionPointName<>("com.intellij.createDirectoryCompletionContributor"); @TestOnly public static final DataKey TEST_DIRECTORY_NAME_KEY = DataKey.create("CreateDirectoryOrPackageAction.testName"); @@ -166,7 +167,7 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar } } - private static JBPopup createLightWeightPopup(@Nullable Project project, + private JBPopup createLightWeightPopup(@Nullable Project project, @NlsContexts.PopupTitle String title, String initialText, @NotNull PsiDirectory directory, @@ -230,7 +231,7 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar } @NotNull - private static List collectSuggestedDirectories(@NotNull PsiDirectory directory) { + protected List collectSuggestedDirectories(@NotNull PsiDirectory directory) { List variants = new ArrayList<>(); VirtualFile vDir = directory.getVirtualFile(); @@ -255,7 +256,10 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar Icon icon = handler == null ? null : handler.getRootIcon(); if (icon == null) icon = AllIcons.Nodes.Folder; - variants.add(new CompletionItem(contributor, relativePath, icon, variant.rootType)); + CompletionItem completionItem = new CompletionItem(contributor, relativePath, icon, variant.rootType); + if (!variants.contains(completionItem)) { + variants.add(completionItem); + } } } @@ -325,7 +329,7 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar return createdDirectories; } - private static final class CompletionItem { + protected static final class CompletionItem { @NotNull final CreateDirectoryCompletionContributor contributor; @NotNull final String relativePath; @@ -346,6 +350,23 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar this.displayText = FileUtil.toSystemDependentName(relativePath); this.icon = icon; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CompletionItem that = (CompletionItem)o; + return contributor.equals(that.contributor) && + relativePath.equals(that.relativePath) && + Objects.equals(rootType, that.rootType) && + displayText.equals(that.displayText) && + Objects.equals(icon, that.icon); + } + + @Override + public int hashCode() { + return Objects.hash(contributor, relativePath, rootType, displayText, icon); + } } private static class DirectoriesWithCompletionPopupPanel extends NewItemWithTemplatesPopupPanel { diff --git a/platform/lang-impl/testSources/com/intellij/ide/actions/CreateDirectoryOrPackageActionTest.kt b/platform/lang-impl/testSources/com/intellij/ide/actions/CreateDirectoryOrPackageActionTest.kt new file mode 100644 index 000000000000..573c1fee4bf5 --- /dev/null +++ b/platform/lang-impl/testSources/com/intellij/ide/actions/CreateDirectoryOrPackageActionTest.kt @@ -0,0 +1,31 @@ +// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.ide.actions + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.psi.PsiDirectory +import com.intellij.testFramework.LightPlatformTestCase +import com.intellij.testFramework.registerExtension +import org.jetbrains.annotations.Nls +import org.jetbrains.jps.model.java.JavaSourceRootType +import org.junit.Assert +import org.junit.Test + +class CreateDirectoryOrPackageActionTest : LightPlatformTestCase() { + @Test + fun `test no duplicates in suggested directories`() { + ApplicationManager.getApplication().registerExtension(CreateDirectoryOrPackageAction.EP, object : CreateDirectoryCompletionContributor { + override fun getDescription(): @Nls(capitalization = Nls.Capitalization.Sentence) String { + return "Mock Source Directories" + } + + override fun getVariants(directory: PsiDirectory): Collection { + return listOf(CreateDirectoryCompletionContributor.Variant("src\\main\\resources", JavaSourceRootType.SOURCE), + CreateDirectoryCompletionContributor.Variant("src\\main\\resources", JavaSourceRootType.SOURCE)) + } + }, testRootDisposable) + val action = CreateDirectoryOrPackageAction() + val directory = psiManager.findDirectory(getSourceRoot())!! + val items = action.collectSuggestedDirectories(directory) + Assert.assertEquals(1, items.size) + } +} \ No newline at end of file