mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 15:19:59 +07:00
[git/codevision] IJPL-187222 Move git files status check outside of read lock
(cherry picked from commit 4fcde413ecb397be7dbb8a668de208df37442942) IJ-MR-162706 GitOrigin-RevId: 9c1ea6a236049d3774d7d412042dc4e3d53be236
This commit is contained in:
committed by
intellij-monorepo-bot
parent
fad6b49fb0
commit
8db2bb18d0
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
package com.intellij.codeInsight.hints
|
||||
|
||||
@@ -12,12 +12,12 @@ import com.intellij.openapi.actionSystem.ActionManager
|
||||
import com.intellij.openapi.actionSystem.ActionPlaces
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectFileIndex
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
@@ -30,6 +30,7 @@ import com.intellij.openapi.vcs.actions.ShortNameType
|
||||
import com.intellij.openapi.vcs.annotate.AnnotationsPreloader
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation
|
||||
import com.intellij.openapi.vcs.annotate.LineAnnotationAspect
|
||||
import com.intellij.openapi.vcs.annotate.LineAnnotationAspect.AUTHOR
|
||||
import com.intellij.openapi.vcs.annotate.LineAnnotationAspectAdapter
|
||||
import com.intellij.openapi.vcs.impl.UpToDateLineNumberProviderImpl
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
@@ -62,15 +63,18 @@ class VcsCodeVisionProvider : CodeVisionProvider<Unit> {
|
||||
}
|
||||
|
||||
override fun computeCodeVision(editor: Editor, uiData: Unit): CodeVisionState {
|
||||
return runReadAction {
|
||||
val project = editor.project ?: return@runReadAction READY_EMPTY
|
||||
val document = editor.document
|
||||
val file = PsiDocumentManager.getInstance(project).getPsiFile(document) ?: return@runReadAction READY_EMPTY
|
||||
val project = editor.project ?: return READY_EMPTY
|
||||
val document = editor.document
|
||||
val fileAnnotationLoading =
|
||||
if (hasPreviewInfo(editor)) LoadingFileAnnotation.Loaded(null)
|
||||
else when (val annotation = getAnnotation(editor, project, document)) {
|
||||
AnnotationResult.NoAnnotation -> return CodeVisionState.Ready(emptyList())
|
||||
AnnotationResult.NotReady -> LoadingFileAnnotation.NotReady
|
||||
is AnnotationResult.Success -> LoadingFileAnnotation.Loaded(annotation.res)
|
||||
}
|
||||
|
||||
if (!hasSupportedVcs(project, file, editor)) return@runReadAction READY_EMPTY
|
||||
|
||||
val virtualFile = file.viewProvider.virtualFile
|
||||
if (ProjectFileIndex.getInstance(project).isInLibrarySource(virtualFile)) return@runReadAction READY_EMPTY
|
||||
return InlayHintsUtils.computeCodeVisionUnderReadAction {
|
||||
val file = PsiDocumentManager.getInstance(project).getPsiFile(document) ?: return@computeCodeVisionUnderReadAction READY_EMPTY
|
||||
|
||||
val fileLanguage = file.language
|
||||
val fileContext = VcsCodeVisionLanguageContext.providersExtensionPoint.forLanguage(fileLanguage)
|
||||
@@ -80,12 +84,18 @@ class VcsCodeVisionProvider : CodeVisionProvider<Unit> {
|
||||
it.isCustomFileAccepted(file)
|
||||
} ?: emptyList()
|
||||
else emptyList()
|
||||
if (fileContext == null && additionalContexts.isEmpty()) return@runReadAction READY_EMPTY
|
||||
// If an annotation is not loaded and the context can't be resolved, we can immediately return an empty state.
|
||||
if (fileContext == null && additionalContexts.isEmpty()) return@computeCodeVisionUnderReadAction READY_EMPTY
|
||||
if (fileAnnotationLoading !is LoadingFileAnnotation.Loaded) return@computeCodeVisionUnderReadAction CodeVisionState.NotReady
|
||||
|
||||
val aspect = when (val aspectResult = getAspect(file, editor)) {
|
||||
AnnotationResult.NoAnnotation -> return@runReadAction CodeVisionState.Ready(emptyList())
|
||||
AnnotationResult.NotReady -> return@runReadAction CodeVisionState.NotReady
|
||||
is AnnotationResult.Success -> aspectResult.res
|
||||
val aspect = when {
|
||||
hasPreviewInfo(editor) -> LineAnnotationAspectAdapter.NULL_ASPECT
|
||||
fileAnnotationLoading.annotation != null -> {
|
||||
val annotation = fileAnnotationLoading.annotation
|
||||
handleAnnotationRegistration(annotation, editor, project, VcsUtil.resolveSymlinkIfNeeded(project, file.viewProvider.virtualFile))
|
||||
annotation.aspects.find { it.id == AUTHOR }
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
|
||||
val lenses = ArrayList<Pair<TextRange, CodeVisionEntry>>()
|
||||
@@ -121,16 +131,32 @@ class VcsCodeVisionProvider : CodeVisionProvider<Unit> {
|
||||
lenses.add(adjustedRange to entry)
|
||||
}
|
||||
}
|
||||
return@runReadAction CodeVisionState.Ready(lenses)
|
||||
return@computeCodeVisionUnderReadAction CodeVisionState.Ready(lenses)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasSupportedVcs(project: Project, file: PsiFile, editor: Editor): Boolean {
|
||||
if (hasPreviewInfo(editor)) {
|
||||
return true
|
||||
private sealed class LoadingFileAnnotation {
|
||||
class Loaded(val annotation: FileAnnotation?) : LoadingFileAnnotation()
|
||||
object NotReady : LoadingFileAnnotation()
|
||||
}
|
||||
|
||||
private fun getAnnotation(editor: Editor, project: Project, document: Document): AnnotationResult<FileAnnotation?> {
|
||||
val fromUserData = editor.getUserData(VCS_CODE_AUTHOR_ANNOTATION)
|
||||
if (fromUserData != null) return AnnotationResult.Success(fromUserData)
|
||||
|
||||
val virtualFile = FileDocumentManager.getInstance().getFile(document)?.let { VcsUtil.resolveSymlinkIfNeeded(project, it) }
|
||||
?: return AnnotationResult.NoAnnotation
|
||||
val vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(virtualFile)?.takeIf { "Git" == it.name }
|
||||
?: return AnnotationResult.NoAnnotation
|
||||
val annotationProvider = vcs.annotationProvider as? CacheableAnnotationProvider
|
||||
?: return AnnotationResult.NoAnnotation
|
||||
val status = FileStatusManager.getInstance(project).getStatus(virtualFile)
|
||||
|
||||
return when (status) {
|
||||
FileStatus.UNKNOWN, FileStatus.IGNORED -> AnnotationResult.NoAnnotation
|
||||
FileStatus.ADDED -> AnnotationResult.Success(null) // new files have no annotation
|
||||
else -> getAnnotation(annotationProvider, virtualFile)
|
||||
}
|
||||
val vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(file.virtualFile) ?: return false
|
||||
return "Git" == vcs.name
|
||||
}
|
||||
|
||||
override fun getPlaceholderCollector(editor: Editor, psiFile: PsiFile?): CodeVisionPlaceholderCollector? {
|
||||
@@ -209,29 +235,15 @@ private fun getCodeAuthorInfo(project: Project, range: TextRange, editor: Editor
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAspect(file: PsiFile, editor: Editor): AnnotationResult<LineAnnotationAspect?> {
|
||||
if (hasPreviewInfo(editor)) return AnnotationResult.Success(LineAnnotationAspectAdapter.NULL_ASPECT)
|
||||
val virtualFile = file.virtualFile ?: return AnnotationResult.NoAnnotation
|
||||
val vcsFile = VcsUtil.resolveSymlinkIfNeeded(file.project, virtualFile)
|
||||
return when (val annotationResult = getAnnotation(file.project, vcsFile, editor)) {
|
||||
AnnotationResult.NoAnnotation -> AnnotationResult.NoAnnotation
|
||||
AnnotationResult.NotReady -> AnnotationResult.NotReady
|
||||
is AnnotationResult.Success -> AnnotationResult.Success(
|
||||
annotationResult.res?.aspects?.find { it.id == LineAnnotationAspect.AUTHOR })
|
||||
}
|
||||
}
|
||||
|
||||
private val VCS_CODE_AUTHOR_ANNOTATION = Key.create<FileAnnotation>("Vcs.CodeAuthor.Annotation")
|
||||
|
||||
private fun getAnnotation(project: Project, file: VirtualFile, editor: Editor): AnnotationResult<FileAnnotation?> {
|
||||
editor.getUserData(VCS_CODE_AUTHOR_ANNOTATION)?.let { return AnnotationResult.Success(it) }
|
||||
private fun getAnnotation(annotationProvider: CacheableAnnotationProvider, file: VirtualFile): AnnotationResult<FileAnnotation?> {
|
||||
val annotation = annotationProvider.getFromCache(file) ?: return AnnotationResult.NotReady
|
||||
return AnnotationResult.Success(annotation)
|
||||
}
|
||||
|
||||
val vcs = ProjectLevelVcsManager.getInstance(project).getVcsFor(file) ?: return AnnotationResult.NoAnnotation
|
||||
val provider = vcs.annotationProvider as? CacheableAnnotationProvider ?: return AnnotationResult.NoAnnotation
|
||||
val status = FileStatusManager.getInstance(project).getStatus(file)
|
||||
if (status == FileStatus.UNKNOWN || status == FileStatus.IGNORED) return AnnotationResult.NoAnnotation
|
||||
if (status == FileStatus.ADDED) return AnnotationResult.Success(null) // new files have no annotation
|
||||
val annotation = provider.getFromCache(file) ?: return AnnotationResult.NotReady
|
||||
private fun handleAnnotationRegistration(annotation: FileAnnotation, editor: Editor, project: Project, file: VirtualFile) {
|
||||
if (editor.getUserData(VCS_CODE_AUTHOR_ANNOTATION) != null) return
|
||||
|
||||
val annotationDisposable = Disposable {
|
||||
unregisterAnnotation(annotation)
|
||||
@@ -250,8 +262,6 @@ private fun getAnnotation(project: Project, file: VirtualFile, editor: Editor):
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
EditorUtil.disposeWithEditor(editor, annotationDisposable)
|
||||
}
|
||||
|
||||
return AnnotationResult.Success(annotation)
|
||||
}
|
||||
|
||||
private fun registerAnnotation(annotation: FileAnnotation) =
|
||||
|
||||
Reference in New Issue
Block a user