Provide library kind for common libraries; get rid of autodetection

This commit is contained in:
Dmitry Jemerov
2017-07-12 15:39:22 +02:00
parent c7e85ea28f
commit 0fa09adf17
14 changed files with 103 additions and 241 deletions
@@ -1,141 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.idea.caches
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.Key
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.io.URLUtil
import org.jetbrains.kotlin.idea.util.application.runReadAction
import java.util.concurrent.atomic.AtomicBoolean
object JarUserDataManager {
enum class State {
INIT,
HAS_FILE,
NO_FILE
}
val version = 2
val fileAttributeService: FileAttributeService? = ServiceManager.getService(FileAttributeService::class.java)
fun register(counter: JarBooleanPropertyCounter) {
fileAttributeService?.register(counter.key.toString(), version)
}
fun hasFileWithProperty(counter: JarBooleanPropertyCounter, file: VirtualFile): Boolean? {
val localJarFile = JarFileSystemUtil.findLocalJarFile(file) ?: return null
val stored = localJarFile.getUserData(counter.key)
if (stored != null) {
if (localJarFile.timeStamp == stored.timestamp) {
return stored.hasFileWithProperty
}
}
if (stored == null && fileAttributeService != null) {
val savedData = fileAttributeService.readEnumAttribute(counter.key.toString(), localJarFile, State::class.java)
if (savedData != null) {
val hasFileWithProperty = savedData.value == State.HAS_FILE
storeUserData(counter, localJarFile, hasFileWithProperty, savedData.timeStamp)
if (localJarFile.timeStamp == savedData.timeStamp) {
return hasFileWithProperty
}
}
}
val jarFileRoot = JarFileSystemUtil.findJarFileRoot(file) ?: return null
scheduleJarProcessing(counter, jarFileRoot, localJarFile)
return null
}
private fun scheduleJarProcessing(counter: JarBooleanPropertyCounter, jarFile: VirtualFile, localJarFile: VirtualFile) {
val userData = localJarFile.getUserData(counter.key)
if (userData != null && localJarFile.timeStamp == userData.timestamp) return
storeUserData(counter, localJarFile, null)
ApplicationManager.getApplication().executeOnPooledThread {
runReadAction {
val data = localJarFile.getUserData(counter.key)
if (data != null &&
((data.hasFileWithProperty != null && localJarFile.timeStamp == data.timestamp) || !data.isProcessStarted.compareAndSet(false, true))) {
// Processing has started in some other thread or is already finished
return@runReadAction
}
val hasFileWithProperty = !VfsUtilCore.processFilesRecursively(jarFile) { file ->
!counter.hasProperty(file)
}
val state = if (hasFileWithProperty) State.HAS_FILE else State.NO_FILE
val savedData = fileAttributeService?.writeEnumAttribute(counter.key.toString(), localJarFile, state)
storeUserData(counter, localJarFile, hasFileWithProperty, (savedData?.timeStamp ?: localJarFile.timeStamp))
}
}
}
private fun storeUserData(counter: JarBooleanPropertyCounter, localJarFile: VirtualFile,
hasFileWithProperty: Boolean?, timestamp: Long? = null) {
assert((timestamp == null) == (hasFileWithProperty == null)) { "Using empty timestamp is only allowed for storing not counted value" }
localJarFile.putUserData(counter.key,
PropertyData(hasFileWithProperty, timestamp ?: localJarFile.timeStamp, isProcessStarted = AtomicBoolean(false)))
}
object JarFileSystemUtil {
fun findJarFileRoot(inJarFile: VirtualFile): VirtualFile? {
if (!inJarFile.url.startsWith("jar://")) return null
var jarFile = inJarFile
while (jarFile.parent != null) jarFile = jarFile.parent
return jarFile
}
fun findLocalJarFile(inJarFile: VirtualFile): VirtualFile? {
if (!inJarFile.url.startsWith("jar://")) return null
val path = inJarFile.path
val jarSeparatorIndex = path.indexOf(URLUtil.JAR_SEPARATOR)
assert(jarSeparatorIndex >= 0) { "Path passed to JarFileSystem must have jar separator '!/': $path" }
val localPath = path.substring(0, jarSeparatorIndex)
return StandardFileSystems.local().findFileByPath(localPath)
}
}
data class PropertyData(val hasFileWithProperty: Boolean?, val timestamp: Long, val isProcessStarted: AtomicBoolean)
abstract class JarBooleanPropertyCounter(keyName: String) {
val key: Key<PropertyData> = Key.create<PropertyData>(keyName)
abstract fun hasProperty(file: VirtualFile): Boolean
override fun toString() = "Counter: $key"
}
}
@@ -32,7 +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.framework.getLibraryPlatform
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
import org.jetbrains.kotlin.idea.util.isInSourceContentWithoutInjected
@@ -211,7 +211,7 @@ class LibraryInfo(val project: Project, val library: Library) : IdeaModuleInfo,
}
override val platform: TargetPlatform
get() = CommonLibraryDetectionUtil.getLibraryPlatform(library)
get() = 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.framework.CommonLibraryDetectionUtil
import org.jetbrains.kotlin.idea.framework.getLibraryPlatform
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 = CommonLibraryDetectionUtil.getLibraryPlatform(library)
val platform = 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, CommonLibraryDetectionUtil.getLibraryPlatform(otherLibrary))) {
if (otherLibrary != null && compatiblePlatforms(platform, getLibraryPlatform(otherLibrary))) {
libraries.add(otherLibrary)
}
}
@@ -1,70 +0,0 @@
/*
* Copyright 2010-2017 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.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 getLibraryPlatform(library: Library): TargetPlatform {
library as? LibraryEx ?: return JvmPlatform
if (library.isDisposed) return JvmPlatform
if (library.kind is JSLibraryKind) return JsPlatform
for (root in library.getFiles(OrderRootType.CLASSES)) {
ProgressManager.checkCanceled()
val jarRoot = JarFileSystem.getInstance().getVirtualFileForJar(root) ?: root
val hasCommonMetadata = JarUserDataManager.hasFileWithProperty(HasCommonKotlinMetadataInJar, jarRoot)
if (hasCommonMetadata == true) {
return TargetPlatform.Default
}
var platform: TargetPlatform? = null
VfsUtilCore.processFilesRecursively(root) { file ->
when {
file.fileType == JavaClassFileType.INSTANCE -> platform = JvmPlatform
isKotlinMetadataFile(file) -> platform = TargetPlatform.Default
}
platform == null
}
platform?.let { return it }
}
return JvmPlatform
}
private fun isKotlinMetadataFile(file: VirtualFile): Boolean =
!file.isDirectory &&
file.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION
object HasCommonKotlinMetadataInJar : JarUserDataManager.JarBooleanPropertyCounter(HasCommonKotlinMetadataInJar::class.simpleName!!) {
override fun hasProperty(file: VirtualFile) = isKotlinMetadataFile(file)
}
}
@@ -32,9 +32,29 @@
package org.jetbrains.kotlin.idea.framework
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import com.intellij.openapi.roots.libraries.DummyLibraryProperties
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
object JSLibraryKind : PersistentLibraryKind<DummyLibraryProperties>("kotlin.js") {
override fun createDefaultProperties() = DummyLibraryProperties.INSTANCE!!
}
}
object CommonLibraryKind : PersistentLibraryKind<DummyLibraryProperties>("kotlin.common") {
override fun createDefaultProperties() = DummyLibraryProperties.INSTANCE!!
}
fun getLibraryPlatform(library: Library): TargetPlatform {
library as? LibraryEx ?: return JvmPlatform
if (library.isDisposed) return JvmPlatform
return when (library.kind) {
JSLibraryKind -> JsPlatform
CommonLibraryKind -> TargetPlatform.Default
else -> JvmPlatform
}
}
@@ -25,9 +25,8 @@ import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsPr
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.impl.libraries.LibraryEx
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.configuration.detectPlatformByPlugin
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.libraryKind
class KotlinAndroidGradleLibraryDataService : AbstractProjectDataService<JavaProject, Void>() {
override fun getTargetDataKey() = AndroidProjectKeys.JAVA_PROJECT
@@ -39,12 +38,12 @@ class KotlinAndroidGradleLibraryDataService : AbstractProjectDataService<JavaPro
modelsProvider: IdeModifiableModelsProvider
) {
for (dataNode in toImport) {
val platform = detectPlatformByPlugin(dataNode.parent as DataNode<ModuleData>)
if (platform == TargetPlatformKind.JavaScript) {
val targetLibraryKind = detectPlatformByPlugin(dataNode.parent as DataNode<ModuleData>)?.libraryKind
if (targetLibraryKind != null) {
for (dep in dataNode.data.jarLibraryDependencies) {
val library = modelsProvider.getLibraryByName(dep.name) as LibraryEx? ?: continue
if (library.kind == null) {
(modelsProvider.getModifiableLibraryModel(library) as LibraryEx.ModifiableModelEx).kind = JSLibraryKind
(modelsProvider.getModifiableLibraryModel(library) as LibraryEx.ModifiableModelEx).kind = targetLibraryKind
}
}
}
@@ -45,7 +45,7 @@ import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.idea.facet.*
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.libraryKind
import org.jetbrains.kotlin.idea.maven.configuration.KotlinMavenConfigurator
import java.io.File
import java.util.*
@@ -90,12 +90,12 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
if (changes.dependencies) {
scheduleDownloadStdlibSources(mavenProject, module)
val platform = detectPlatformByExecutions(mavenProject)
if (platform == TargetPlatformKind.JavaScript) {
val targetLibraryKind = detectPlatformByExecutions(mavenProject)?.libraryKind
if (targetLibraryKind != null) {
modifiableModelsProvider.getModifiableRootModel(module).orderEntries().forEachLibrary { library ->
if ((library as LibraryEx).kind == null) {
val model = modifiableModelsProvider.getModifiableLibraryModel(library) as LibraryEx.ModifiableModelEx
model.kind = JSLibraryKind
model.kind = targetLibraryKind
}
true
}
@@ -26,8 +26,8 @@ import com.intellij.openapi.roots.impl.libraries.LibraryEx
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.codeInsight.gradle.GradleImportingTestCase
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.junit.Assert
import java.io.File
@@ -594,7 +594,7 @@ class KotlinMavenImporterTest : MavenImportingTestCase() {
val rootManager = ModuleRootManager.getInstance(getModule("project"))
val stdlib = rootManager.orderEntries.filterIsInstance<LibraryOrderEntry>().single().library
GradleImportingTestCase.assertEquals(JSLibraryKind, (stdlib as LibraryEx).kind)
assertEquals(JSLibraryKind, (stdlib as LibraryEx).kind)
}
fun testFacetSplitConfiguration() {
@@ -1099,7 +1099,7 @@ class KotlinMavenImporterTest : MavenImportingTestCase() {
createProjectSubDirs("src/main/kotlin", "src/main/kotlin.jvm", "src/test/kotlin", "src/test/kotlin.jvm")
importProject("""
<groupId>test</groupId>
<groupId>test</groupId>0
<artifactId>project</artifactId>
<version>1.0.0</version>
@@ -1135,6 +1135,10 @@ class KotlinMavenImporterTest : MavenImportingTestCase() {
assertImporterStatePresent()
Assert.assertEquals(TargetPlatformKind.Common, facetSettings.targetPlatformKind)
val rootManager = ModuleRootManager.getInstance(getModule("project"))
val stdlib = rootManager.orderEntries.filterIsInstance<LibraryOrderEntry>().single().library
assertEquals(CommonLibraryKind, (stdlib as LibraryEx).kind)
}
fun testJvmDetectionByConflictingGoalsAndJvmStdlib() {
+1
View File
@@ -823,6 +823,7 @@
<usageContextPanelProvider implementation="org.jetbrains.kotlin.idea.slicer.KotlinUsageContextDataOutflowPanel$Provider"/>
<library.type implementation="org.jetbrains.kotlin.idea.framework.JSLibraryType"/>
<library.type implementation="org.jetbrains.kotlin.idea.framework.CommonLibraryType"/>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.FoldInitializerAndIfToElvisIntention</className>
@@ -29,9 +29,7 @@ import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.searches.IndexPatternSearch;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.caches.JarUserDataManager;
import org.jetbrains.kotlin.idea.debugger.filter.DebuggerFiltersUtilKt;
import org.jetbrains.kotlin.idea.framework.CommonLibraryDetectionUtil;
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinTodoSearcher;
import org.jetbrains.kotlin.utils.PathUtil;
@@ -61,8 +59,6 @@ public class PluginStartupComponent implements ApplicationComponent {
ThreadTrackerPatcherForTeamCityTesting.INSTANCE.patchThreadTracker();
}
JarUserDataManager.INSTANCE.register(CommonLibraryDetectionUtil.HasCommonKotlinMetadataInJar.INSTANCE);
DebuggerFiltersUtilKt.addKotlinStdlibDebugFilterIfNeeded();
try {
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
import org.jetbrains.kotlin.idea.facet.*
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.libraryKind
import org.jetbrains.kotlin.idea.inspections.gradle.findAll
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedKotlinStdlibVersionByModuleData
@@ -110,10 +110,10 @@ class KotlinGradleLibraryDataService : AbstractProjectDataService<LibraryData, V
val projectDataNode = libraryDataNode.parent!! as DataNode<ProjectData>
val ownerModule = findOwnerModule(libraryDataNode.data, projectDataNode) ?: continue
val targetPlatform = detectPlatformByPlugin(ownerModule)
if (targetPlatform == TargetPlatformKind.JavaScript) {
val targetLibraryKind = detectPlatformByPlugin(ownerModule)?.libraryKind
if (targetLibraryKind != null) {
val modifiableModel = modelsProvider.getModifiableLibraryModel(ideLibrary) as LibraryEx.ModifiableModelEx
modifiableModel.kind = JSLibraryKind
modifiableModel.kind = targetLibraryKind
}
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2017 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.kotlin.idea.framework
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.DummyLibraryProperties
import com.intellij.openapi.roots.libraries.LibraryType
import com.intellij.openapi.roots.libraries.NewLibraryConfiguration
import com.intellij.openapi.roots.libraries.ui.LibraryEditorComponent
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.KotlinIcons
import javax.swing.JComponent
object CommonLibraryType : LibraryType<DummyLibraryProperties>(CommonLibraryKind) {
override fun createPropertiesEditor(editorComponent: LibraryEditorComponent<DummyLibraryProperties>) = null
override fun getCreateActionName() = null
override fun createNewLibrary(parentComponent: JComponent,
contextDirectory: VirtualFile?,
project: Project): NewLibraryConfiguration? = null
override fun getIcon(properties: DummyLibraryProperties?) = KotlinIcons.SMALL_LOGO
}
@@ -23,16 +23,14 @@ import com.intellij.openapi.fileTypes.PlainTextFileType
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectBundle
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.DummyLibraryProperties
import com.intellij.openapi.roots.libraries.LibraryType
import com.intellij.openapi.roots.libraries.LibraryTypeService
import com.intellij.openapi.roots.libraries.NewLibraryConfiguration
import com.intellij.openapi.roots.libraries.*
import com.intellij.openapi.roots.libraries.ui.FileTypeBasedRootFilter
import com.intellij.openapi.roots.libraries.ui.LibraryEditorComponent
import com.intellij.openapi.roots.libraries.ui.RootDetector
import com.intellij.openapi.roots.ui.configuration.libraryEditor.DefaultLibraryRootsComponentDescriptor
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.KotlinIcons
import javax.swing.JComponent
@@ -86,3 +84,10 @@ class JSLibraryType : LibraryType<DummyLibraryProperties>(JSLibraryKind) {
}
private fun isAcceptedForJsLibrary(extension: String?) = extension == "js" || extension == "kjsm"
val TargetPlatformKind<*>.libraryKind: PersistentLibraryKind<*>?
get() = when(this) {
TargetPlatformKind.JavaScript -> JSLibraryKind
TargetPlatformKind.Common -> CommonLibraryKind
else -> null
}
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.junit.Assert
import org.junit.Test
@@ -624,6 +625,11 @@ class GradleFacetImportTest : GradleImportingTestCase() {
}
apply plugin: 'kotlin-platform-common'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:1.1.0"
}
""")
importProject()
@@ -632,6 +638,10 @@ class GradleFacetImportTest : GradleImportingTestCase() {
Assert.assertEquals("1.1", apiLevel!!.versionString)
Assert.assertEquals(TargetPlatformKind.Common, targetPlatformKind)
}
val rootManager = ModuleRootManager.getInstance(getModule("project_main"))
val stdlib = rootManager.orderEntries.filterIsInstance<LibraryOrderEntry>().single().library
assertEquals(CommonLibraryKind, (stdlib as LibraryEx).kind)
}
@Test