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.progress.util.ProgressIndicatorUtils
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
fun <T : Any> runInReadActionWithWriteActionPriority(f: () -> T): T? { fun <T : Any> runInReadActionWithWriteActionPriorityWithPCE(f: () -> T): T {
var r: T? = null var r: T? = null
if (!with(ApplicationManager.getApplication()) { isDispatchThread && isUnitTestMode }) { if (!with(ApplicationManager.getApplication()) { isDispatchThread && isUnitTestMode }) {
ProgressIndicatorUtils.runInReadActionWithWriteActionPriority { val complete = ProgressIndicatorUtils.runInReadActionWithWriteActionPriority {
r = f() r = f()
} }
// There is a write action in progress or pending, so no point in counting the result
if (!complete) throw ProcessCanceledException()
} }
else { else {
r = f() 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!! return r!!
} }
@@ -38,7 +38,7 @@ import org.intellij.plugins.intelliLang.util.AnnotationUtilEx
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.references.KtReference 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.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -74,19 +74,18 @@ class KotlinLanguageInjector(
val needImmediateAnswer = with(ApplicationManager.getApplication()) { isDispatchThread && !isUnitTestMode } val needImmediateAnswer = with(ApplicationManager.getApplication()) { isDispatchThread && !isUnitTestMode }
val kotlinCachedInjection = ktHost.cachedInjectionWithModification val kotlinCachedInjection = ktHost.cachedInjectionWithModification
val cachedBaseInjection = kotlinCachedInjection?.baseInjection ?: ABSENT_KOTLIN_INJECTION
val modificationCount = PsiManager.getInstance(project).modificationTracker.modificationCount val modificationCount = PsiManager.getInstance(project).modificationTracker.modificationCount
val baseInjection = when { val baseInjection = when {
needImmediateAnswer -> cachedBaseInjection needImmediateAnswer -> kotlinCachedInjection?.baseInjection ?: ABSENT_KOTLIN_INJECTION
kotlinCachedInjection != null && (modificationCount == kotlinCachedInjection.modificationCount) -> kotlinCachedInjection != null && (modificationCount == kotlinCachedInjection.modificationCount) ->
kotlinCachedInjection.baseInjection kotlinCachedInjection.baseInjection
else -> { else -> {
runInReadActionWithWriteActionPriority { runInReadActionWithWriteActionPriorityWithPCE {
val computedInjection = computeBaseInjection(ktHost, support, registrar) ?: ABSENT_KOTLIN_INJECTION val computedInjection = computeBaseInjection(ktHost, support, registrar) ?: ABSENT_KOTLIN_INJECTION
ktHost.cachedInjectionWithModification = KotlinCachedInjection(modificationCount, computedInjection) ktHost.cachedInjectionWithModification = KotlinCachedInjection(modificationCount, computedInjection)
computedInjection computedInjection
} ?: cachedBaseInjection }
} }
} }