diff --git a/plugins/devkit/devkit-core/src/dom/impl/ModuleDescriptorNameConverter.java b/plugins/devkit/devkit-core/src/dom/impl/ModuleDescriptorNameConverter.java index 44f751b70a68..51b590dee2ca 100644 --- a/plugins/devkit/devkit-core/src/dom/impl/ModuleDescriptorNameConverter.java +++ b/plugins/devkit/devkit-core/src/dom/impl/ModuleDescriptorNameConverter.java @@ -6,18 +6,23 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; +import com.intellij.psi.search.GlobalSearchScopes; import com.intellij.psi.xml.XmlFile; +import com.intellij.util.Processor; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xml.ConvertContext; import com.intellij.util.xml.DomUtil; import com.intellij.util.xml.ElementPresentationManager; import com.intellij.util.xml.ResolvingConverter; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.devkit.DevKitBundle; @@ -30,10 +35,28 @@ import java.util.*; public class ModuleDescriptorNameConverter extends ResolvingConverter { + @NonNls + private static final String SUB_DESCRIPTOR_DELIMITER = "/"; + @NonNls + private static final String SUB_DESCRIPTOR_FILENAME_DELIMITER = "."; + @Override public String getErrorMessage(@Nullable String s, ConvertContext context) { + String value = StringUtil.notNullize(s); + + String filePath; + String moduleName; + if (isSubDescriptor(value)) { + filePath = getSubDescriptorFilePath(value); + moduleName = getSubDescriptorModuleName(value); + } + else { + filePath = getDescriptorFilePath(value); + moduleName = value; + } + return DevKitBundle.message("plugin.xml.convert.module.descriptor.name", - getDescriptorFilePath(s), s); + filePath, moduleName); } @Override @@ -42,9 +65,21 @@ public class ModuleDescriptorNameConverter extends ResolvingConverter getVariants(ConvertContext context) { final Module currentModule = context.getModule(); if (currentModule == null) return Collections.emptyList(); + final Project project = context.getProject(); + List variants = new SmartList<>(); final Set dependencies = getDependencies(currentModule); - List variants = new SmartList<>(); + dependencies.add(currentModule); for (Module module : dependencies) { - ContainerUtil.addIfNotNull(variants, findForModule(module)); + String moduleName = module.getName(); + processModuleSourceRoots(module, root -> { + final Collection plugins = DescriptorUtil.getPlugins(project, GlobalSearchScopes.directoryScope(project, root, false)); + variants.addAll(ContainerUtil.filter(plugins, plugin -> DomUtil.getFile(plugin).getName().startsWith(moduleName))); + return true; + }); } return variants; } @NotNull - private static Set getDependencies(Module currentModule) { + private static Set getDependencies(@NotNull Module currentModule) { final Set dependencies = new LinkedHashSet<>(); ModuleUtilCore.getDependencies(currentModule, dependencies); dependencies.remove(currentModule); @@ -87,22 +139,48 @@ public class ModuleDescriptorNameConverter extends ResolvingConverter resourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(JavaModuleSourceRootTypes.PRODUCTION); - for (VirtualFile root : resourceRoots) { - final VirtualFile candidate = root.findChild(getDescriptorFilePath(moduleName)); - if (candidate == null) continue; + private static IdeaPlugin findDescriptorFile(@NotNull Module module, @NotNull String filePath) { + Ref ideaPlugin = Ref.create(); + processModuleSourceRoots(module, root -> { + final VirtualFile candidate = root.findChild(filePath); + if (candidate == null) return true; final PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(candidate); if (DescriptorUtil.isPluginXml(psiFile)) { - return DescriptorUtil.getIdeaPlugin((XmlFile)psiFile); + ideaPlugin.set(DescriptorUtil.getIdeaPlugin((XmlFile)psiFile)); + return false; } + return true; + }); + return ideaPlugin.get(); + } + + private static void processModuleSourceRoots(@NotNull Module module, Processor processor) { + for (VirtualFile root : ModuleRootManager.getInstance(module).getSourceRoots(JavaModuleSourceRootTypes.PRODUCTION)) { + if (!processor.process(root)) return; } - return null; } @NotNull - private static String getDescriptorFilePath(String moduleName) { - return moduleName + ".xml"; + private static String getDescriptorFilePath(@NotNull String fileName) { + return fileName + ".xml"; + } + + private static boolean isSubDescriptor(@NotNull String value) { + return StringUtil.contains(value, SUB_DESCRIPTOR_DELIMITER); + } + + @NotNull + private static String getSubDescriptorModuleName(@NotNull String value) { + final String moduleName = StringUtil.substringBefore(value, SUB_DESCRIPTOR_DELIMITER); + assert moduleName != null : value; + return moduleName; + } + + @NotNull + private static String getSubDescriptorFilePath(@NotNull String value) { + final String moduleName = getSubDescriptorModuleName(value); + final String fileName = StringUtil.substringAfter(value, SUB_DESCRIPTOR_DELIMITER); + assert fileName != null : value; + return getDescriptorFilePath(moduleName + SUB_DESCRIPTOR_FILENAME_DELIMITER + fileName); } } diff --git a/plugins/devkit/devkit-core/src/dom/index/PluginIdDependenciesIndex.java b/plugins/devkit/devkit-core/src/dom/index/PluginIdDependenciesIndex.java index 477744af3681..6ab91a26279e 100644 --- a/plugins/devkit/devkit-core/src/dom/index/PluginIdDependenciesIndex.java +++ b/plugins/devkit/devkit-core/src/dom/index/PluginIdDependenciesIndex.java @@ -88,7 +88,8 @@ public final class PluginIdDependenciesIndex extends PluginXmlIndexBase getPluginAndDependsIds(Project project, Set files) { diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsDependencies-content.subDescriptor.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsDependencies-content.subDescriptor.xml new file mode 100644 index 000000000000..920485d75ddc --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsDependencies-content.subDescriptor.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsDependencies.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsDependencies.xml index 889f4e46552d..cda00961cb9c 100644 --- a/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsDependencies.xml +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsDependencies.xml @@ -5,6 +5,7 @@ + diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/anotherModule/anotherModule.secondary-descriptor.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/anotherModule/anotherModule.secondary-descriptor.xml new file mode 100644 index 000000000000..0bbcf8d4b598 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/anotherModule/anotherModule.secondary-descriptor.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/mainModule/META-INF/plugin.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/mainModule/META-INF/plugin.xml index cb7cf9b7bdef..ecaf4b557e07 100644 --- a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/mainModule/META-INF/plugin.xml +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/mainModule/META-INF/plugin.xml @@ -6,6 +6,12 @@ + + anotherModule/INVALID_VALUE"/> + + + mainModule/INVALID_VALUE"/> + invalidModuleName"/> diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/mainModule/mainModule.sub-descriptor.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/mainModule/mainModule.sub-descriptor.xml new file mode 100644 index 000000000000..0465c2432b62 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorHighlighting/mainModule/mainModule.sub-descriptor.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorModuleNameCompletion/anotherModule/anotherModule.secondary-descriptor.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorModuleNameCompletion/anotherModule/anotherModule.secondary-descriptor.xml new file mode 100644 index 000000000000..0bbcf8d4b598 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/contentDescriptorModuleNameCompletion/anotherModule/anotherModule.secondary-descriptor.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/dependencyDescriptorHighlighting/anotherModule/anotherModule.secondary-descriptor.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/dependencyDescriptorHighlighting/anotherModule/anotherModule.secondary-descriptor.xml new file mode 100644 index 000000000000..0bbcf8d4b598 --- /dev/null +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/dependencyDescriptorHighlighting/anotherModule/anotherModule.secondary-descriptor.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/dependencyDescriptorHighlighting/mainModule/META-INF/plugin.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/dependencyDescriptorHighlighting/mainModule/META-INF/plugin.xml index 02c8fabddf39..66526f7cc1d1 100644 --- a/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/dependencyDescriptorHighlighting/mainModule/META-INF/plugin.xml +++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/contentDependencyDescriptor/dependencyDescriptorHighlighting/mainModule/META-INF/plugin.xml @@ -5,6 +5,7 @@ + invalid.module"/> diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlContentDependencyDescriptorTest.java b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlContentDependencyDescriptorTest.java index 6d96cbccd5c0..1d73b8aed3fa 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlContentDependencyDescriptorTest.java +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlContentDependencyDescriptorTest.java @@ -11,11 +11,11 @@ import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PsiTestUtil; import com.intellij.testFramework.TestDataPath; -import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.util.ArrayUtil; import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NonNls; import org.jetbrains.idea.devkit.DevkitJavaTestsUtil; import org.jetbrains.idea.devkit.inspections.PluginXmlDomInspection; @@ -24,17 +24,14 @@ import java.util.List; @TestDataPath("$CONTENT_ROOT/testData/codeInsight/contentDependencyDescriptor") public class PluginXmlContentDependencyDescriptorTest extends JavaCodeInsightFixtureTestCase { + @NonNls + private static final String MAIN_MODULE_NAME = "mainModule"; + @Override protected String getBasePath() { return DevkitJavaTestsUtil.TESTDATA_PATH + "codeInsight/contentDependencyDescriptor"; } - @Override - protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception { - String editorUIApi = PathUtil.getJarPathForClass(AnAction.class); - moduleBuilder.addLibrary("editor-ui-api", editorUIApi); - } - public void testNonJetBrainsHighlighting() { doHighlightingTest(ArrayUtil.EMPTY_STRING_ARRAY); } @@ -50,13 +47,19 @@ public class PluginXmlContentDependencyDescriptorTest extends JavaCodeInsightFix public void testContentDescriptorModuleNameCompletion() { setupModules("anotherModule"); - List lookupElements = myFixture.getCompletionVariants("META-INF/plugin.xml"); - assertSameElements(lookupElements, "anotherModule"); + myFixture.configureFromTempProjectFile(MAIN_MODULE_NAME + "/META-INF/plugin.xml"); + myFixture.completeBasic(); + List lookupElements = myFixture.getLookupElementStrings(); + assertSameElements(lookupElements, "anotherModule", "anotherModule/secondary-descriptor"); final LookupElementPresentation anotherModule = getLookupElementPresentation("anotherModule"); assertEquals(AllIcons.Nodes.Module, anotherModule.getIcon()); + assertFalse(anotherModule.isItemTextBold()); //noinspection SpellCheckingInspection assertEquals("mypackage.subpackage", anotherModule.getTypeText()); + + final LookupElementPresentation anotherModuleSecondary = getLookupElementPresentation("anotherModule/secondary-descriptor"); + assertTrue(anotherModuleSecondary.isItemTextBold()); } public void testContentDescriptorHighlighting() { @@ -87,24 +90,30 @@ public class PluginXmlContentDependencyDescriptorTest extends JavaCodeInsightFix setupModules(dependencyModuleNames); myFixture.enableInspections(new PluginXmlDomInspection()); - myFixture.testHighlighting(true, false, false, "META-INF/plugin.xml"); + myFixture.testHighlighting(true, false, false, "mainModule/META-INF/plugin.xml"); } private void setupModules(String... dependencyModuleNames) { - String testName = getTestName(true); - myFixture.copyDirectoryToProject("/" + testName + "/mainModule", "/"); - - if (dependencyModuleNames.length == 0) return; + final Module mainModule = addModule(MAIN_MODULE_NAME); for (String moduleName : dependencyModuleNames) { - final VirtualFile dependencyModuleRoot = - myFixture.copyDirectoryToProject("/" + testName + "/" + moduleName, "/" + moduleName); - - Module dependencyModule = PsiTestUtil.addModule(getProject(), StdModuleTypes.JAVA, moduleName, dependencyModuleRoot); - ModuleRootModificationUtil.addDependency(getModule(), dependencyModule); + final Module dependencyModule = addModule(moduleName); + ModuleRootModificationUtil.addDependency(mainModule, dependencyModule); } } + private Module addModule(String moduleName) { + String testName = getTestName(true); + + final VirtualFile dependencyModuleRoot = + myFixture.copyDirectoryToProject("/" + testName + "/" + moduleName, "/" + moduleName); + + Module dependencyModule = PsiTestUtil.addModule(getProject(), StdModuleTypes.JAVA, moduleName, dependencyModuleRoot); + PsiTestUtil.addLibrary(dependencyModule, "editor-ui-api", PathUtil.getJarPathForClass(AnAction.class)); + + return dependencyModule; + } + private LookupElementPresentation getLookupElementPresentation(String lookupString) { final LookupElement lookupElement = ContainerUtil.find(myFixture.getLookupElements(), element -> element.getLookupString().equals(lookupString)); diff --git a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlFunctionalTest.groovy b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlFunctionalTest.groovy index 2493e8a7189f..a52f1ad6104e 100644 --- a/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlFunctionalTest.groovy +++ b/plugins/devkit/devkit-java-tests/testSrc/org/jetbrains/idea/devkit/codeInsight/PluginXmlFunctionalTest.groovy @@ -198,13 +198,20 @@ class PluginXmlFunctionalTest extends JavaCodeInsightFixtureTestCase { void testExtensionsDependencies() { addExtensionsModule("ExtensionsDependencies-module") + VirtualFile contentFile = addExtensionsModule("ExtensionsDependencies-content") + VirtualFile contentSubDescriptorFile = + myFixture.copyFileToProject("ExtensionsDependencies-content.subDescriptor.xml", + "/ExtensionsDependencies-content/ExtensionsDependencies-content.subDescriptor.xml") doHighlightingTest("ExtensionsDependencies.xml", "ExtensionsDependencies-plugin.xml") myFixture.configureFromExistingVirtualFile(contentFile) doHighlightingTest() + + myFixture.configureFromExistingVirtualFile(contentSubDescriptorFile) + doHighlightingTest() } private VirtualFile addExtensionsModule(String name) {