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:
@@ -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
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user