@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.idea.configuration
18
18
19
19
import com.intellij.openapi.application.ApplicationManager
20
20
import com.intellij.openapi.extensions.Extensions
21
- import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
22
21
import com.intellij.openapi.module.Module
23
- import com.intellij.openapi.module.ModuleManager
24
22
import com.intellij.openapi.project.DumbService
25
23
import com.intellij.openapi.project.Project
26
24
import com.intellij.openapi.roots.DependencyScope
@@ -30,6 +28,7 @@ import com.intellij.psi.search.GlobalSearchScope
30
28
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
31
29
import org.jetbrains.kotlin.idea.KotlinFileType
32
30
import org.jetbrains.kotlin.idea.configuration.ui.notifications.ConfigureKotlinNotification
31
+ import org.jetbrains.kotlin.idea.util.application.runReadAction
33
32
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
34
33
import org.jetbrains.kotlin.idea.versions.getKotlinJvmRuntimeMarkerClass
35
34
import org.jetbrains.kotlin.idea.versions.hasKotlinJsKjsmFile
@@ -96,9 +95,9 @@ fun getRepositoryForVersion(version: String): RepositoryDescription? = when {
96
95
else -> null
97
96
}
98
97
99
- fun isModuleConfigured (module : Module ): Boolean {
98
+ fun isModuleConfigured (moduleSourceRootGroup : ModuleSourceRootGroup ): Boolean {
100
99
return allConfigurators().any {
101
- it.getStatus(module ) == ConfigureKotlinStatus .CONFIGURED
100
+ it.getStatus(moduleSourceRootGroup ) == ConfigureKotlinStatus .CONFIGURED
102
101
}
103
102
}
104
103
@@ -107,57 +106,67 @@ fun getModulesWithKotlinFiles(project: Project): Collection<Module> {
107
106
return emptyList()
108
107
}
109
108
110
- if (! FileTypeIndex .containsFileOfType(KotlinFileType .INSTANCE , GlobalSearchScope .projectScope(project))) {
109
+ if (! runReadAction { FileTypeIndex .containsFileOfType (KotlinFileType .INSTANCE , GlobalSearchScope .projectScope(project)) } ) {
111
110
return emptyList()
112
111
}
113
112
114
113
return project.allModules()
115
114
.filter { module ->
116
- FileTypeIndex .containsFileOfType(KotlinFileType .INSTANCE , module.getModuleScope(true ))
115
+ runReadAction {
116
+ FileTypeIndex .containsFileOfType(KotlinFileType .INSTANCE , module.getModuleScope(true ))
117
+ }
117
118
}
118
119
}
119
120
120
- fun getConfigurableModulesWithKotlinFiles (project : Project ): Collection < Module > {
121
+ fun getConfigurableModulesWithKotlinFiles (project : Project ): List < ModuleSourceRootGroup > {
121
122
val modules = getModulesWithKotlinFiles(project)
122
- if (modules.isEmpty()) return modules
123
+ if (modules.isEmpty()) return emptyList()
123
124
124
- val pathMap = ModuleManager .getInstance(project).modules.asList().buildExternalPathMap()
125
- return modules.mapTo(HashSet ()) { module ->
126
- val externalPath = module.externalProjectPath
127
- if (externalPath == null ) module else (pathMap[externalPath] ? : module)
128
- }
125
+ return ModuleSourceRootMap (project).groupByBaseModules(modules)
129
126
}
130
127
131
128
fun showConfigureKotlinNotificationIfNeeded (module : Module ) {
132
- if (isModuleConfigured(module)) return
129
+ val moduleGroup = ModuleSourceRootMap (module.project).toModuleGroup(module)
130
+ if (isModuleConfigured(moduleGroup)) return
133
131
134
132
ConfigureKotlinNotificationManager .notify(module.project)
135
133
}
136
134
137
135
fun showConfigureKotlinNotificationIfNeeded (project : Project , excludeModules : List <Module > = emptyList()) {
138
- ApplicationManager .getApplication().executeOnPooledThread {
139
- val notificationString = DumbService .getInstance(project).runReadActionInSmartMode(Computable {
140
- val modules = getConfigurableModulesWithKotlinFiles(project) - excludeModules
141
- if (modules.all(::isModuleConfigured)) null else ConfigureKotlinNotification .getNotificationString(project, excludeModules)
142
- })
143
- if (notificationString != null ) {
144
- ApplicationManager .getApplication().invokeLater {
145
- ConfigureKotlinNotificationManager .notify(project, ConfigureKotlinNotification (project, excludeModules, notificationString))
146
- }
136
+ val notificationString = DumbService .getInstance(project).runReadActionInSmartMode(Computable {
137
+ val modules = getConfigurableModulesWithKotlinFiles(project).exclude(excludeModules)
138
+ if (modules.all(::isModuleConfigured))
139
+ null
140
+ else
141
+ ConfigureKotlinNotification .getNotificationString(project, excludeModules)
142
+ })
143
+
144
+ if (notificationString != null ) {
145
+ ApplicationManager .getApplication().invokeLater {
146
+ ConfigureKotlinNotificationManager .notify(project, ConfigureKotlinNotification (project, excludeModules, notificationString))
147
147
}
148
148
}
149
149
}
150
150
151
151
fun getAbleToRunConfigurators (project : Project ): Collection <KotlinProjectConfigurator > {
152
- val modules = getConfigurableModulesWithKotlinFiles (project).ifEmpty { project.allModules() }
152
+ val modules = getConfigurableModules (project)
153
153
154
154
return allConfigurators().filter { configurator ->
155
- modules.any { module -> configurator.getStatus(module) == ConfigureKotlinStatus .CAN_BE_CONFIGURED }
155
+ modules.any { configurator.getStatus(it) == ConfigureKotlinStatus .CAN_BE_CONFIGURED }
156
+ }
157
+ }
158
+
159
+ fun getConfigurableModules (project : Project ): List <ModuleSourceRootGroup > {
160
+ return getConfigurableModulesWithKotlinFiles(project).ifEmpty {
161
+ ModuleSourceRootMap (project).groupByBaseModules(project.allModules())
156
162
}
157
163
}
158
164
159
165
fun getAbleToRunConfigurators (module : Module ): Collection <KotlinProjectConfigurator > {
160
- return allConfigurators().filter { it.getStatus(module) == ConfigureKotlinStatus .CAN_BE_CONFIGURED }
166
+ val moduleGroup = ModuleSourceRootMap (module.project).toModuleGroup(module)
167
+ return allConfigurators().filter {
168
+ it.getStatus(moduleGroup) == ConfigureKotlinStatus .CAN_BE_CONFIGURED
169
+ }
161
170
}
162
171
163
172
fun getConfiguratorByName (name : String ): KotlinProjectConfigurator ? {
@@ -167,56 +176,26 @@ fun getConfiguratorByName(name: String): KotlinProjectConfigurator? {
167
176
fun allConfigurators () = Extensions .getExtensions(KotlinProjectConfigurator .EP_NAME )
168
177
169
178
fun getCanBeConfiguredModules (project : Project , configurator : KotlinProjectConfigurator ): List <Module > {
170
- return project.allModules()
171
- .filter { module -> configurator.canConfigure(module) }
172
- .excludeSourceRootModules()
173
- }
174
-
175
- private fun KotlinProjectConfigurator.canConfigure (module : Module ) =
176
- getStatus(module) == ConfigureKotlinStatus .CAN_BE_CONFIGURED &&
177
- (allConfigurators().toList() - this ).none { it.getStatus(module) == ConfigureKotlinStatus .CONFIGURED }
178
-
179
- fun Collection<Module>.excludeSourceRootModules (): List <Module > {
180
- val pathMap = buildExternalPathMap()
181
- return filter { it.externalProjectId == null || it.externalProjectPath == null } + pathMap.values
179
+ return ModuleSourceRootMap (project).groupByBaseModules(project.allModules())
180
+ .filter { configurator.canConfigure(it) }
181
+ .map { it.baseModule }
182
182
}
183
183
184
- fun Collection<Module>.buildExternalPathMap (): Map <String , Module > {
185
- val pathMap = mutableMapOf<String , Module >()
186
- for (module in this ) {
187
- val externalId = module.externalProjectId
188
- val externalPath = module.externalProjectPath
189
- if (externalId != null && externalPath != null ) {
190
- val previousModule = pathMap[externalPath]
191
- // the module without the source root suffix will have the shortest name
192
- if (previousModule == null || isSourceRootPrefix(externalId, previousModule.externalProjectId!! )) {
193
- pathMap[externalPath] = module
194
- }
195
- }
196
- }
197
- return pathMap
198
- }
199
-
200
- private fun isSourceRootPrefix (externalId : String , previousModuleExternalId : String )
201
- = externalId.length < previousModuleExternalId.length && previousModuleExternalId.startsWith(externalId)
202
-
203
- val Module .externalProjectId: String?
204
- get() = ExternalSystemApiUtil .getExternalProjectId(this )
205
-
206
- val Module .externalProjectPath: String?
207
- get() = ExternalSystemApiUtil .getExternalProjectPath(this )
184
+ private fun KotlinProjectConfigurator.canConfigure (moduleSourceRootGroup : ModuleSourceRootGroup ) =
185
+ getStatus(moduleSourceRootGroup) == ConfigureKotlinStatus .CAN_BE_CONFIGURED &&
186
+ (allConfigurators().toList() - this ).none { it.getStatus(moduleSourceRootGroup) == ConfigureKotlinStatus .CONFIGURED }
208
187
209
188
fun getCanBeConfiguredModulesWithKotlinFiles (project : Project , configurator : KotlinProjectConfigurator ): List <Module > {
210
189
val modules = getConfigurableModulesWithKotlinFiles(project)
211
- return modules.filter { module -> configurator.getStatus(module ) == ConfigureKotlinStatus .CAN_BE_CONFIGURED }
190
+ return modules.filter { configurator.getStatus(it ) == ConfigureKotlinStatus .CAN_BE_CONFIGURED }.map { it.baseModule }
212
191
}
213
192
214
193
fun getCanBeConfiguredModulesWithKotlinFiles (project : Project , excludeModules : Collection <Module > = emptyList()): Collection <Module > {
215
- val modulesWithKotlinFiles = getConfigurableModulesWithKotlinFiles(project) - excludeModules
194
+ val modulesWithKotlinFiles = getConfigurableModulesWithKotlinFiles(project).exclude( excludeModules)
216
195
val configurators = allConfigurators()
217
- return modulesWithKotlinFiles.filter { module ->
218
- configurators.any { it.getStatus(module ) == ConfigureKotlinStatus .CAN_BE_CONFIGURED }
219
- }
196
+ return modulesWithKotlinFiles.filter { moduleSourceRootGroup ->
197
+ configurators.any { it.getStatus(moduleSourceRootGroup ) == ConfigureKotlinStatus .CAN_BE_CONFIGURED }
198
+ }.map { it.baseModule }
220
199
}
221
200
222
201
fun hasAnyKotlinRuntimeInScope (module : Module ): Boolean {
0 commit comments