mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] upgrade module path: resolve (IDEA-189693)
Uses relative location of files on module dependency list to disambiguate upgradeable modules.
This commit is contained in:
+53
-5
@@ -5,6 +5,8 @@ import com.intellij.ProjectTopics;
|
||||
import com.intellij.ide.highlighter.JavaClassFileType;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
@@ -28,6 +30,7 @@ import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
@@ -172,18 +175,18 @@ public class JavaFileManagerImpl implements JavaFileManager, Disposable {
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PsiJavaModule> findModules(@NotNull String moduleName, @NotNull GlobalSearchScope scope) {
|
||||
scope = new LibSrcExcludingScope(scope);
|
||||
GlobalSearchScope excludingScope = new LibSrcExcludingScope(scope);
|
||||
|
||||
Collection<PsiJavaModule> named = JavaModuleNameIndex.getInstance().get(moduleName, myManager.getProject(), scope);
|
||||
Collection<PsiJavaModule> named = JavaModuleNameIndex.getInstance().get(moduleName, myManager.getProject(), excludingScope);
|
||||
if (!named.isEmpty()) {
|
||||
return named;
|
||||
return upgradeModules(sortModules(named, scope), moduleName, scope);
|
||||
}
|
||||
|
||||
Collection<VirtualFile> jars = JavaAutoModuleNameIndex.getFilesByKey(moduleName, scope);
|
||||
Collection<VirtualFile> jars = JavaAutoModuleNameIndex.getFilesByKey(moduleName, excludingScope);
|
||||
if (!jars.isEmpty()) {
|
||||
List<PsiJavaModule> automatic = jars.stream().map(f -> LightJavaModule.getModule(myManager, f)).collect(Collectors.toList());
|
||||
if (!automatic.isEmpty()) {
|
||||
return automatic;
|
||||
return sortModules(automatic, scope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,4 +206,49 @@ public class JavaFileManagerImpl implements JavaFileManager, Disposable {
|
||||
return super.contains(file) && !myIndex.isInLibrarySource(file);
|
||||
}
|
||||
}
|
||||
|
||||
private static Collection<PsiJavaModule> sortModules(Collection<PsiJavaModule> modules, GlobalSearchScope scope) {
|
||||
if (modules.size() > 1) {
|
||||
List<PsiJavaModule> list = new ArrayList<>(modules);
|
||||
list.sort((m1, m2) -> scope.compare(virtualFile(m2), virtualFile(m1)));
|
||||
modules = list;
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
|
||||
private static VirtualFile virtualFile(PsiJavaModule m) {
|
||||
return m instanceof LightJavaModule ? ((LightJavaModule)m).getRootVirtualFile() : m.getContainingFile().getVirtualFile();
|
||||
}
|
||||
|
||||
private static Collection<PsiJavaModule> upgradeModules(Collection<PsiJavaModule> modules, String moduleName, GlobalSearchScope scope) {
|
||||
if (modules.size() > 1 && PsiJavaModule.UPGRADEABLE.contains(moduleName) && scope instanceof ModuleWithDependenciesScope) {
|
||||
Module module = ((ModuleWithDependenciesScope)scope).getModule();
|
||||
boolean isModular = Stream.of(ModuleRootManager.getInstance(module).getSourceRoots(true))
|
||||
.filter(scope::contains)
|
||||
.anyMatch(root -> root.findChild(PsiJavaModule.MODULE_INFO_FILE) != null);
|
||||
if (isModular) {
|
||||
List<PsiJavaModule> list = new ArrayList<>(modules);
|
||||
|
||||
ModuleFileIndex index = ModuleRootManager.getInstance(module).getFileIndex();
|
||||
for (ListIterator<PsiJavaModule> i = list.listIterator(); i.hasNext(); ) {
|
||||
PsiJavaModule candidate = i.next();
|
||||
if (index.getOrderEntryForFile(candidate.getContainingFile().getVirtualFile()) instanceof JdkOrderEntry) {
|
||||
if (i.previousIndex() > 0) {
|
||||
i.remove(); // not at the top -> is upgraded
|
||||
}
|
||||
else {
|
||||
list = Collections.singletonList(candidate); // shadows subsequent modules
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list.size() != modules.size()) {
|
||||
modules = list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return modules;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
+2
-2
@@ -33,7 +33,7 @@ class ModuleCompletionTest : LightJava9ModulesCodeInsightFixtureTestCase() {
|
||||
|
||||
fun testRequiresBare() =
|
||||
variants("module M { requires <caret>",
|
||||
"transitive", "static", "M2", "java.base", "java.se", "java.xml.bind", "javax.doomed",
|
||||
"transitive", "static", "M2", "java.base", "java.se", "java.xml.bind", "java.xml.ws", "javax.doomed",
|
||||
"lib.multi.release", "lib.named", "lib.auto", "lib.claimed")
|
||||
fun testRequiresTransitive() = complete("module M { requires tr<caret> }", "module M { requires transitive <caret> }")
|
||||
fun testRequiresSimpleName() = complete("module M { requires M<caret> }", "module M { requires M2;<caret> }")
|
||||
@@ -46,7 +46,7 @@ class ModuleCompletionTest : LightJava9ModulesCodeInsightFixtureTestCase() {
|
||||
fun testExportsTo() = complete("module M { exports pkg.other <caret> }", "module M { exports pkg.other to <caret> }")
|
||||
fun testExportsToList() =
|
||||
variants("module M { exports pkg.other to <caret> }",
|
||||
"M2", "java.base", "java.se", "java.xml.bind", "javax.doomed", "lib.multi.release", "lib.named")
|
||||
"M2", "java.base", "java.se", "java.xml.bind", "java.xml.ws", "javax.doomed", "lib.multi.release", "lib.named")
|
||||
fun testExportsToUnambiguous() = complete("module M { exports pkg.other to M<caret> }", "module M { exports pkg.other to M2<caret> }")
|
||||
|
||||
fun testUsesPrefixed() = complete("module M { uses p<caret> }", "module M { uses pkg.<caret> }")
|
||||
|
||||
@@ -321,6 +321,15 @@ class ModuleHighlightingTest : LightJava9ModulesCodeInsightFixtureTestCase() {
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun testUpgradeableModuleOnModulePath() {
|
||||
myFixture.enableInspections(DeprecationInspection(), MarkedForRemovalInspection())
|
||||
highlight("""
|
||||
module M {
|
||||
requires <error descr="'java.xml.bind' is deprecated and marked for removal">java.xml.bind</error>;
|
||||
requires java.xml.ws;
|
||||
}""".trimIndent())
|
||||
}
|
||||
|
||||
fun testLinearModuleGraphBug() {
|
||||
addFile("module-info.java", "module M6 { requires M7; }", M6)
|
||||
addFile("module-info.java", "module M7 { }", M7)
|
||||
|
||||
+8
@@ -74,6 +74,14 @@ object MultiModuleJava9ProjectDescriptor : DefaultLightProjectDescriptor() {
|
||||
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-multi-release.jar!/")
|
||||
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib_invalid_1_2.jar!/")
|
||||
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-xml-bind.jar!/")
|
||||
|
||||
ModuleRootModificationUtil.addModuleLibrary(main, "${libDir}/lib-xml-ws.jar!/")
|
||||
ModuleRootModificationUtil.updateModel(main) {
|
||||
val entries = it.orderEntries.toMutableList()
|
||||
entries.add(0, entries.last()) // places an upgrade module before the JDK
|
||||
entries.removeAt(entries.size - 1)
|
||||
it.rearrangeOrderEntries(entries.toTypedArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
+6
-27
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// Copyright 2000-2018 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 com.intellij.openapi.module.impl.scopes;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -44,9 +30,7 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope {
|
||||
@interface ScopeConstant {}
|
||||
|
||||
private final Module myModule;
|
||||
@ScopeConstant
|
||||
private final int myOptions;
|
||||
|
||||
private final @ScopeConstant int myOptions;
|
||||
private final ProjectFileIndexImpl myProjectFileIndex;
|
||||
|
||||
private volatile Set<Module> myModules;
|
||||
@@ -56,11 +40,9 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope {
|
||||
super(module.getProject());
|
||||
myModule = module;
|
||||
myOptions = options;
|
||||
|
||||
myProjectFileIndex = (ProjectFileIndexImpl)ProjectRootManager.getInstance(module.getProject()).getFileIndex();
|
||||
|
||||
final LinkedHashSet<VirtualFile> roots = ContainerUtil.newLinkedHashSet();
|
||||
|
||||
Set<VirtualFile> roots = ContainerUtil.newLinkedHashSet();
|
||||
if (hasOption(CONTENT)) {
|
||||
Set<Module> modules = calcModules();
|
||||
myModules = ContainerUtil.newTroveSet(modules);
|
||||
@@ -87,10 +69,7 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope {
|
||||
private OrderEnumerator getOrderEnumeratorForOptions() {
|
||||
OrderEnumerator en = ModuleRootManager.getInstance(myModule).orderEntries();
|
||||
en.recursively();
|
||||
|
||||
if (hasOption(COMPILE_ONLY)) {
|
||||
en.exportedOnly().compileOnly();
|
||||
}
|
||||
if (hasOption(COMPILE_ONLY)) en.exportedOnly().compileOnly();
|
||||
if (!hasOption(LIBRARIES)) en.withoutLibraries().withoutSdk();
|
||||
if (!hasOption(MODULES)) en.withoutDepModules();
|
||||
if (!hasOption(TESTS)) en.productionOnly();
|
||||
@@ -101,7 +80,7 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope {
|
||||
private Set<Module> calcModules() {
|
||||
// In the case that hasOption(CONTENT), the order of the modules set matters for
|
||||
// ordering the content roots, so use a LinkedHashSet
|
||||
final Set<Module> modules = ContainerUtil.newLinkedHashSet();
|
||||
Set<Module> modules = ContainerUtil.newLinkedHashSet();
|
||||
OrderEnumerator en = getOrderEnumeratorForOptions();
|
||||
en.forEach(each -> {
|
||||
if (each instanceof ModuleOrderEntry) {
|
||||
@@ -215,4 +194,4 @@ public class ModuleWithDependenciesScope extends GlobalSearchScope {
|
||||
" include other modules:" + hasOption(MODULES) +
|
||||
" include tests:" + hasOption(TESTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user