Skip to content

Commit e0dc7a2

Browse files
committed
Migration for pre-1.1.3 JS libraries
#KT-19156 Fixed
1 parent 861219f commit e0dc7a2

File tree

16 files changed

+196
-43
lines changed

16 files changed

+196
-43
lines changed

idea/idea-analysis/src/org/jetbrains/kotlin/idea/framework/JsLibraryStdDetectionUtil.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ import java.util.jar.Attributes
3333
object JsLibraryStdDetectionUtil {
3434
private val IS_JS_LIBRARY_STD_LIB = Key.create<Boolean>("IS_JS_LIBRARY_STD_LIB")
3535

36-
fun hasJsStdlibJar(library: Library): Boolean {
36+
fun hasJsStdlibJar(library: Library, ignoreKind: Boolean = false): Boolean {
3737
if (library !is LibraryEx || library.isDisposed) return false
38-
if (library.kind !is JSLibraryKind) return false
38+
if (!ignoreKind && library.kind !is JSLibraryKind) return false
3939

4040
val classes = Arrays.asList(*library.getFiles(OrderRootType.CLASSES))
4141
return getJsStdLibJar(classes) != null

idea/idea-analysis/src/org/jetbrains/kotlin/idea/project/ProjectStructureUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public Boolean compute() {
9090
ModuleRootManager.getInstance(module).orderEntries().librariesOnly().forEachLibrary(new Processor<Library>() {
9191
@Override
9292
public boolean process(Library library) {
93-
if (JsLibraryStdDetectionUtil.INSTANCE.hasJsStdlibJar(library)) {
93+
if (JsLibraryStdDetectionUtil.INSTANCE.hasJsStdlibJar(library, false)) {
9494
jsLibrary.set(library);
9595
return false;
9696
}

idea/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinInProjectUtils.kt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,19 @@ import com.intellij.openapi.module.Module
2222
import com.intellij.openapi.project.DumbService
2323
import com.intellij.openapi.project.Project
2424
import com.intellij.openapi.roots.DependencyScope
25+
import com.intellij.openapi.roots.LibraryOrderEntry
26+
import com.intellij.openapi.roots.ModuleRootManager
27+
import com.intellij.openapi.roots.impl.libraries.LibraryEx
28+
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
2529
import com.intellij.openapi.util.Computable
30+
import com.intellij.openapi.vfs.VirtualFile
31+
import com.intellij.psi.search.DelegatingGlobalSearchScope
2632
import com.intellij.psi.search.FileTypeIndex
2733
import com.intellij.psi.search.GlobalSearchScope
2834
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
2935
import org.jetbrains.kotlin.idea.KotlinFileType
3036
import org.jetbrains.kotlin.idea.configuration.ui.notifications.ConfigureKotlinNotification
37+
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
3138
import org.jetbrains.kotlin.idea.util.application.runReadAction
3239
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
3340
import org.jetbrains.kotlin.idea.versions.getKotlinJvmRuntimeMarkerClass
@@ -202,7 +209,7 @@ fun hasAnyKotlinRuntimeInScope(module: Module): Boolean {
202209
val scope = module.getModuleWithDependenciesAndLibrariesScope(hasKotlinFilesOnlyInTests(module))
203210
return runReadAction {
204211
getKotlinJvmRuntimeMarkerClass(module.project, scope) != null ||
205-
hasKotlinJsKjsmFile(module.project, scope) ||
212+
hasKotlinJsKjsmFile(module.project, LibraryKindSearchScope(module, scope, JSLibraryKind) ) ||
206213
hasKotlinCommonRuntimeInScope(scope)
207214
}
208215
}
@@ -217,7 +224,7 @@ fun hasKotlinJvmRuntimeInScope(module: Module): Boolean {
217224
fun hasKotlinJsRuntimeInScope(module: Module): Boolean {
218225
return runReadAction {
219226
val scope = module.getModuleWithDependenciesAndLibrariesScope(hasKotlinFilesOnlyInTests(module))
220-
hasKotlinJsKjsmFile(module.project, scope)
227+
hasKotlinJsKjsmFile(module.project, LibraryKindSearchScope(module, scope, JSLibraryKind))
221228
}
222229
}
223230

@@ -244,4 +251,18 @@ fun isEap(version: String): Boolean {
244251
fun useEapRepository(minorKotlinVersion: Int, version: String): Boolean {
245252
return Regex("1\\.$minorKotlinVersion(\\.\\d)?-[A-Za-z][A-Za-z0-9-]*").matches(version) &&
246253
!version.startsWith("1.$minorKotlinVersion.0-dev")
247-
}
254+
}
255+
256+
private class LibraryKindSearchScope(val module: Module,
257+
val baseScope: GlobalSearchScope,
258+
val libraryKind: PersistentLibraryKind<*>
259+
) : DelegatingGlobalSearchScope(baseScope) {
260+
override fun contains(file: VirtualFile): Boolean {
261+
if (!super.contains(file)) return false
262+
val orderEntry = ModuleRootManager.getInstance(module).fileIndex.getOrderEntryForFile(file)
263+
if (orderEntry is LibraryOrderEntry) {
264+
return (orderEntry.library as LibraryEx).kind == libraryKind
265+
}
266+
return true
267+
}
268+
}

idea/src/org/jetbrains/kotlin/idea/configuration/ConfigureKotlinNotificationManager.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.idea.configuration
1818

1919
import com.intellij.notification.Notification
2020
import com.intellij.notification.NotificationsManager
21+
import com.intellij.openapi.application.ApplicationManager
2122
import com.intellij.openapi.module.Module
23+
import com.intellij.openapi.project.DumbService
2224
import com.intellij.openapi.project.Project
2325
import org.jetbrains.kotlin.idea.configuration.ui.notifications.ConfigureKotlinNotification
2426
import kotlin.reflect.KClass
@@ -64,3 +66,16 @@ interface KotlinSingleNotificationManager<in T: Notification> {
6466
}
6567
}
6668

69+
70+
fun checkHideNonConfiguredNotifications(project: Project) {
71+
if (ConfigureKotlinNotificationManager.getVisibleNotifications(project).isNotEmpty()) {
72+
ApplicationManager.getApplication().executeOnPooledThread {
73+
DumbService.getInstance(project).waitForSmartMode()
74+
if (getConfigurableModulesWithKotlinFiles(project).all(::isModuleConfigured)) {
75+
ApplicationManager.getApplication().invokeLater {
76+
ConfigureKotlinNotificationManager.expireOldNotifications(project)
77+
}
78+
}
79+
}
80+
}
81+
}

idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJavaModuleConfigurator.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import com.intellij.openapi.module.Module
2222
import com.intellij.openapi.projectRoots.JavaSdk
2323
import com.intellij.openapi.projectRoots.JavaSdkVersion
2424
import com.intellij.openapi.projectRoots.Sdk
25+
import com.intellij.openapi.roots.LibraryOrderEntry
26+
import com.intellij.openapi.roots.ModuleRootManager
27+
import com.intellij.openapi.roots.impl.libraries.LibraryEx
2528
import com.intellij.openapi.roots.libraries.Library
2629
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
2730
import org.jetbrains.kotlin.config.JvmTarget
@@ -30,6 +33,7 @@ import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgume
3033
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
3134
import org.jetbrains.kotlin.idea.facet.initializeIfNeeded
3235
import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription
36+
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil
3337
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
3438
import org.jetbrains.kotlin.idea.util.projectStructure.sdk
3539
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
@@ -38,6 +42,9 @@ import org.jetbrains.kotlin.resolve.TargetPlatform
3842
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
3943

4044
open class KotlinJavaModuleConfigurator internal constructor() : KotlinWithLibraryConfigurator() {
45+
override fun isApplicable(module: Module): Boolean {
46+
return super.isApplicable(module) && !hasBrokenJsRuntime(module)
47+
}
4148

4249
override fun isConfigured(module: Module): Boolean {
4350
return hasKotlinJvmRuntimeInScope(module)
@@ -113,4 +120,12 @@ open class KotlinJavaModuleConfigurator internal constructor() : KotlinWithLibra
113120
val instance: KotlinJavaModuleConfigurator
114121
get() = Extensions.findExtension(KotlinProjectConfigurator.EP_NAME, KotlinJavaModuleConfigurator::class.java)
115122
}
123+
124+
private fun hasBrokenJsRuntime(module: Module): Boolean {
125+
for (orderEntry in ModuleRootManager.getInstance(module).orderEntries) {
126+
val library = (orderEntry as? LibraryOrderEntry)?.library as? LibraryEx ?: continue
127+
if (JsLibraryStdDetectionUtil.hasJsStdlibJar(library, ignoreKind = true)) return true
128+
}
129+
return false
130+
}
116131
}

idea/src/org/jetbrains/kotlin/idea/configuration/KotlinJsModuleConfigurator.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,17 @@ package org.jetbrains.kotlin.idea.configuration
1818

1919
import com.intellij.openapi.module.Module
2020
import com.intellij.openapi.projectRoots.Sdk
21+
import com.intellij.openapi.roots.LibraryOrderEntry
22+
import com.intellij.openapi.roots.ModuleRootManager
23+
import com.intellij.openapi.roots.impl.libraries.LibraryEx
2124
import com.intellij.openapi.roots.libraries.DummyLibraryProperties
2225
import com.intellij.openapi.roots.libraries.Library
2326
import com.intellij.openapi.roots.libraries.LibraryType
27+
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
2428
import org.jetbrains.kotlin.idea.framework.JSLibraryStdDescription
2529
import org.jetbrains.kotlin.idea.framework.JSLibraryType
30+
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil
31+
import org.jetbrains.kotlin.idea.util.application.runWriteAction
2632
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
2733
import org.jetbrains.kotlin.idea.versions.isKotlinJsRuntime
2834
import org.jetbrains.kotlin.js.JavaScript
@@ -65,4 +71,32 @@ open class KotlinJsModuleConfigurator : KotlinWithLibraryConfigurator() {
6571
companion object {
6672
const val NAME = JavaScript.LOWER_NAME
6773
}
74+
75+
/**
76+
* Migrate pre-1.1.3 projects which didn't have explicitly specified kind for JS libraries.
77+
*/
78+
override fun findAndFixBrokenKotlinLibrary(module: Module, collector: NotificationMessageCollector): Library? {
79+
val allLibraries = mutableListOf<LibraryEx>()
80+
var brokenStdlib: Library? = null
81+
for (orderEntry in ModuleRootManager.getInstance(module).orderEntries) {
82+
val library = (orderEntry as? LibraryOrderEntry)?.library as? LibraryEx ?: continue
83+
allLibraries.add(library)
84+
if (JsLibraryStdDetectionUtil.hasJsStdlibJar(library, ignoreKind = true) && library.kind == null) {
85+
brokenStdlib = library
86+
}
87+
}
88+
89+
if (brokenStdlib != null) {
90+
runWriteAction {
91+
for (library in allLibraries.filter { it.kind == null }) {
92+
library.modifiableModel.apply {
93+
kind = JSLibraryKind
94+
commit()
95+
}
96+
}
97+
}
98+
collector.addMessage("Updated JavaScript libraries in module ${module.name}")
99+
}
100+
return brokenStdlib
101+
}
68102
}

idea/src/org/jetbrains/kotlin/idea/configuration/KotlinSetupEnvironmentNotificationProvider.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class KotlinSetupEnvironmentNotificationProvider(
114114
createComponentActionLabel("Configure") { label ->
115115
val singleConfigurator = configurators.singleOrNull()
116116
if (singleConfigurator != null) {
117-
singleConfigurator.configure(module.project, emptyList())
117+
singleConfigurator.apply(module.project)
118118
}
119119
else {
120120
val configuratorsPopup = createConfiguratorsPopup(module.project, configurators)
@@ -125,15 +125,19 @@ class KotlinSetupEnvironmentNotificationProvider(
125125
}
126126
}
127127

128+
private fun KotlinProjectConfigurator.apply(project: Project) {
129+
configure(project, emptyList())
130+
EditorNotifications.getInstance(project).updateAllNotifications()
131+
checkHideNonConfiguredNotifications(project)
132+
}
133+
128134
fun createConfiguratorsPopup(project: Project, configurators: List<KotlinProjectConfigurator>): ListPopup {
129135
val step = object : BaseListPopupStep<KotlinProjectConfigurator>("Choose Configurator", configurators) {
130-
override fun getTextFor(value: KotlinProjectConfigurator?): String {
131-
return value?.presentableText ?: "<none>"
132-
}
136+
override fun getTextFor(value: KotlinProjectConfigurator?) = value?.presentableText ?: "<none>"
133137

134138
override fun onChosen(selectedValue: KotlinProjectConfigurator?, finalChoice: Boolean): PopupStep<*>? {
135139
return doFinalStep {
136-
selectedValue?.configure(project, emptyList())
140+
selectedValue?.apply(project)
137141
}
138142
}
139143
}

idea/src/org/jetbrains/kotlin/idea/configuration/KotlinWithLibraryConfigurator.kt

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj
137137
) {
138138
val project = module.project
139139

140-
val library = getKotlinLibrary(module)
140+
val library = findAndFixBrokenKotlinLibrary(module, collector)
141+
?: getKotlinLibrary(module)
141142
?: getKotlinLibrary(project)
142143
?: createNewLibrary(project, collector)
143144

@@ -316,15 +317,17 @@ abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProj
316317
protected open fun configureKotlinSettings(modules: List<Module>) {
317318
}
318319

320+
protected open fun findAndFixBrokenKotlinLibrary(module: Module, collector: NotificationMessageCollector): Library? = null
321+
322+
protected open fun isApplicable(module: Module): Boolean {
323+
return !KotlinPluginUtil.isAndroidGradleModule(module) &&
324+
!KotlinPluginUtil.isMavenModule(module) &&
325+
!KotlinPluginUtil.isGradleModule(module)
326+
}
327+
319328
companion object {
320329
val DEFAULT_LIBRARY_DIR = "lib"
321330

322-
protected fun isApplicable(module: Module): Boolean {
323-
return !KotlinPluginUtil.isAndroidGradleModule(module) &&
324-
!KotlinPluginUtil.isMavenModule(module) &&
325-
!KotlinPluginUtil.isGradleModule(module)
326-
}
327-
328331
fun getPathFromLibrary(library: Library?, type: OrderRootType): String? {
329332
if (library == null) return null
330333

idea/src/org/jetbrains/kotlin/idea/configuration/ui/KotlinConfigurationCheckerComponent.kt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ import com.intellij.openapi.project.Project
2626
import com.intellij.openapi.roots.ModuleRootEvent
2727
import com.intellij.openapi.roots.ModuleRootListener
2828
import com.intellij.openapi.startup.StartupManager
29-
import org.jetbrains.kotlin.idea.configuration.*
29+
import org.jetbrains.kotlin.idea.configuration.checkHideNonConfiguredNotifications
30+
import org.jetbrains.kotlin.idea.configuration.getModulesWithKotlinFiles
31+
import org.jetbrains.kotlin.idea.configuration.showConfigureKotlinNotificationIfNeeded
3032
import org.jetbrains.kotlin.idea.project.getAndCacheLanguageLevelByDependencies
3133
import org.jetbrains.kotlin.idea.versions.collectModulesWithOutdatedRuntime
3234
import org.jetbrains.kotlin.idea.versions.findOutdatedKotlinLibraries
@@ -54,16 +56,7 @@ class KotlinConfigurationCheckerComponent(project: Project) : AbstractProjectCom
5456
}
5557
}
5658

57-
if (ConfigureKotlinNotificationManager.getVisibleNotifications(project).isNotEmpty()) {
58-
ApplicationManager.getApplication().executeOnPooledThread {
59-
DumbService.getInstance(myProject).waitForSmartMode()
60-
if (getConfigurableModulesWithKotlinFiles(project).all(::isModuleConfigured)) {
61-
ApplicationManager.getApplication().invokeLater {
62-
ConfigureKotlinNotificationManager.expireOldNotifications(project)
63-
}
64-
}
65-
}
66-
}
59+
checkHideNonConfiguredNotifications(project)
6760
}
6861
})
6962
}

idea/testData/configuration/jsLibraryWithoutPaths/projectFile.ipr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</component>
88
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK"/>
99
<component name="libraryTable">
10-
<library name="KotlinJavaScript">
10+
<library name="KotlinJavaScript" type="kotlin.js">
1111
<CLASSES />
1212
<JAVADOC />
1313
<SOURCES />
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="JAVA_MODULE" version="4">
3+
<component name="NewModuleRootManager" inherit-compiler-output="true">
4+
<exclude-output />
5+
<content url="file://$MODULE_DIR$">
6+
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
7+
</content>
8+
<orderEntry type="inheritedJdk" />
9+
<orderEntry type="sourceFolder" forTests="false" />
10+
<orderEntry type="library" name="KotlinJavaRuntime (2)" level="project" />
11+
</component>
12+
</module>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project version="4">
3+
<component name="CompilerConfiguration">
4+
<resourceExtensions />
5+
<wildcardResourcePatterns>
6+
<entry name="!?*.java" />
7+
<entry name="!?*.form" />
8+
<entry name="!?*.class" />
9+
<entry name="!?*.groovy" />
10+
<entry name="!?*.scala" />
11+
<entry name="!?*.flex" />
12+
<entry name="!?*.kt" />
13+
<entry name="!?*.clj" />
14+
<entry name="!?*.aj" />
15+
</wildcardResourcePatterns>
16+
<annotationProcessing>
17+
<profile default="true" name="Default" enabled="false">
18+
<processorPath useClasspath="true" />
19+
</profile>
20+
</annotationProcessing>
21+
</component>
22+
<component name="CopyrightManager" default="" />
23+
<component name="ProjectModuleManager">
24+
<modules>
25+
<module fileurl="file://$PROJECT_DIR$/module.iml" filepath="$PROJECT_DIR$/module.iml" />
26+
</modules>
27+
</component>
28+
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
29+
<output url="file://$PROJECT_DIR$/out" />
30+
</component>
31+
<component name="libraryTable">
32+
<library name="KotlinJavaRuntime (2)">
33+
<CLASSES>
34+
<root url="jar://$PROJECT_DIR$/../jsRuntime11Maven/kotlin-stdlib-js-1.1.0.jar!/" />
35+
</CLASSES>
36+
<JAVADOC />
37+
<SOURCES>
38+
</SOURCES>
39+
</library>
40+
</component>
41+
</project>

idea/testData/configuration/jsLibraryWrongKind/src/foo.kt

Whitespace-only changes.

idea/testData/configuration/twoModulesWithJSNonDefaultPath/projectFile.ipr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</component>
99
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK"/>
1010
<component name="libraryTable">
11-
<library name="KotlinJavaScript">
11+
<library name="KotlinJavaScript" type="kotlin.js">
1212
<CLASSES>
1313
<root url="jar://$TEMP_TEST_DIR$/kotlin-stdlib-js.jar!/" />
1414
</CLASSES>

0 commit comments

Comments
 (0)