Optimize library kind detection and make it interruptible

This commit is contained in:
Dmitry Jemerov
2017-06-30 17:50:28 +02:00
parent 49252f6eec
commit 84418738a7
5 changed files with 38 additions and 28 deletions
@@ -32,6 +32,7 @@ import com.intellij.util.SmartList
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.caches.resolve.LibraryModuleInfo
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.idea.framework.CommonLibraryDetectionUtil
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected
@@ -210,7 +211,7 @@ class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo,
}
override val platform: TargetPlatform
get() = TargetPlatformDetector.getPlatform(library)
get() = CommonLibraryDetectionUtil.getLibraryPlatform(library)
override val sourcesModuleInfo: SourceForBinaryModuleInfo
get() = LibrarySourceInfo(project, library)
@@ -30,7 +30,7 @@ import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.idea.core.util.CachedValue
import org.jetbrains.kotlin.idea.core.util.getValue
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.framework.CommonLibraryDetectionUtil
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
@@ -72,7 +72,7 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend
val libraries = LinkedHashSet<Library>()
val sdks = LinkedHashSet<Sdk>()
val platform = TargetPlatformDetector.getPlatform(library)
val platform = CommonLibraryDetectionUtil.getLibraryPlatform(library)
for (module in getLibraryUsageIndex().modulesLibraryIsUsedIn[library]) {
if (!processedModules.add(module)) continue
@@ -84,7 +84,7 @@ class LibraryDependenciesCacheImpl(private val project: Project) : LibraryDepend
override fun visitLibraryOrderEntry(libraryOrderEntry: LibraryOrderEntry, value: Unit) {
val otherLibrary = libraryOrderEntry.library
if (otherLibrary != null && compatiblePlatforms(platform, TargetPlatformDetector.getPlatform(otherLibrary))) {
if (otherLibrary != null && compatiblePlatforms(platform, CommonLibraryDetectionUtil.getLibraryPlatform(otherLibrary))) {
libraries.add(otherLibrary)
}
}
@@ -16,31 +16,52 @@
package org.jetbrains.kotlin.idea.framework
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.vfs.JarFileSystem
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.caches.JarUserDataManager
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
object CommonLibraryDetectionUtil {
@JvmStatic
fun isCommonLibrary(library: Library): Boolean {
if (library is LibraryEx && library.isDisposed) return false
fun getLibraryPlatform(library: Library): TargetPlatform {
if (library is LibraryEx && library.isDisposed) return JvmPlatform
for (root in library.getFiles(OrderRootType.CLASSES)) {
val hasMetadata = JarUserDataManager.hasFileWithProperty(HasCommonKotlinMetadataInJar, root)
if (hasMetadata != null) {
return hasMetadata
ProgressManager.checkCanceled()
val jarRoot = JarFileSystem.getInstance().getVirtualFileForJar(root) ?: root
val hasCommonMetadata = JarUserDataManager.hasFileWithProperty(HasCommonKotlinMetadataInJar, jarRoot)
if (hasCommonMetadata == true) {
return TargetPlatform.Default
}
val hasJSMetadata = JarUserDataManager.hasFileWithProperty(KotlinJavaScriptLibraryDetectionUtil.HasKotlinJSMetadataInJar, root)
if (hasJSMetadata == true) {
return JsPlatform
}
if (!VfsUtilCore.processFilesRecursively(root) { !isKotlinMetadataFile(it) }) {
return true
var platform: TargetPlatform? = null
VfsUtilCore.processFilesRecursively(root) { file ->
if (file.fileType == JavaClassFileType.INSTANCE)
platform = JvmPlatform
else if (isKotlinMetadataFile(file))
platform = TargetPlatform.Default
else if (KotlinJavaScriptLibraryDetectionUtil.isJsFileWithMetadata(file))
platform = JsPlatform
platform == null
}
platform?.let { return it }
}
return false
return JvmPlatform
}
private fun isKotlinMetadataFile(file: VirtualFile): Boolean =
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.framework
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.Library
@@ -36,9 +37,10 @@ object KotlinJavaScriptLibraryDetectionUtil {
@JvmStatic fun isKotlinJavaScriptLibrary(classesRoots: List<VirtualFile>): Boolean {
// Prevent clashing with java runtime
if (JavaRuntimeDetectionUtil.getJavaRuntimeVersion(classesRoots) != null) return false
if (JavaRuntimeDetectionUtil.getRuntimeJar(classesRoots) != null) return false
classesRoots.forEach { root ->
ProgressManager.checkCanceled()
val hasMetadata = HasKotlinJSMetadataInJar.hasMetadataFromCache(root)
if (hasMetadata != null) {
return hasMetadata
@@ -52,7 +54,7 @@ object KotlinJavaScriptLibraryDetectionUtil {
return false
}
private fun isJsFileWithMetadata(file: VirtualFile): Boolean {
fun isJsFileWithMetadata(file: VirtualFile): Boolean {
if (!file.isDirectory && JavaScript.EXTENSION == file.extension) {
val content = try {
file.contentsToByteArray(false)
@@ -19,14 +19,10 @@ package org.jetbrains.kotlin.idea.project;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.framework.CommonLibraryDetectionUtil;
import org.jetbrains.kotlin.idea.framework.KotlinJavaScriptLibraryDetectionUtil;
import org.jetbrains.kotlin.js.resolve.JsPlatform;
import org.jetbrains.kotlin.psi.KtCodeFragment;
import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.psi.KtPsiFactoryKt;
@@ -75,14 +71,4 @@ public class TargetPlatformDetector {
return ProjectStructureUtil.getCachedPlatformForModule(module);
}
@NotNull
public static TargetPlatform getPlatform(@NotNull Library library) {
if (KotlinJavaScriptLibraryDetectionUtil.isKotlinJavaScriptLibrary(library)) {
return JsPlatform.INSTANCE;
}
if (CommonLibraryDetectionUtil.isCommonLibrary(library)) {
return TargetPlatform.Default.INSTANCE;
}
return JvmPlatform.INSTANCE;
}
}