diff --git a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml
index 8f392f5d2933..22802b04d90c 100644
--- a/plugins/devkit/devkit-core/resources/META-INF/plugin.xml
+++ b/plugins/devkit/devkit-core/resources/META-INF/plugin.xml
@@ -63,6 +63,7 @@
+
diff --git a/plugins/devkit/devkit-core/src/dom/impl/ExtensionsDomExtender.java b/plugins/devkit/devkit-core/src/dom/impl/ExtensionsDomExtender.java
index 32f8bf1ad64a..6b0150618e2c 100644
--- a/plugins/devkit/devkit-core/src/dom/impl/ExtensionsDomExtender.java
+++ b/plugins/devkit/devkit-core/src/dom/impl/ExtensionsDomExtender.java
@@ -3,12 +3,14 @@ package org.jetbrains.idea.devkit.dom.impl;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
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.xml.XmlFile;
+import com.intellij.psi.impl.include.FileIncludeManager;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomUtil;
import com.intellij.util.xml.XmlName;
@@ -19,8 +21,9 @@ import com.intellij.util.xml.reflect.DomExtender;
import com.intellij.util.xml.reflect.DomExtensionsRegistrar;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.devkit.dom.*;
+import org.jetbrains.idea.devkit.dom.index.PluginIdDependenciesIndex;
import org.jetbrains.idea.devkit.dom.index.PluginIdModuleIndex;
-import org.jetbrains.idea.devkit.util.DescriptorUtil;
+import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import java.util.*;
@@ -89,36 +92,42 @@ public class ExtensionsDomExtender extends DomExtender {
static Collection getDependencies(IdeaPlugin ideaPlugin) {
Set result = new HashSet<>();
-
result.add(PluginManagerCore.CORE_PLUGIN_ID);
for (Dependency dependency : ideaPlugin.getDependencies()) {
ContainerUtil.addIfNotNull(result, dependency.getStringValue());
}
- if (ideaPlugin.getPluginId() == null) {
- final VirtualFile file = DomUtil.getFile(ideaPlugin).getOriginalFile().getVirtualFile();
- if (file != null) {
- final String fileName = file.getName();
- if (!PluginManagerCore.PLUGIN_XML.equals(fileName)) {
- final VirtualFile mainPluginXml = file.findFileByRelativePath("../" + PluginManagerCore.PLUGIN_XML);
- if (mainPluginXml != null) {
- final PsiFile psiFile = PsiManager.getInstance(ideaPlugin.getManager().getProject()).findFile(mainPluginXml);
- if (psiFile instanceof XmlFile) {
- final XmlFile xmlFile = (XmlFile)psiFile;
- final IdeaPlugin mainPlugin = DescriptorUtil.getIdeaPlugin(xmlFile);
- if (mainPlugin != null) {
- ContainerUtil.addIfNotNull(result, mainPlugin.getPluginId());
- for (Dependency dependency : mainPlugin.getDependencies()) {
- ContainerUtil.addIfNotNull(result, dependency.getStringValue());
- }
- }
- }
- }
- }
- }
+ if (ideaPlugin.getPluginId() != null) {
+ return result;
}
+ final VirtualFile currentFile = DomUtil.getFile(ideaPlugin).getOriginalFile().getVirtualFile();
+ if (currentFile == null) {
+ return result;
+ }
+
+ final Project project = ideaPlugin.getManager().getProject();
+ final VirtualFile[] includingFiles = FileIncludeManager.getManager(project).getIncludingFiles(currentFile, false);
+
+ final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
+ Set includingAndDependsFiles = new SmartHashSet<>();
+ for (VirtualFile virtualFile : includingFiles) {
+ if (!fileIndex.isUnderSourceRootOfType(virtualFile, JavaModuleSourceRootTypes.PRODUCTION)) {
+ continue;
+ }
+ includingAndDependsFiles.add(virtualFile);
+ }
+
+ final Collection dependsToFiles = PluginIdDependenciesIndex.findDependsTo(project, currentFile);
+ includingAndDependsFiles.addAll(dependsToFiles);
+
+ if (includingAndDependsFiles.isEmpty()) {
+ return result;
+ }
+
+ final Set ids = PluginIdDependenciesIndex.getPluginAndDependsIds(project, includingAndDependsFiles);
+ result.addAll(ids);
return result;
}
}
diff --git a/plugins/devkit/devkit-core/src/dom/index/PluginIdDependenciesIndex.java b/plugins/devkit/devkit-core/src/dom/index/PluginIdDependenciesIndex.java
new file mode 100644
index 000000000000..eead1f7e8f7a
--- /dev/null
+++ b/plugins/devkit/devkit-core/src/dom/index/PluginIdDependenciesIndex.java
@@ -0,0 +1,98 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package org.jetbrains.idea.devkit.dom.index;
+
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.search.GlobalSearchScopesCore;
+import com.intellij.util.PathUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.SmartHashSet;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.devkit.dom.Dependency;
+import org.jetbrains.idea.devkit.dom.IdeaPlugin;
+
+import java.util.*;
+
+public class PluginIdDependenciesIndex extends ScalarIndexExtension {
+
+ private static final ID NAME = ID.create("PluginIdDependenciesIndex");
+
+ @NonNls
+ private static final String FILENAME_KEY_PREFIX = "___FILENAME___";
+
+ @NotNull
+ @Override
+ public KeyDescriptor getKeyDescriptor() {
+ return EnumeratorStringDescriptor.INSTANCE;
+ }
+
+ @NotNull
+ @Override
+ public ID getName() {
+ return NAME;
+ }
+
+ @NotNull
+ @Override
+ public DataIndexer getIndexer() {
+ return inputData -> {
+ IdeaPlugin plugin = RegistrationIndexer.obtainIdeaPlugin(inputData);
+ if (plugin == null) return Collections.emptyMap();
+
+ List ids = new SmartList<>();
+ ContainerUtil.addIfNotNull(ids, plugin.getPluginId());
+ for (Dependency dependency : plugin.getDependencies()) {
+ ContainerUtil.addIfNotNull(ids, dependency.getStringValue());
+
+ final String configFile = dependency.getConfigFile().getStringValue();
+ if (configFile != null) {
+ final String filename = PathUtil.getFileName(configFile);
+ ids.add(getDependsIndexingKey(filename));
+ }
+ }
+
+ return ContainerUtil.newHashMap(ids, Collections.nCopies(ids.size(), null));
+ };
+ }
+
+ @Override
+ public int getVersion() {
+ return 0;
+ }
+
+ @NotNull
+ @Override
+ public FileBasedIndex.InputFilter getInputFilter() {
+ return new DefaultFileTypeSpecificInputFilter(StdFileTypes.XML);
+ }
+
+ @Override
+ public boolean dependsOnFileContent() {
+ return true;
+ }
+
+ public static Set getPluginAndDependsIds(Project project, Set files) {
+ Set ids = new SmartHashSet<>();
+ for (VirtualFile file : files) {
+ final Map data = FileBasedIndex.getInstance().getFileData(NAME, file, project);
+ ids.addAll(ContainerUtil.filter(data.keySet(), s -> !StringUtil.startsWith(s, FILENAME_KEY_PREFIX)));
+ }
+ return ids;
+ }
+
+ public static Collection findDependsTo(Project project, VirtualFile file) {
+ return FileBasedIndex.getInstance().getContainingFiles(NAME, getDependsIndexingKey(file.getName()),
+ GlobalSearchScopesCore.projectProductionScope(project));
+ }
+
+ private static String getDependsIndexingKey(String filename) {
+ return FILENAME_KEY_PREFIX + filename;
+ }
+}
diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting-included.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting-included.xml
new file mode 100644
index 000000000000..0607282fd6e9
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting-included.xml
@@ -0,0 +1,11 @@
+
+
+
+ INVALID_VALUE"/>
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting-via-depends.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting-via-depends.xml
new file mode 100644
index 000000000000..46750c0705d1
--- /dev/null
+++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting-via-depends.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ INVALID_VALUE"/>
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting.xml b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting.xml
index ad86305e3591..111244128166 100644
--- a/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting.xml
+++ b/plugins/devkit/devkit-java-tests/testData/codeInsight/ExtensionsHighlighting.xml
@@ -1,4 +1,4 @@
-
+
com.intellij.myPlugin
JetBrains
1.0
@@ -12,6 +12,10 @@
com.intellij.custom
+ com.myplugin.depends
+
+
+
<myPlugin.ext/>
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 9c480d9c1807..4d110aba76e3 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
@@ -159,7 +159,12 @@ class PluginXmlFunctionalTest extends JavaCodeInsightFixtureTestCase {
"public class MyServiceDescriptor { @Attribute public String serviceImplementation; }")
configureByFile()
+ myFixture.copyFileToProject("ExtensionsHighlighting-included.xml")
+ myFixture.copyFileToProject("ExtensionsHighlighting-via-depends.xml",)
myFixture.checkHighlighting(true, false, false)
+
+ myFixture.testHighlighting("ExtensionsHighlighting-included.xml")
+ myFixture.testHighlighting("ExtensionsHighlighting-via-depends.xml")
}
void testDependsHighlighting() {