[reader mode] IDEA-305056 EA-697215 use timestamps to re-run a visual formatting pass only when needed

Use a combination of Document and CodeStyleSettings timestamps to detect when visual formatting information needs to be recomputed, instead of FileStatusMap and manual DaemonCodeAnalyzer.restarts on CodeStyleSettingsChanged events

GitOrigin-RevId: baf73652d4e0a8a948183aa7baf1eed9cdfd8714
This commit is contained in:
Vojtech Balik
2024-04-09 14:52:39 +02:00
committed by intellij-monorepo-bot
parent 1b275b3f52
commit 85afa4fbc6
5 changed files with 32 additions and 64 deletions

View File

@@ -12797,21 +12797,6 @@ c:com.intellij.formatting.service.FormattingUiNotificationService
- reportError(java.lang.String,java.lang.String,java.lang.String):V
- reportError(java.lang.String,java.lang.String,java.lang.String,com.intellij.openapi.actionSystem.AnAction[]):V
- reportErrorAndNavigate(java.lang.String,java.lang.String,java.lang.String,com.intellij.formatting.FormattingContext,I):V
f:com.intellij.formatting.visualLayer.VisualFormattingLayerHighlightingPass
- com.intellij.codeHighlighting.EditorBoundHighlightingPass
- <init>(com.intellij.openapi.editor.Editor,com.intellij.psi.PsiFile):V
- doApplyInformationToEditor():V
- doCollectInformation(com.intellij.openapi.progress.ProgressIndicator):V
- f:getService():com.intellij.formatting.visualLayer.VisualFormattingLayerService
f:com.intellij.formatting.visualLayer.VisualFormattingLayerHighlightingPassFactory
- com.intellij.codeHighlighting.DirtyScopeTrackingHighlightingPassFactory
- <init>(com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar):V
- createHighlightingPass(com.intellij.psi.PsiFile,com.intellij.openapi.editor.Editor):com.intellij.formatting.visualLayer.VisualFormattingLayerHighlightingPass
- getPassId():I
f:com.intellij.formatting.visualLayer.VisualFormattingLayerHighlightingPassFactory$Registrar
- com.intellij.codeHighlighting.TextEditorHighlightingPassFactoryRegistrar
- <init>():V
- registerHighlightingPassFactory(com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar,com.intellij.openapi.project.Project):V
f:com.intellij.formatting.visualLayer.VisualFormattingLayerServiceImpl
- com.intellij.formatting.visualLayer.VisualFormattingLayerService
- <init>():V

View File

