From 85afa4fbc6b7cf2e2abd6c36ed1e80d32ccd57c4 Mon Sep 17 00:00:00 2001 From: Vojtech Balik Date: Tue, 9 Apr 2024 14:52:39 +0200 Subject: [PATCH] [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 --- platform/lang-impl/api-dump-unreviewed.txt | 15 ------ .../VisualFormattingLayerHighlightingPass.kt | 47 ++++++++++++------- .../VisualFormattingRestartingListener.kt | 29 ------------ .../src/META-INF/LangExtensions.xml | 2 +- .../src/META-INF/PlatformLangComponents.xml | 3 -- 5 files changed, 32 insertions(+), 64 deletions(-) delete mode 100644 platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingRestartingListener.kt diff --git a/platform/lang-impl/api-dump-unreviewed.txt b/platform/lang-impl/api-dump-unreviewed.txt index 36e87773f9b9..339995fc2f4b 100644 --- a/platform/lang-impl/api-dump-unreviewed.txt +++ b/platform/lang-impl/api-dump-unreviewed.txt @@ -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 -- (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 -- (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 -- ():V -- registerHighlightingPassFactory(com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar,com.intellij.openapi.project.Project):V f:com.intellij.formatting.visualLayer.VisualFormattingLayerServiceImpl - com.intellij.formatting.visualLayer.VisualFormattingLayerService - ():V diff --git a/platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingLayerHighlightingPass.kt b/platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingLayerHighlightingPass.kt index 5356092cd690..9a4313b54e30 100644 --- a/platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingLayerHighlightingPass.kt +++ b/platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingLayerHighlightingPass.kt @@ -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("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) diff --git a/platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingRestartingListener.kt b/platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingRestartingListener.kt deleted file mode 100644 index b5885de47f88..000000000000 --- a/platform/lang-impl/src/com/intellij/formatting/visualLayer/VisualFormattingRestartingListener.kt +++ /dev/null @@ -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) - } -} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ff8e4ebe0144..83a7eb7888d6 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -1622,7 +1622,7 @@ - + - -