LSP-407 ContractInferenceIndexKt: extract contract inference gist to a service class

GitOrigin-RevId: e064a340a5fc3576d7fa482d9c68ff545bfae68a
This commit is contained in:
Bartek Pacia
2026-01-14 17:34:06 +00:00
committed by intellij-monorepo-bot
parent 527e4b4d8c
commit d5042e8d62
2 changed files with 42 additions and 6 deletions
@@ -0,0 +1,38 @@
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInspection.dataFlow.inference
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.Service
import com.intellij.util.gist.GistManager
import com.intellij.util.gist.PsiFileGist
private const val VERSION = 14
/**
* Holds the [PsiFileGist] for caching contract inference results.
* <p>
* This is a separate service to avoid accessing [GistManager] during static class initialization of [InferenceVisitor],
* which violates platform rules (class initialization must not depend on services).
* See LSP-407 to learn more.
*/
@Service
internal class ContractInferenceGist {
val gist: PsiFileGist<Map<Int, MethodData>> get() = _gist
private val _gist: PsiFileGist<Map<Int, MethodData>>
constructor() {
_gist = GistManager.getInstance().newPsiFileGist(
/* id = */ "contractInference",
/* version = */ VERSION,
/* externalizer = */ MethodDataExternalizer,
/* calcData = */ { psiFile -> indexFile(psiFile.node.lighterAST) },
)
}
companion object {
@JvmStatic
fun getInstance(): ContractInferenceGist {
return ApplicationManager.getApplication().getService(ContractInferenceGist::class.java)
}
}
}
@@ -23,17 +23,13 @@ import com.intellij.psi.util.CachedValuesManager
import com.intellij.util.gist.GistManager
import java.util.*
private val gist = GistManager.getInstance().newPsiFileGist("contractInference", 14, MethodDataExternalizer) { file ->
indexFile(file.node.lighterAST)
}
private fun indexFile(tree: LighterAST): Map<Int, MethodData> {
internal fun indexFile(tree: LighterAST): Map<Int, MethodData> {
val visitor = InferenceVisitor(tree)
visitor.visitNode(tree.root)
return visitor.result
}
internal data class ClassData(
private data class ClassData(
val hasSuper: Boolean,
val hasPureInitializer: Boolean,
val isFinal: Boolean,
@@ -206,6 +202,7 @@ public fun handleInconsistency(method: PsiMethodImpl, cachedData: MethodData, e:
if (e is ProcessCanceledException) return e
val file = method.containingFile
val gist = ContractInferenceGist.getInstance().gist
val gistMap = gist.getFileData(file)
GistManager.getInstance().invalidateData(file.viewProvider.virtualFile)
@@ -233,6 +230,7 @@ public fun handleInconsistency(method: PsiMethodImpl, cachedData: MethodData, e:
public fun getIndexedData(method: PsiMethodImpl): MethodData? {
val file = method.containingFile
val map = CachedValuesManager.getCachedValue(file) {
val gist = ContractInferenceGist.getInstance().gist
CachedValueProvider.Result.create(bindMethods(gist.getFileData(file), file), file)
}
return map[method]