Skip to content

Commit 6078607

Browse files
committed
Adding coroutines to analysis process
1 parent 5150404 commit 6078607

File tree

14 files changed

+320
-307
lines changed

14 files changed

+320
-307
lines changed

kotlin-bundled-compiler/.classpath

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<classpath>
3+
<classpathentry exported="true" kind="lib" path="lib/kotlinx-coroutines-core.jar"/>
4+
<classpathentry exported="true" kind="lib" path="lib/kotlinx-coroutines-jdk8.jar"/>
35
<classpathentry exported="true" kind="lib" path="lib/ide-dependencies.jar"/>
46
<classpathentry exported="true" kind="lib" path="lib/kotlin-compiler.jar" sourcepath="lib/kotlin-compiler-sources.jar"/>
57
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>

kotlin-bundled-compiler/META-INF/MANIFEST.MF

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ Bundle-ClassPath: .,
1414
lib/kotlin-reflect.jar,
1515
../kotlin-eclipse-ui-test/lib/gson-2.3.1.jar,
1616
lib/kotlin-formatter.jar,
17-
lib/ide-dependencies.jar
17+
lib/ide-dependencies.jar,
18+
lib/kotlinx-coroutines-core.jar,
19+
lib/kotlinx-coroutines-jdk8.jar
1820
Export-Package:
1921
com.intellij,
2022
com.intellij.codeInsight,
@@ -177,6 +179,9 @@ Export-Package:
177179
kotlin.collections,
178180
kotlin.comparisons,
179181
kotlin.concurrent,
182+
kotlin.coroutines,
183+
kotlin.coroutines.intrinsics,
184+
kotlin.coroutines.jvm.internal,
180185
kotlin.internal;x-internal:=true,
181186
kotlin.io,
182187
kotlin.jvm,
@@ -194,6 +199,7 @@ Export-Package:
194199
kotlin.script.templates.standard,
195200
kotlin.sequences,
196201
kotlin.text,
202+
kotlinx.coroutines,
197203
org.jetbrains.annotations,
198204
org.jetbrains.kotlin,
199205
org.jetbrains.kotlin.analyzer,

kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinAnalysisFileCache.kt

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,51 @@
1616
*******************************************************************************/
1717
package org.jetbrains.kotlin.core.model
1818

19-
import org.eclipse.jdt.core.IJavaProject
19+
import kotlinx.coroutines.Deferred
20+
import kotlinx.coroutines.async
21+
import kotlinx.coroutines.runBlocking
2022
import org.jetbrains.kotlin.core.resolve.AnalysisResultWithProvider
2123
import org.jetbrains.kotlin.core.resolve.EclipseAnalyzerFacadeForJVM
24+
import org.jetbrains.kotlin.core.resolve.KotlinCoroutinesScope
2225
import org.jetbrains.kotlin.psi.KtFile
23-
import org.jetbrains.kotlin.core.builder.KotlinPsiManager
2426

25-
data class FileAnalysisResults(val file: KtFile, val analysisResult: AnalysisResultWithProvider)
27+
data class FileAnalysisResults(val file: KtFile, val analysisResult: Deferred<AnalysisResultWithProvider>)
2628

