Fix outdated highlighting for Kotlin injected fragments (KT-18842)

Do not use cached value for injection in non-dispatch threads and throw
PCE if value isn't ready. Otherwise outdated value may be stored in
highlighting.

 #KT-18842 Fixed
This commit is contained in:
Nikolay Krasko
2017-07-21 15:54:18 +03:00
parent 7f8e7c66f5
commit b6bd3e15c5
2 changed files with 9 additions and 18 deletions
@@ -22,27 +22,19 @@ import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.util.ProgressIndicatorUtils
import com.intellij.openapi.project.Project
fun <T : Any> runInReadActionWithWriteActionPriority(f: () -> T): T? {
fun <T : Any> runInReadActionWithWriteActionPriorityWithPCE(f: () -> T): T {
var r: T? = null
if (!with(ApplicationManager.getApplication()) { isDispatchThread && isUnitTestMode }) {
ProgressIndicatorUtils.runInReadActionWithWriteActionPriority {
val complete = ProgressIndicatorUtils.runInReadActionWithWriteActionPriority {
r = f()
}
// There is a write action in progress or pending, so no point in counting the result
if (!complete) throw ProcessCanceledException()
}
else {
r = f()
}
return r
}
fun <T : Any> runInReadActionWithWriteActionPriorityWithPCE(f: () -> T): T {
var r: T? = null
val complete = ProgressIndicatorUtils.runInReadActionWithWriteActionPriority {
r = f()
}
// There is a write action in progress or pending, so no point in counting the result
if (!complete) throw ProcessCanceledException()
return r!!
}
@@ -38,7 +38,7 @@ import org.intellij.plugins.intelliLang.util.AnnotationUtilEx
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.runInReadActionWithWriteActionPriority
import org.jetbrains.kotlin.idea.runInReadActionWithWriteActionPriorityWithPCE
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
@@ -74,19 +74,18 @@ class KotlinLanguageInjector(
val needImmediateAnswer = with(ApplicationManager.getApplication()) { isDispatchThread && !isUnitTestMode }
val kotlinCachedInjection = ktHost.cachedInjectionWithModification
val cachedBaseInjection = kotlinCachedInjection?.baseInjection ?: ABSENT_KOTLIN_INJECTION
val modificationCount = PsiManager.getInstance(project).modificationTracker.modificationCount
val baseInjection = when {
needImmediateAnswer -> cachedBaseInjection
needImmediateAnswer -> kotlinCachedInjection?.baseInjection ?: ABSENT_KOTLIN_INJECTION
kotlinCachedInjection != null && (modificationCount == kotlinCachedInjection.modificationCount) ->
kotlinCachedInjection.baseInjection
else -> {
runInReadActionWithWriteActionPriority {
runInReadActionWithWriteActionPriorityWithPCE {
val computedInjection = computeBaseInjection(ktHost, support, registrar) ?: ABSENT_KOTLIN_INJECTION
ktHost.cachedInjectionWithModification = KotlinCachedInjection(modificationCount, computedInjection)
computedInjection
} ?: cachedBaseInjection
}
}
}