diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaModuleNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaModuleNameIndex.java index ea77bd10daea..f13a406fc82e 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaModuleNameIndex.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaModuleNameIndex.java @@ -20,16 +20,26 @@ package com.intellij.psi.impl.java.stubs.index; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiJavaModule; import com.intellij.psi.impl.search.JavaSourceFilterScope; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.stubs.StringStubIndexExtension; import com.intellij.psi.stubs.StubIndex; import com.intellij.psi.stubs.StubIndexKey; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.FileBasedIndex; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static com.intellij.openapi.util.text.StringUtil.compareVersionNumbers; public class JavaModuleNameIndex extends StringStubIndexExtension { private static final JavaModuleNameIndex ourInstance = new JavaModuleNameIndex(); @@ -51,7 +61,46 @@ public class JavaModuleNameIndex extends StringStubIndexExtension @Override public Collection get(@NotNull String name, @NotNull Project project, @NotNull GlobalSearchScope scope) { - return StubIndex.getElements(getKey(), name, project, new JavaSourceFilterScope(scope), PsiJavaModule.class); + Collection modules = StubIndex.getElements(getKey(), name, project, new JavaSourceFilterScope(scope), PsiJavaModule.class); + if (modules.size() > 1) { + modules = filterVersions(project, modules); + } + return modules; + } + + private static Collection filterVersions(Project project, Collection modules) { + Map filter = ContainerUtil.newHashMap(); + Set screened = ContainerUtil.newHashSet(); + + ProjectFileIndex index = ProjectFileIndex.SERVICE.getInstance(project); + for (PsiJavaModule module : modules) { + VirtualFile file = module.getContainingFile().getVirtualFile(); + if (index.isInLibraryClasses(file)) { + VirtualFile classRoot = index.getClassRootForFile(file); + if (classRoot != null) { + PsiJavaModule previous = filter.get(classRoot); + if (previous == null) { + filter.put(classRoot, module); + } + else if (compareVersionNumbers(fileVersion(file), fileVersion(previous.getContainingFile().getVirtualFile())) < 0) { + filter.put(classRoot, module); + screened.add(previous); + } + else { + screened.add(module); + } + } + } + } + + return screened.isEmpty() ? modules : modules.stream().filter(module -> !screened.contains(module)).collect(Collectors.toList()); + } + + private static final Pattern MULTI_RESOLVE_VERSION = Pattern.compile("/META-INF/versions/([^/]+)/" + PsiJavaModule.MODULE_INFO_CLS_FILE); + + private static String fileVersion(VirtualFile file) { + Matcher matcher = MULTI_RESOLVE_VERSION.matcher(file.getPath()); + return matcher.find() ? matcher.group(1) : "0"; } @Override diff --git a/java/java-tests/testData/codeInsight/jigsaw/lib-multi-release.jar b/java/java-tests/testData/codeInsight/jigsaw/lib-multi-release.jar new file mode 100644 index 000000000000..d6a717b19a70 Binary files /dev/null and b/java/java-tests/testData/codeInsight/jigsaw/lib-multi-release.jar differ diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt index 50186729027a..af13c4403f20 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ModuleHighlightingTest.kt @@ -73,6 +73,7 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() { requires M2; requires M3; requires lib.auto; + requires lib.multi.release; }""".trimIndent()) } diff --git a/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt b/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt index 18197f71b68e..db6919c98268 100644 --- a/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt +++ b/java/java-tests/testSrc/com/intellij/testFramework/fixtures/MultiModuleJava9ProjectDescriptor.kt @@ -75,6 +75,7 @@ object MultiModuleJava9ProjectDescriptor : DefaultLightProjectDescriptor() { ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-named-1.0.jar!/") ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-auto-1.0.jar!/") ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-auto-2.0.jar!/") + ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-multi-release.jar!/") } }