27-
public object KotlinAnalysisFileCache {
28-
private @Volatile var lastAnalysedFileCache: FileAnalysisResults? = null
29+
object KotlinAnalysisFileCache {
2930

30-
@Synchronized fun getAnalysisResult(file: KtFile): AnalysisResultWithProvider {
31-
return getImmediatlyFromCache(file) ?: run {
31+
@Volatile
32+
private var lastAnalysedFileCache: FileAnalysisResults? = null
33+
34+
fun getAnalysisResult(file: KtFile): AnalysisResultWithProvider {
35+
return runBlocking {
36+
getImmediatelyFromCache(file)?.await()
37+
} ?: runBlocking {
3238
val environment = getEnvironment(file.project)!!
33-
val analysisResult = resolve(file, environment)
34-
35-
lastAnalysedFileCache = FileAnalysisResults(file, analysisResult)
36-
lastAnalysedFileCache!!.analysisResult
39+
val analysisResult = KotlinCoroutinesScope.async {
40+
resolve(file, environment)
41+
}
42+
saveLastResult(file, analysisResult).analysisResult.await()
3743
}
3844
}
45+
46+
@Synchronized
47+
private fun saveLastResult(file: KtFile, result: Deferred<AnalysisResultWithProvider>): FileAnalysisResults =
48+
FileAnalysisResults(file, result).also {
49+
lastAnalysedFileCache = it
50+
}
3951

4052
fun resetCache() {
4153
lastAnalysedFileCache = null
4254
}
4355

44-
private fun resolve(file: KtFile, environment: KotlinCommonEnvironment): AnalysisResultWithProvider {
45-
return when (environment) {
56+
private fun resolve(file: KtFile, environment: KotlinCommonEnvironment): AnalysisResultWithProvider =
57+
when (environment) {
4658
is KotlinScriptEnvironment -> EclipseAnalyzerFacadeForJVM.analyzeScript(environment, file)
4759
is KotlinEnvironment -> EclipseAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(environment, listOf(file))
4860
else -> throw IllegalArgumentException("Could not analyze file with environment: $environment")
4961
}
50-
}
5162

5263
@Synchronized
53-
private fun getImmediatlyFromCache(file: KtFile): AnalysisResultWithProvider? {
54-
return if (lastAnalysedFileCache != null && lastAnalysedFileCache!!.file == file)
55-
lastAnalysedFileCache!!.analysisResult
56-
else
57-
null
58-
}
64+
private fun getImmediatelyFromCache (ktFile: KtFile) : Deferred<AnalysisResultWithProvider>? =
65+
lastAnalysedFileCache?.takeIf { it.file == ktFile }?.analysisResult
5966
}

kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinAnalysisProjectCache.kt

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
*******************************************************************************/
1717
package org.jetbrains.kotlin.core.model
1818

19+
import kotlinx.coroutines.Deferred
20+
import kotlinx.coroutines.async
21+
import kotlinx.coroutines.runBlocking
1922
import org.eclipse.core.resources.IFile
2023
import org.eclipse.core.resources.IProject
2124
import org.eclipse.core.resources.IResourceChangeEvent
@@ -24,52 +27,54 @@ import org.eclipse.jdt.core.IJavaProject
2427
import org.eclipse.jdt.core.JavaCore
2528
import org.jetbrains.kotlin.analyzer.AnalysisResult
2629
import org.jetbrains.kotlin.core.builder.KotlinPsiManager
27-
import org.jetbrains.kotlin.core.resolve.EclipseAnalyzerFacadeForJVM
28-
import org.jetbrains.kotlin.core.utils.ProjectUtils
29-
import java.util.concurrent.ConcurrentHashMap
30+
import org.jetbrains.kotlin.core.resolve.AnalysisResultWithProvider
31+
import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer
32+
import org.jetbrains.kotlin.core.resolve.KotlinCoroutinesScope
33+
import java.util.concurrent.*
3034

31-
public object KotlinAnalysisProjectCache : IResourceChangeListener {
32-
private val cachedAnalysisResults = ConcurrentHashMap<IProject, AnalysisResult>()
35+
object KotlinAnalysisProjectCache : IResourceChangeListener {
36+
private val cachedAnalysisResults = ConcurrentHashMap<IProject, Deferred<AnalysisResultWithProvider>>()
3337

34-
public fun resetCache(project: IProject) {
38+
fun resetCache(project: IProject) {
3539
synchronized(project) {
36-
cachedAnalysisResults.remove(project)
40+
cachedAnalysisResults.remove(project)?.cancel()
3741
}
3842
}
3943

40-
public fun resetAllCaches() {
44+
fun resetAllCaches() {
4145
cachedAnalysisResults.keys.toList().forEach {
4246
resetCache(it)
4347
}
4448
}
4549

46-
public fun getAnalysisResult(javaProject: IJavaProject): AnalysisResult {
47-
val project = javaProject.getProject()
48-
return synchronized(project) {
49-
val analysisResult = cachedAnalysisResults.get(project) ?: run {
50-
EclipseAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
51-
KotlinEnvironment.getEnvironment(project),
52-
ProjectUtils.getSourceFiles(javaProject.getProject())).analysisResult
50+
fun cancelablePostAnalysis(javaProject: IJavaProject, post: (AnalysisResult) -> Unit) {
51+
try {
52+
KotlinCoroutinesScope.async {
53+
resetCache(javaProject.project)
54+
post(getAnalysisResult(javaProject).analysisResult)
5355
}
54-
55-
cachedAnalysisResults.putIfAbsent(project, analysisResult) ?: analysisResult
56-
}
56+
} catch (e: CancellationException) {}
5757
}
5858

59-
public @Synchronized fun getAnalysisResultIfCached(project: IProject): AnalysisResult? {
60-
return cachedAnalysisResults.get(project)
59+
fun getAnalysisResult(javaProject: IJavaProject) : AnalysisResultWithProvider {
60+
return runBlocking {
61+
val project = javaProject.project
62+
synchronized(this@KotlinAnalysisProjectCache) {
63+
cachedAnalysisResults.getOrPut(project) { KotlinAnalyzer.analyzeProjectAsync(project) }
64+
}.await()
65+
}
6166
}
6267

6368
override fun resourceChanged(event: IResourceChangeEvent) {
64-
when (event.getType()) {
69+
when (event.type) {
6570
IResourceChangeEvent.PRE_DELETE,
6671
IResourceChangeEvent.PRE_CLOSE,
67-
IResourceChangeEvent.PRE_BUILD -> event.getDelta()?.accept { delta ->
68-
val resource = delta.getResource()
72+
IResourceChangeEvent.PRE_BUILD -> event.delta?.accept { delta ->
73+
val resource = delta.resource
6974
if (resource is IFile) {
7075
val javaProject = JavaCore.create(resource.getProject())
7176
if (KotlinPsiManager.isKotlinSourceFile(resource, javaProject)) {
72-
cachedAnalysisResults.remove(resource.getProject())
77+
resetCache(resource.getProject())
7378
}
7479

7580
return@accept false
@@ -79,4 +84,4 @@ public object KotlinAnalysisProjectCache : IResourceChangeListener {
7984
}
8085
}
8186
}
82-
}
87+
}

kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ object EclipseAnalyzerFacadeForJVM {
7070
}
7171

7272
val allFiles = LinkedHashSet<KtFile>(filesSet)
73-
val addedFiles = filesSet.map { getPath(it) }.filterNotNull().toSet()
73+
val addedFiles = filesSet.mapNotNull { getPath(it) }.toSet()
7474
ProjectUtils.getSourceFilesWithDependencies(environment.javaProject).filterNotTo(allFiles) {
7575
getPath(it) in addedFiles
7676
}

kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinAnalyzer.kt

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
*******************************************************************************/
1717
package org.jetbrains.kotlin.core.resolve
1818

19+
import kotlinx.coroutines.Deferred
20+
import kotlinx.coroutines.async
1921
import org.eclipse.core.resources.IProject
2022
import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache
2123
import org.jetbrains.kotlin.core.model.KotlinEnvironment
2224
import org.jetbrains.kotlin.core.model.getEnvironment
25+
import org.jetbrains.kotlin.core.utils.ProjectUtils
2326
import org.jetbrains.kotlin.psi.KtFile
2427

2528
object KotlinAnalyzer {
@@ -34,27 +37,25 @@ object KotlinAnalyzer {
3437
files.size == 1 -> analyzeFile(files.single())
3538

3639
else -> {
37-
val environment = getEnvironment(files.first().project)
38-
if (environment == null) {
40+
val environment = getEnvironment(files.first().project) ?:
3941
throw IllegalStateException("There is no environment for project: ${files.first().project}")
40-
}
41-
42-
if (environment !is KotlinEnvironment) {
42+
43+
environment as? KotlinEnvironment ?:
4344
throw IllegalStateException("Only KotlinEnvironment can be used to analyze several files")
44-
}
45-
45+
4646
analyzeFiles(environment, files)
4747
}
4848
}
4949
}
50-
51-
fun analyzeProject(eclipseProject: IProject): AnalysisResultWithProvider {
52-
val environment = KotlinEnvironment.getEnvironment(eclipseProject)
53-
return analyzeFiles(environment, emptyList())
54-
}
50+
51+
fun analyzeProjectAsync(project: IProject) : Deferred<AnalysisResultWithProvider> =
52+
KotlinCoroutinesScope.async {
53+
analyzeFiles(
54+
KotlinEnvironment.getEnvironment(project),
55+
ProjectUtils.getSourceFiles(project))
56+
}
5557

5658
private fun analyzeFiles(kotlinEnvironment: KotlinEnvironment,
57-
filesToAnalyze: Collection<KtFile>): AnalysisResultWithProvider {
58-
return EclipseAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(kotlinEnvironment, filesToAnalyze)
59-
}
59+
filesToAnalyze: Collection<KtFile>): AnalysisResultWithProvider =
60+
EclipseAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(kotlinEnvironment, filesToAnalyze)
6061
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.jetbrains.kotlin.core.resolve
2+
3+
import kotlinx.coroutines.CoroutineScope
4+
import kotlinx.coroutines.Dispatchers
5+
import kotlinx.coroutines.GlobalScope
6+
import kotlinx.coroutines.Job
7+
import kotlinx.coroutines.SupervisorJob
8+
import kotlinx.coroutines.joinAll
9+
import kotlinx.coroutines.launch
10+
import kotlinx.coroutines.runBlocking
11+
import kotlin.coroutines.CoroutineContext
12+
13+
object KotlinCoroutinesScope : CoroutineScope {
14+
15+
private val job: Job by lazy { SupervisorJob() }
16+
17+
override val coroutineContext: CoroutineContext
18+
get() = job + Dispatchers.Default
19+
20+
@JvmStatic
21+
fun join() = runBlocking {
22+
job.children.toList().joinAll()
23+
}
24+
}

0 commit comments

Comments
 (0)