FUS-842 log reader mode enabled/disabled state for open/close editor

GitOrigin-RevId: c1f701cac72dce8f29e3f9e4c12413d570bf8c8f
This commit is contained in:
Dmitry.Krasilschikov
2020-10-19 15:22:07 +00:00
committed by intellij-monorepo-bot
parent 90e6f69cd0
commit 94a7747e97
13 changed files with 179 additions and 161 deletions
@@ -2,8 +2,8 @@
package com.intellij.ide.impl
import com.intellij.codeInsight.actions.ReaderModeProvider
import com.intellij.codeInsight.actions.ReaderModeSettings
import com.intellij.codeInsight.daemon.impl.JavaCodeVisionProvider
import com.intellij.codeInsight.actions.ReaderModeSettings
import com.intellij.codeInsight.hints.InlayHintsPassFactory
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
@@ -15,4 +15,8 @@ interface ReaderModeProvider {
* otherwise, if it's false, it should apply changes for every opening file
*/
fun applyModeChanged(project: Project, editor: Editor, readerMode: Boolean, fileIsOpenAlready: Boolean) {}
enum class ReaderMode {
LIBRARIES, READ_ONLY, LIBRARIES_AND_READ_ONLY
}
}
@@ -1,6 +1,7 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.actions
import com.intellij.codeInsight.actions.ReaderModeSettings.Companion.matchMode
import com.intellij.icons.AllIcons
import com.intellij.ide.HelpTooltip
import com.intellij.lang.LangBundle
@@ -39,7 +40,7 @@ class ReaderModeActionProvider : InspectionWidgetActionProvider {
else {
if (project.isInitialized) {
val file = PsiDocumentManager.getInstance(project).getPsiFile(editor.document)?.virtualFile
e.presentation.isEnabledAndVisible = ReaderModeFileEditorListener.matchMode(project, file)
e.presentation.isEnabledAndVisible = matchMode(project, file)
}
else {
e.presentation.isEnabledAndVisible = false
@@ -3,9 +3,7 @@ package com.intellij.codeInsight.actions
import com.intellij.application.options.editor.CheckboxDescriptor
import com.intellij.application.options.editor.checkBox
import com.intellij.codeInsight.actions.ReaderMode.*
import com.intellij.lang.LangBundle
import com.intellij.openapi.components.*
import com.intellij.openapi.options.BoundSearchableConfigurable
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.DialogPanel
@@ -59,87 +57,4 @@ class ReaderModeConfigurable(val project: Project) : BoundSearchableConfigurable
super.apply()
project.messageBus.syncPublisher(READER_MODE_TOPIC).modeChanged(project)
}
}
enum class ReaderMode {
LIBRARIES, READ_ONLY, LIBRARIES_AND_READ_ONLY
}
@State(name = "ReaderModeSettings", storages = [Storage(StoragePathMacros.WORKSPACE_FILE)])
class ReaderModeSettings : PersistentStateComponentWithModificationTracker<ReaderModeSettings.State> {
companion object {
@JvmStatic
fun instance(project: Project): ReaderModeSettings {
return ServiceManager.getService(project, ReaderModeSettings::class.java)
}
}
private var myState = State()
class State : BaseState() {
var showBreadcrumbs: Boolean = true
var showLigatures: Boolean = true
var increaseLineSpacing: Boolean = false
var showRenderedDocs: Boolean = true
var showInlayHints: Boolean = true
var showWarnings: Boolean = false
@get:ReportValue
var enabled by property(true)
var mode: ReaderMode = LIBRARIES_AND_READ_ONLY
}
var showBreadcrumbs: Boolean
get() = state.showBreadcrumbs
set(value) {
state.showBreadcrumbs = value
}
var showLigatures: Boolean
get() = state.showLigatures
set(value) {
state.showLigatures = value
}
var increaseLineSpacing: Boolean
get() = state.increaseLineSpacing
set(value) {
state.increaseLineSpacing = value
}
var showInlaysHints: Boolean
get() = state.showInlayHints
set(value) {
state.showInlayHints = value
}
var showRenderedDocs: Boolean
get() = state.showRenderedDocs
set(value) {
state.showRenderedDocs = value
}
var showWarnings: Boolean
get() = state.showWarnings
set(value) {
state.showWarnings = value
}
var enabled: Boolean
get() = state.enabled
set(value) {
state.enabled = value
}
var mode: ReaderMode
get() = state.mode
set(value) {
state.mode = value
}
override fun getState(): State = myState
override fun loadState(state: State) {
myState = state
}
override fun getStateModificationCount() = state.modificationCount
}
@@ -1,65 +0,0 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.actions
import com.intellij.codeInsight.actions.ReaderModeFileEditorListener.Companion.applyReaderMode
import com.intellij.codeInsight.actions.ReaderModeSettings.Companion.instance
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.event.EditorFactoryEvent
import com.intellij.openapi.editor.event.EditorFactoryListener
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.fileEditor.*
import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.FileIndexFacade
import com.intellij.openapi.util.Pair
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiManager
class ReaderModeFileEditorListener : FileEditorManagerListener {
override fun fileOpenedSync(source: FileEditorManager, file: VirtualFile, editors: Pair<Array<FileEditor>, Array<FileEditorProvider>>) {
if (!instance(source.project).enabled) return
val selectedEditor = source.getSelectedEditor(file)
if (selectedEditor !is PsiAwareTextEditorImpl) return
applyReaderMode(source.project, selectedEditor.editor, file)
}
companion object {
private var EP_READER_MODE_PROVIDER = ExtensionPointName<ReaderModeProvider>("com.intellij.readerModeProvider")
fun applyReaderMode(project: Project, editor: Editor?, file: VirtualFile?, fileIsOpenAlready: Boolean = false) {
if (editor == null || file == null || PsiManager.getInstance(project).findFile(file) == null) return
if (matchMode(project, file)) {
EP_READER_MODE_PROVIDER.extensions().forEach {
it.applyModeChanged(project, editor, instance(project).enabled, fileIsOpenAlready)
}
}
}
fun matchMode(project: Project?, file: VirtualFile?): Boolean {
if (project == null || file == null) return false
val inLibraries = FileIndexFacade.getInstance(project).isInLibraryClasses(file) || FileIndexFacade.getInstance(project).isInLibrarySource(file)
val isWritable = file.isWritable
return when (instance(project).mode) {
ReaderMode.LIBRARIES_AND_READ_ONLY -> inLibraries || !isWritable
ReaderMode.LIBRARIES -> inLibraries
ReaderMode.READ_ONLY -> !isWritable
}
}
}
}
class ReaderModeEditorFactoryListener : EditorFactoryListener {
override fun editorCreated(event: EditorFactoryEvent) {
val editor = event.editor
val project = editor.project
if (project == null || !project.isInitialized || project.isDefault || !instance(project).enabled) return
if (editor !is EditorImpl) return
applyReaderMode(project, editor, FileDocumentManager.getInstance().getFile(editor.document))
}
}
@@ -1,7 +1,7 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.actions
import com.intellij.codeInsight.actions.ReaderModeFileEditorListener.Companion.applyReaderMode
import com.intellij.codeInsight.actions.ReaderModeSettings.Companion.applyReaderMode
import com.intellij.openapi.editor.EditorFactory
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.fileEditor.FileDocumentManager
@@ -42,7 +42,7 @@ class ReaderModeHighlightingSettingsProvider : DefaultHighlightingSettingProvide
override fun getDefaultSetting(project: Project, file: VirtualFile): FileHighlightingSetting? {
if (ReaderModeSettings.instance(project).enabled
&& !ReaderModeSettings.instance(project).showWarnings
&& ReaderModeFileEditorListener.matchMode(project, file)) {
&& ReaderModeSettings.matchMode(project, file)) {
return FileHighlightingSetting.SKIP_INSPECTION
}
@@ -0,0 +1,20 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.editorActions
import com.intellij.codeInsight.actions.ReaderModeSettings
import com.intellij.codeInsight.actions.ReaderModeSettings.Companion.applyReaderMode
import com.intellij.openapi.editor.event.EditorFactoryEvent
import com.intellij.openapi.editor.event.EditorFactoryListener
import com.intellij.openapi.editor.impl.EditorImpl
import com.intellij.openapi.fileEditor.FileDocumentManager
class ReaderModeEditorFactoryListener : EditorFactoryListener {
override fun editorCreated(event: EditorFactoryEvent) {
val editor = event.editor
val project = editor.project
if (project == null || !project.isInitialized || project.isDefault || !ReaderModeSettings.instance(project).enabled) return
if (editor !is EditorImpl) return
applyReaderMode(project, editor, FileDocumentManager.getInstance().getFile(editor.document))
}
}
@@ -0,0 +1,22 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.editorActions
import com.intellij.codeInsight.actions.ReaderModeSettings
import com.intellij.codeInsight.actions.ReaderModeSettings.Companion.applyReaderMode
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.FileEditorManagerListener
import com.intellij.openapi.fileEditor.FileEditorProvider
import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl
import com.intellij.openapi.util.Pair
import com.intellij.openapi.vfs.VirtualFile
class ReaderModeFileEditorListener : FileEditorManagerListener {
override fun fileOpenedSync(source: FileEditorManager, file: VirtualFile, editors: Pair<Array<FileEditor>, Array<FileEditorProvider>>) {
if (!ReaderModeSettings.instance(source.project).enabled) return
val selectedEditor = source.getSelectedEditor(file)
if (selectedEditor !is PsiAwareTextEditorImpl) return
applyReaderMode(source.project, selectedEditor.editor, file)
}
}
@@ -0,0 +1,116 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.actions
import com.intellij.codeInsight.actions.ReaderModeProvider.ReaderMode
import com.intellij.openapi.components.*
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.FileIndexFacade
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiManager
@State(name = "ReaderModeSettings", storages = [Storage(StoragePathMacros.WORKSPACE_FILE)])
class ReaderModeSettings : PersistentStateComponentWithModificationTracker<ReaderModeSettings.State> {
companion object {
private var EP_READER_MODE_PROVIDER = ExtensionPointName<ReaderModeProvider>("com.intellij.readerModeProvider")
@JvmStatic
fun instance(project: Project): ReaderModeSettings {
return ServiceManager.getService(project, ReaderModeSettings::class.java)
}
fun applyReaderMode(project: Project, editor: Editor?, file: VirtualFile?, fileIsOpenAlready: Boolean = false) {
if (editor == null || file == null || PsiManager.getInstance(project).findFile(file) == null) return
if (matchMode(project, file)) {
EP_READER_MODE_PROVIDER.extensions().forEach {
it.applyModeChanged(project, editor, instance(project).enabled, fileIsOpenAlready)
}
}
}
fun matchMode(project: Project?, file: VirtualFile?): Boolean {
if (project == null || file == null) return false
val inLibraries = FileIndexFacade.getInstance(project).isInLibraryClasses(file) || FileIndexFacade.getInstance(
project).isInLibrarySource(file)
val isWritable = file.isWritable
return when (instance(project).mode) {
ReaderMode.LIBRARIES_AND_READ_ONLY -> inLibraries || !isWritable
ReaderMode.LIBRARIES -> inLibraries
ReaderMode.READ_ONLY -> !isWritable
}
}
}
private var myState = State()
class State : BaseState() {
var showBreadcrumbs: Boolean = true
var showLigatures: Boolean = true
var increaseLineSpacing: Boolean = false
var showRenderedDocs: Boolean = true
var showInlayHints: Boolean = true
var showWarnings: Boolean = false
@get:ReportValue
var enabled by property(true)
var mode: ReaderMode = ReaderMode.LIBRARIES_AND_READ_ONLY
}
var showBreadcrumbs: Boolean
get() = state.showBreadcrumbs
set(value) {
state.showBreadcrumbs = value
}
var showLigatures: Boolean
get() = state.showLigatures
set(value) {
state.showLigatures = value
}
var increaseLineSpacing: Boolean
get() = state.increaseLineSpacing
set(value) {
state.increaseLineSpacing = value
}
var showInlaysHints: Boolean
get() = state.showInlayHints
set(value) {
state.showInlayHints = value
}
var showRenderedDocs: Boolean
get() = state.showRenderedDocs
set(value) {
state.showRenderedDocs = value
}
var showWarnings: Boolean
get() = state.showWarnings
set(value) {
state.showWarnings = value
}
var enabled: Boolean
get() = state.enabled
set(value) {
state.enabled = value
}
var mode: ReaderMode
get() = state.mode
set(value) {
state.mode = value
}
override fun getState(): State = myState
override fun loadState(state: State) {
myState = state
}
override fun getStateModificationCount() = state.modificationCount
}
@@ -1,12 +1,12 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.collectors.fus.fileTypes;
import com.intellij.codeInsight.actions.ReaderModeSettings;
import com.intellij.internal.statistic.eventLog.EventLogGroup;
import com.intellij.internal.statistic.eventLog.events.EventField;
import com.intellij.internal.statistic.eventLog.events.EventFields;
import com.intellij.internal.statistic.eventLog.events.EventPair;
import com.intellij.internal.statistic.eventLog.events.VarargEventId;
import com.intellij.internal.statistic.eventLog.fus.FeatureUsageLogger;
import com.intellij.internal.statistic.eventLog.validator.ValidationResultType;
import com.intellij.internal.statistic.eventLog.validator.rules.EventContext;
import com.intellij.internal.statistic.eventLog.validator.rules.impl.CustomValidationRule;
@@ -50,6 +50,7 @@ public class FileTypeUsageCounterCollector extends CounterUsagesCollector {
private static final EventField<String> FILE_TYPE = EventFields.StringValidatedByCustomRule("file_type", "file_type");
private static final EventField<String> SCHEMA = EventFields.StringValidatedByCustomRule("schema", "file_type_schema");
private static final EventField<Boolean> IS_WRITABLE = EventFields.Boolean("is_writable");
private static final EventField<Boolean> IS_IN_READER_MODE = EventFields.Boolean("is_in_reader_mode");
@Override
public EventLogGroup getGroup() {
@@ -63,8 +64,8 @@ public class FileTypeUsageCounterCollector extends CounterUsagesCollector {
private static final VarargEventId SELECT = registerFileTypeEvent("select");
private static final VarargEventId EDIT = registerFileTypeEvent("edit");
private static final VarargEventId OPEN = registerFileTypeEvent("open", IS_WRITABLE);
private static final VarargEventId CLOSE = registerFileTypeEvent("close", IS_WRITABLE);
private static final VarargEventId OPEN = registerFileTypeEvent("open", IS_WRITABLE, IS_IN_READER_MODE);
private static final VarargEventId CLOSE = registerFileTypeEvent("close", IS_WRITABLE, IS_IN_READER_MODE);
public static void triggerEdit(@NotNull Project project, @NotNull VirtualFile file) {
log(EDIT, project, file);
@@ -80,11 +81,15 @@ public class FileTypeUsageCounterCollector extends CounterUsagesCollector {
}
public static void triggerOpen(@NotNull Project project, @NotNull VirtualFile file) {
OPEN.log(project, ArrayUtil.append(buildCommonEventPairs(project, file), IS_WRITABLE.with(file.isWritable())));
OPEN.log(project, ArrayUtil.append(ArrayUtil.append(buildCommonEventPairs(project, file),
IS_WRITABLE.with(file.isWritable())),
IS_IN_READER_MODE.with(ReaderModeSettings.Companion.matchMode(project, file))));
}
public static void triggerClosed(@NotNull Project project, @NotNull VirtualFile file) {
CLOSE.log(project, ArrayUtil.append(buildCommonEventPairs(project, file), IS_WRITABLE.with(file.isWritable())));
CLOSE.log(project, ArrayUtil.append(ArrayUtil.append(buildCommonEventPairs(project, file),
IS_WRITABLE.with(file.isWritable())),
IS_IN_READER_MODE.with(ReaderModeSettings.Companion.matchMode(project, file))));
}
private static void log(@NotNull VarargEventId eventId, @NotNull Project project, @NotNull VirtualFile file) {
@@ -1101,7 +1101,7 @@
<backgroundPostStartupActivity implementation="com.intellij.accessibility.AccessibilityUsageTrackerCollector$CollectStatisticsTask"/>
<editorFactoryListener implementation="com.intellij.codeInsight.actions.ReaderModeEditorFactoryListener"/>
<editorFactoryListener implementation="com.intellij.codeInsight.editorActions.ReaderModeEditorFactoryListener"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains">
<urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/>
@@ -63,7 +63,7 @@
<!-- another one for project level -->
<listener class="com.intellij.notification.impl.MacEventReader" topic="com.intellij.notification.Notifications" os="mac" activeInHeadlessMode="false"/>
<listener class="com.intellij.notification.impl.NotificationsBeeper" topic="com.intellij.notification.Notifications" activeInHeadlessMode="false"/>
<listener class="com.intellij.codeInsight.actions.ReaderModeFileEditorListener"
<listener class="com.intellij.codeInsight.editorActions.ReaderModeFileEditorListener"
topic="com.intellij.openapi.fileEditor.FileEditorManagerListener" activeInHeadlessMode="false"/>
<listener class="com.intellij.codeInsight.actions.ReaderModeSettingsListener"
topic="com.intellij.codeInsight.actions.ReaderModeListener" activeInHeadlessMode="false"/>