@@ -1,33 +1,32 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:Internal
package com.intellij.formatting.visualLayer
import com.intellij.codeHighlighting.*
import com.intellij.codeInsight.daemon.impl.FileStatusMap
import com.intellij.codeHighlighting.EditorBoundHighlightingPass
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactoryRegistrar
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar
import com.intellij.formatting.visualLayer.VisualFormattingLayerService.Companion.visualFormattingLayerCodeStyleSettings
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiFile
import org.jetbrains.annotations.ApiStatus.Internal
internal class VisualFormattingLayerHighlightingPassFactory : TextEditorHighlightingPassFactory, TextEditorHighlightingPassFactoryRegistrar {
class VisualFormattingLayerHighlightingPassFactory(registrar: TextEditorHighlightingPassRegistrar) : DirtyScopeTrackingHighlightingPassFactory {
class Registrar : TextEditorHighlightingPassFactoryRegistrar {
override fun registerHighlightingPassFactory(registrar: TextEditorHighlightingPassRegistrar, project: Project) {
VisualFormattingLayerHighlightingPassFactory(registrar)
}
}
override fun createHighlightingPass(file: PsiFile, editor: Editor): EditorBoundHighlightingPass? =
if (editor.vfmtTimestamp == editor.getCurrentVfmtTimestamp()) null
else VisualFormattingLayerHighlightingPass(editor, file)
private val passId = registrar.registerTextEditorHighlightingPass(this, null, null, false, -1)
override fun getPassId(): Int = passId
override fun createHighlightingPass(file: PsiFile, editor: Editor): VisualFormattingLayerHighlightingPass? {
FileStatusMap.getDirtyTextRange(editor.document, file, passId) ?: return null
return VisualFormattingLayerHighlightingPass(editor, file)
override fun registerHighlightingPassFactory(registrar: TextEditorHighlightingPassRegistrar, project: Project) {
registrar.registerTextEditorHighlightingPass(this, null, null, false, -1)
}
}
class VisualFormattingLayerHighlightingPass(editor: Editor, file: PsiFile) : EditorBoundHighlightingPass(editor, file, true) {
private class VisualFormattingLayerHighlightingPass(editor: Editor, file: PsiFile) : EditorBoundHighlightingPass(editor, file, true) {
val service: VisualFormattingLayerService by lazy { VisualFormattingLayerService.getInstance() }
@@ -39,6 +38,22 @@ class VisualFormattingLayerHighlightingPass(editor: Editor, file: PsiFile) : Edi
override fun doApplyInformationToEditor() {
service.applyVisualFormattingLayerElementsToEditor(myEditor, myVisualFormattingLayerElements)
myEditor.vfmtTimestamp = myEditor.getCurrentVfmtTimestamp()
}
}
private data class Timestamp(val documentStamp: Long, val codeStyleSettingsStamp: Long)
private val VFMT_TIMESTAMP = Key.create<Timestamp>("com.intellij.formatting.visualLayer.VFMT_TIMESTAMP")
private fun Editor.getCurrentVfmtTimestamp(): Timestamp? {
val vfmtCodeStyle = this.visualFormattingLayerCodeStyleSettings ?: return null
return Timestamp(
this.document.modificationStamp,
vfmtCodeStyle.modificationTracker.modificationCount)
}
private var Editor.vfmtTimestamp
get() = getUserData(VFMT_TIMESTAMP)
set(value) = putUserData(VFMT_TIMESTAMP, value)

View File

@@ -1,29 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.formatting.visualLayer
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.formatting.visualLayer.VisualFormattingLayerService.Companion.visualFormattingLayerCodeStyleSettings
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.codeStyle.CodeStyleSettingsChangeEvent
import com.intellij.psi.codeStyle.CodeStyleSettingsListener
private class VisualFormattingRestartingListener(private val project: Project) : CodeStyleSettingsListener {
override fun codeStyleSettingsChanged(event: CodeStyleSettingsChangeEvent) {
val virtualFile = event.virtualFile
val psiDocumentManager = PsiDocumentManager.getInstance(project)
val daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project)
val editors = FileEditorManager.getInstance(project).run {
if (virtualFile == null) allEditors.asList() else getAllEditorList(virtualFile)
}
editors
.filter {
it is TextEditor && it.editor.visualFormattingLayerCodeStyleSettings != null && !it.editor.document.isWritable
}
.mapNotNull { psiDocumentManager.getCachedPsiFile((it as TextEditor).editor.document) }
.toSet()
.forEach(daemonCodeAnalyzer::restart)
}
}

View File

@@ -1622,7 +1622,7 @@
<highlightingPassFactory implementation="com.intellij.codeInsight.daemon.impl.ExternalToolPassFactory"/>
<highlightingPassFactory implementation="com.intellij.codeInsight.daemon.impl.WolfPassFactory"/>
<highlightingPassFactory implementation="com.intellij.formatting.visualLayer.VisualFormattingLayerHighlightingPassFactory$Registrar"/>
<highlightingPassFactory implementation="com.intellij.formatting.visualLayer.VisualFormattingLayerHighlightingPassFactory"/>
<applicationService serviceInterface="com.intellij.openapi.roots.libraries.LibraryKindRegistry"
serviceImplementation="com.intellij.openapi.roots.impl.libraries.LibraryKindRegistryImpl"

View File

@@ -270,8 +270,5 @@
<listener class="com.intellij.psi.search.scope.packageSet.UpdatingScopeOnProjectStructureChangeListener"
topic="com.intellij.openapi.project.ModuleListener"/>
<listener class="com.intellij.formatting.visualLayer.VisualFormattingRestartingListener"
topic="com.intellij.psi.codeStyle.CodeStyleSettingsListener"/>
</projectListeners>
</idea-plugin>