[java] refactoring: extract findExportedDependenciesReachableViaThisDependencyOnly to a separate class and convert to Kotlin

GitOrigin-RevId: 0eb718a866a8e06f7ce78128599abf7ae89bbef3
This commit is contained in:
Nikolay Chashnikov
2021-04-30 12:02:07 +03:00
committed by intellij-monorepo-bot
parent 4ba07a4238
commit d5644380a4
4 changed files with 80 additions and 73 deletions

View File

@@ -48,9 +48,9 @@ class AnalyzeModuleDependencyAction extends AnAction {
if (selectedEntry instanceof ModuleOrderEntry) {
Module depModule = ((ModuleOrderEntry)selectedEntry).getModule();
LOG.assertTrue(depModule != null);
Map<OrderEntry, OrderEntry> additionalDependencies = JavaProjectRootsUtil
.findExportedDependenciesReachableViaThisDependencyOnly(myPanel.getRootModel().getModule(),
depModule, modulesProvider);
Map<OrderEntry, OrderEntry> additionalDependencies =
JavaProjectDependenciesAnalyzer.findExportedDependenciesReachableViaThisDependencyOnly(myPanel.getRootModel().getModule(),
depModule, modulesProvider);
additionalScopes = new LinkedHashMap<>();
for (Map.Entry<OrderEntry, OrderEntry> entry : additionalDependencies.entrySet()) {
additionalScopes.put(getScopeForOrderEntry(entry.getKey()), entry.getValue());

View File

@@ -0,0 +1,74 @@
// Copyright 2000-2021 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.roots
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.impl.OrderEntryUtil
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.util.Condition
object JavaProjectDependenciesAnalyzer {
/**
* Returns order entries which are exported to `module` from its direct `dependency`, and which aren't available via other dependencies.
* @return map from a direct or transitive dependency of `dependency` parameter to a corresponding direct dependency of `dependency` parameter.
*/
@JvmStatic
fun findExportedDependenciesReachableViaThisDependencyOnly(module: Module,
dependency: Module,
rootModelProvider: RootModelProvider): Map<OrderEntry, OrderEntry> {
val moduleOrderEntry = OrderEntryUtil.findModuleOrderEntry(rootModelProvider.getRootModel(module), dependency)
?: throw IllegalArgumentException("Cannot find dependency from $module to $dependency")
val withoutThisDependency = Condition { entry: OrderEntry ->
!(entry is ModuleOrderEntry && entry.getOwnerModule() == module && dependency == entry.module)
}
var enumerator = rootModelProvider.getRootModel(module).orderEntries()
.satisfying(withoutThisDependency)
.using(rootModelProvider)
.compileOnly()
.recursively().exportedOnly()
if (moduleOrderEntry.scope.isForProductionCompile) {
enumerator = enumerator.productionOnly()
}
val reachableModules = LinkedHashSet<Module>()
val reachableLibraries = LinkedHashSet<Library>()
enumerator.forEach { entry ->
when (entry) {
is ModuleSourceOrderEntry -> reachableModules.add(entry.getOwnerModule())
is ModuleOrderEntry -> entry.module?.let { reachableModules.add(it) }
is LibraryOrderEntry -> entry.library?.let { reachableLibraries.add(it) }
}
true
}
val result = LinkedHashMap<OrderEntry, OrderEntry>()
rootModelProvider.getRootModel(dependency)
.orderEntries().using(rootModelProvider).exportedOnly().withoutSdk().withoutModuleSourceEntries()
.forEach { direct ->
when {
direct is ModuleOrderEntry -> {
val depModule = direct.module
if (depModule != null && depModule !in reachableModules) {
result[direct] = direct
rootModelProvider.getRootModel(depModule).orderEntries().using(rootModelProvider).exportedOnly().withoutSdk().recursively()
.forEach { transitive ->
if (transitive is ModuleSourceOrderEntry && transitive.ownerModule !in reachableModules && depModule != transitive.ownerModule
|| transitive is LibraryOrderEntry && transitive.library != null && transitive.library !in reachableLibraries) {
if (transitive !in result) {
result[transitive] = direct
}
}
true
}
}
}
direct is LibraryOrderEntry && direct.library != null && direct.library !in reachableLibraries -> {
result[direct] = direct
}
}
true
}
return result
}
}

View File

@@ -5,9 +5,6 @@ import com.intellij.ide.projectView.impl.ProjectRootsUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.impl.OrderEntryUtil;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.NonPhysicalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiCodeFragment;
@@ -21,7 +18,8 @@ import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import org.jetbrains.jps.model.java.JavaResourceRootProperties;
import org.jetbrains.jps.model.java.JavaSourceRootProperties;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
public final class JavaProjectRootsUtil {
public static boolean isOutsideJavaSourceRoot(@Nullable PsiFile psiFile) {
@@ -81,71 +79,6 @@ public final class JavaProjectRootsUtil {
return new NonGeneratedSourceScope(baseScope, project);
}
/**
* Returns order entries which are exported to {@code module} from its direct {@code dependency}, and which aren't available via other dependencies.
* @return map from a direct or transitive dependency of {@code dependency} parameter to a corresponding direct dependency of {@code dependency} parameter.
*/
@NotNull
public static Map<OrderEntry, OrderEntry> findExportedDependenciesReachableViaThisDependencyOnly(@NotNull Module module,
@NotNull Module dependency,
@NotNull RootModelProvider rootModelProvider) {
ModuleOrderEntry moduleOrderEntry = OrderEntryUtil.findModuleOrderEntry(rootModelProvider.getRootModel(module), dependency);
if (moduleOrderEntry == null) {
throw new IllegalArgumentException("Cannot find dependency from " + module + " to " + dependency);
}
Condition<OrderEntry> withoutThisDependency = entry -> !(entry instanceof ModuleOrderEntry && entry.getOwnerModule().equals(module) &&
dependency.equals(((ModuleOrderEntry)entry).getModule()));
OrderEnumerator enumerator =
rootModelProvider.getRootModel(module).orderEntries()
.satisfying(withoutThisDependency)
.using(rootModelProvider)
.compileOnly()
.recursively().exportedOnly();
if (moduleOrderEntry.getScope().isForProductionCompile()) {
enumerator = enumerator.productionOnly();
}
Set<Module> reachableModules = new HashSet<>();
Set<Library> reachableLibraries = new HashSet<>();
enumerator.forEach(entry -> {
if (entry instanceof ModuleSourceOrderEntry) {
reachableModules.add(entry.getOwnerModule());
}
else if (entry instanceof ModuleOrderEntry) {
ContainerUtil.addIfNotNull(reachableModules, ((ModuleOrderEntry)entry).getModule());
}
else if (entry instanceof LibraryOrderEntry) {
ContainerUtil.addIfNotNull(reachableLibraries, ((LibraryOrderEntry)entry).getLibrary());
}
return true;
});
Map<OrderEntry, OrderEntry> result = new LinkedHashMap<>();
rootModelProvider.getRootModel(dependency).orderEntries().using(rootModelProvider).exportedOnly().withoutSdk().withoutModuleSourceEntries().forEach(direct -> {
if (direct instanceof ModuleOrderEntry) {
Module depModule = ((ModuleOrderEntry)direct).getModule();
if (depModule != null && !reachableModules.contains(depModule)) {
result.put(direct, direct);
rootModelProvider.getRootModel(depModule).orderEntries().using(rootModelProvider).exportedOnly().withoutSdk().recursively().forEach(transitive -> {
if (transitive instanceof ModuleSourceOrderEntry && !reachableModules.contains(transitive.getOwnerModule()) && !depModule.equals(transitive.getOwnerModule())
|| transitive instanceof LibraryOrderEntry && ((LibraryOrderEntry)transitive).getLibrary() != null && !reachableLibraries.contains(((LibraryOrderEntry)transitive).getLibrary())) {
if (!result.containsKey(transitive)) {
result.put(transitive, direct);
}
}
return true;
});
}
}
else if (direct instanceof LibraryOrderEntry && ((LibraryOrderEntry)direct).getLibrary() != null && !reachableLibraries.contains(((LibraryOrderEntry)direct).getLibrary())) {
result.put(direct, direct);
}
return true;
});
return result;
}
private static final class NonGeneratedSourceScope extends DelegatingGlobalSearchScope {
@NotNull private final Project myProject;

View File

@@ -115,6 +115,6 @@ public class FindReachableExportedDependenciesTest extends JavaModuleTestCase {
private Set<Map.Entry<OrderEntry, OrderEntry>> findReachableViaThisDependencyOnly(Module a, Module b) {
ModulesProvider rootModelProvider = DefaultModulesProvider.createForProject(myProject);
return JavaProjectRootsUtil.findExportedDependenciesReachableViaThisDependencyOnly(a, b, rootModelProvider).entrySet();
return JavaProjectDependenciesAnalyzer.findExportedDependenciesReachableViaThisDependencyOnly(a, b, rootModelProvider).entrySet();
}
}