From 691068c0c25318a28b3bdd6637f06f2066265fbc Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 29 Sep 2014 16:39:56 +0400 Subject: [PATCH] Implement LibraryDependenciesCache --- .../intellij/openapi/roots/annotations.xml | 6 +- .../resolve/LibraryDependenciesCache.kt | 106 ++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/LibraryDependenciesCache.kt diff --git a/annotations/com/intellij/openapi/roots/annotations.xml b/annotations/com/intellij/openapi/roots/annotations.xml index f0bdec252df..5308bd0edbe 100644 --- a/annotations/com/intellij/openapi/roots/annotations.xml +++ b/annotations/com/intellij/openapi/roots/annotations.xml @@ -22,7 +22,11 @@ - + + + diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/LibraryDependenciesCache.kt b/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/LibraryDependenciesCache.kt new file mode 100644 index 00000000000..6037282135e --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/caches/resolve/LibraryDependenciesCache.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2014 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. + */ + +package org.jetbrains.jet.plugin.caches.resolve + +import com.intellij.openapi.project.Project +import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.libraries.Library +import com.intellij.util.containers.MultiMap +import com.intellij.psi.util.CachedValuesManager +import com.intellij.psi.util.CachedValueProvider +import com.intellij.openapi.roots.ProjectRootModificationTracker +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.LibraryOrderEntry +import com.intellij.openapi.roots.OrderEntry +import com.intellij.openapi.roots.ModuleOrderEntry +import com.intellij.openapi.util.Condition +import java.util.LinkedHashSet +import com.intellij.openapi.roots.RootPolicy +import org.jetbrains.jet.utils.addIfNotNull +import com.intellij.openapi.projectRoots.Sdk +import com.intellij.openapi.roots.JdkOrderEntry +import com.intellij.openapi.roots.ModuleSourceOrderEntry + +public class LibraryDependenciesCache(private val project: Project) { + + //NOTE: used LibraryRuntimeClasspathScope as reference + public fun getLibrariesAndSdksUsedWith(library: Library): Pair, List> { + val processedModules = LinkedHashSet() + val condition = Condition() { orderEntry -> + if (orderEntry is ModuleOrderEntry) { + val module = orderEntry.getModule() + module != null && module !in processedModules + } + else { + true + } + } + + val libraries = LinkedHashSet() + val sdks = LinkedHashSet() + + fun collectLibrariesAndSdksAcrossDependencies(module: Module) { + if (!processedModules.add(module)) return + + ModuleRootManager.getInstance(module).orderEntries().recursively().satisfying(condition).process(object : RootPolicy() { + override fun visitModuleSourceOrderEntry(moduleSourceOrderEntry: ModuleSourceOrderEntry?, value: Unit?): Unit? { + processedModules.addIfNotNull(moduleSourceOrderEntry?.getOwnerModule()) + return Unit + } + + public override fun visitLibraryOrderEntry(libraryOrderEntry: LibraryOrderEntry?, value: Unit?): Unit? { + libraries.addIfNotNull(libraryOrderEntry?.getLibrary()) + return Unit + } + + override fun visitJdkOrderEntry(jdkOrderEntry: JdkOrderEntry?, value: Unit?): Unit? { + sdks.addIfNotNull(jdkOrderEntry?.getJdk()) + return Unit + } + }, Unit) + } + + getLibraryUsageIndex().modulesLibraryIsUsedIn[library].forEach { module -> collectLibrariesAndSdksAcrossDependencies(module) } + + return Pair(libraries.toList(), sdks.toList()) + } + + public fun getLibraryUsageIndex(): LibraryUsageIndex { + return CachedValuesManager.getManager(project).getCachedValue(project) { + CachedValueProvider.Result(LibraryUsageIndex(), ProjectRootModificationTracker.getInstance(project)) + }!! + } + + private inner class LibraryUsageIndex { + val modulesLibraryIsUsedIn: MultiMap = MultiMap.createSet(); + { + ModuleManager.getInstance(project).getModules().forEach { + module -> + ModuleRootManager.getInstance(module).getOrderEntries().forEach { + entry -> + if (entry is LibraryOrderEntry) { + val library = entry.getLibrary() + if (library != null) { + modulesLibraryIsUsedIn.putValue(library, module) + } + } + } + } + } + } +} \ No newline at end of file