KT-32366: Use TextEditorWithPreview as editor for scratch files
- get rid of `ScratchFileHook` completely - use `KtsScratchFileEditorProvider` to encapsulate details about scratch file presentation - remove obsolete functions from `scratchUtils`
This commit is contained in:
committed by
Roman Golyshev
parent
37c6102a03
commit
1d6de45db6
@@ -21,8 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.scratch.attachedOutputHandler
|
||||
import org.jetbrains.kotlin.idea.scratch.getScratchFile
|
||||
import org.jetbrains.kotlin.idea.scratch.ui.findScratchFileEditorWithPreview
|
||||
|
||||
class ClearScratchAction : ScratchAction(
|
||||
KotlinBundle.message("scratch.clear.button"),
|
||||
@@ -33,8 +32,7 @@ class ClearScratchAction : ScratchAction(
|
||||
|
||||
val selectedEditor = FileEditorManager.getInstance(project).selectedTextEditor ?: return
|
||||
val textEditor = TextEditorProvider.getInstance().getTextEditor(selectedEditor)
|
||||
val scratchFile = textEditor.getScratchFile() ?: return
|
||||
|
||||
textEditor.attachedOutputHandler?.clear(scratchFile)
|
||||
textEditor.findScratchFileEditorWithPreview()?.clearOutputHandlers()
|
||||
}
|
||||
}
|
||||
@@ -12,14 +12,9 @@ import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.TextEditor
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.idea.actions.KOTLIN_WORKSHEET_EXTENSION
|
||||
import org.jetbrains.kotlin.idea.scratch.output.ScratchOutputHandler
|
||||
import org.jetbrains.kotlin.idea.scratch.ui.ScratchTopPanel
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
import org.jetbrains.kotlin.idea.scratch.ui.findScratchFileEditorWithPreview
|
||||
|
||||
internal val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.scratch")
|
||||
internal fun Logger.printDebugMessage(str: String) {
|
||||
@@ -32,12 +27,6 @@ val VirtualFile.isKotlinWorksheet: Boolean
|
||||
val VirtualFile.isKotlinScratch: Boolean
|
||||
get() = ScratchFileService.getInstance().getRootType(this) is ScratchRootType
|
||||
|
||||
fun getEditorWithoutScratchFile(fileManager: FileEditorManager, virtualFile: VirtualFile): TextEditor? {
|
||||
val editor = fileManager.getSelectedEditor(virtualFile) as? TextEditor
|
||||
if (editor?.getScratchFile() != null) return null
|
||||
return editor
|
||||
}
|
||||
|
||||
fun getScratchFileFromEditorSelectedForFile(fileManager: FileEditorManager, virtualFile: VirtualFile): ScratchFile? {
|
||||
val editor = fileManager.getSelectedEditor(virtualFile) as? TextEditor ?: return null
|
||||
return editor.getScratchFile()
|
||||
@@ -49,22 +38,5 @@ fun getScratchFileFromSelectedEditor(project: Project): ScratchFile? {
|
||||
}
|
||||
|
||||
fun TextEditor.getScratchFile(): ScratchFile? {
|
||||
return scratchTopPanel?.scratchFile
|
||||
return findScratchFileEditorWithPreview()?.scratchFile
|
||||
}
|
||||
|
||||
fun TextEditor.addScratchPanel(panel: ScratchTopPanel) {
|
||||
scratchTopPanel = panel
|
||||
FileEditorManager.getInstance(panel.scratchFile.project).addTopComponent(this, panel.component)
|
||||
|
||||
Disposer.register(this, panel)
|
||||
}
|
||||
|
||||
fun TextEditor.attachOutputHandler(handler: ScratchOutputHandler) {
|
||||
outputHandler = handler
|
||||
}
|
||||
|
||||
val TextEditor.attachedOutputHandler: ScratchOutputHandler? get() = outputHandler
|
||||
|
||||
private var TextEditor.scratchTopPanel: ScratchTopPanel? by UserDataProperty<TextEditor, ScratchTopPanel>(Key.create("scratch.panel"))
|
||||
|
||||
private var TextEditor.outputHandler: ScratchOutputHandler? by UserDataProperty<TextEditor, ScratchOutputHandler>(Key.create("scratch.output.handler"))
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.scratch.ui
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.ActionToolbar
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.EditorFactory
|
||||
import com.intellij.openapi.fileEditor.FileEditor
|
||||
import com.intellij.openapi.fileEditor.FileEditorPolicy
|
||||
import com.intellij.openapi.fileEditor.FileEditorProvider
|
||||
import com.intellij.openapi.fileEditor.TextEditor
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.pom.Navigatable
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.idea.scratch.*
|
||||
import org.jetbrains.kotlin.idea.scratch.output.InlayScratchOutputHandler
|
||||
import org.jetbrains.kotlin.idea.scratch.output.ScratchOutputHandlerAdapter
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
|
||||
private const val KTS_SCRATCH_EDITOR_PROVIDER: String = "KtsScratchFileEditorProvider"
|
||||
|
||||
class KtScratchFileEditorProvider : FileEditorProvider, DumbAware {
|
||||
override fun getEditorTypeId(): String = KTS_SCRATCH_EDITOR_PROVIDER
|
||||
|
||||
override fun accept(project: Project, file: VirtualFile): Boolean {
|
||||
if (!file.isValid) return false
|
||||
if (!(file.isKotlinScratch || file.isKotlinWorksheet)) return false
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file) ?: return false
|
||||
return ScratchFileLanguageProvider.get(psiFile.fileType) != null
|
||||
}
|
||||
|
||||
override fun createEditor(project: Project, file: VirtualFile): FileEditor {
|
||||
val scratchFile = createScratchFile(project, file) ?: return TextEditorProvider.getInstance().createEditor(project, file)
|
||||
|
||||
return KtScratchFileEditorWithPreview.create(scratchFile)
|
||||
}
|
||||
|
||||
override fun getPolicy(): FileEditorPolicy = FileEditorPolicy.HIDE_DEFAULT_EDITOR
|
||||
}
|
||||
|
||||
class KtScratchFileEditorWithPreview private constructor(
|
||||
val scratchFile: ScratchFile,
|
||||
editor: TextEditor,
|
||||
preview: TextEditor
|
||||
) : TextEditorWithPreview(editor, preview), TextEditor {
|
||||
|
||||
private val inlayOutputHandler = InlayScratchOutputHandler(editor)
|
||||
private val scratchTopPanel = ScratchTopPanel(scratchFile)
|
||||
|
||||
init {
|
||||
editor.parentScratchEditorWithPreview = this
|
||||
|
||||
scratchFile.compilingScratchExecutor?.addOutputHandler(inlayOutputHandler)
|
||||
scratchFile.replScratchExecutor?.addOutputHandler(inlayOutputHandler)
|
||||
|
||||
ScratchFileAutoRunner.addListener(scratchFile.project, editor)
|
||||
}
|
||||
|
||||
override fun dispose() {
|
||||
scratchFile.replScratchExecutor?.stop()
|
||||
scratchFile.compilingScratchExecutor?.stop()
|
||||
super.dispose()
|
||||
}
|
||||
|
||||
override fun navigateTo(navigatable: Navigatable) {
|
||||
myEditor.navigateTo(navigatable)
|
||||
}
|
||||
|
||||
override fun canNavigateTo(navigatable: Navigatable): Boolean {
|
||||
return myEditor.canNavigateTo(navigatable)
|
||||
}
|
||||
|
||||
override fun getEditor(): Editor {
|
||||
return myEditor.editor
|
||||
}
|
||||
|
||||
override fun createToolbar(): ActionToolbar? {
|
||||
return scratchTopPanel.actionsToolbar
|
||||
}
|
||||
|
||||
fun clearOutputHandlers() {
|
||||
inlayOutputHandler.clear(scratchFile)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun create(scratchFile: ScratchFile): KtScratchFileEditorWithPreview {
|
||||
val textEditorProvider = TextEditorProvider.getInstance()
|
||||
|
||||
val mainEditor = textEditorProvider.createEditor(scratchFile.project, scratchFile.file) as TextEditor
|
||||
val editorFactory = EditorFactory.getInstance()
|
||||
|
||||
val viewer = editorFactory.createViewer(editorFactory.createDocument(""))
|
||||
Disposer.register(mainEditor, Disposable { editorFactory.releaseEditor(viewer) })
|
||||
|
||||
val previewEditor = textEditorProvider.getTextEditor(viewer)
|
||||
|
||||
return KtScratchFileEditorWithPreview(scratchFile, mainEditor, previewEditor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun TextEditor.findScratchFileEditorWithPreview(): KtScratchFileEditorWithPreview? =
|
||||
if (this is KtScratchFileEditorWithPreview) this else parentScratchEditorWithPreview
|
||||
|
||||
private var TextEditor.parentScratchEditorWithPreview: KtScratchFileEditorWithPreview?
|
||||
by UserDataProperty(Key.create("parent.preview.editor"))
|
||||
|
||||
fun createScratchFile(project: Project, file: VirtualFile): ScratchFile? {
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file) ?: return null
|
||||
val scratchFile = ScratchFileLanguageProvider.get(psiFile.language)?.newScratchFile(project, file) ?: return null
|
||||
setupCodeAnalyzerRestarterOutputHandler(project, scratchFile)
|
||||
|
||||
return scratchFile
|
||||
}
|
||||
|
||||
private fun setupCodeAnalyzerRestarterOutputHandler(project: Project, scratchFile: ScratchFile) {
|
||||
scratchFile.replScratchExecutor?.addOutputHandler(object : ScratchOutputHandlerAdapter() {
|
||||
override fun onFinish(file: ScratchFile) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
if (!file.project.isDisposed) {
|
||||
val scratch = file.getPsiFile()
|
||||
if (scratch?.isValid == true) {
|
||||
DaemonCodeAnalyzer.getInstance(project).restart(scratch)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.scratch.ui
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.ProjectComponent
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.FileEditorManagerListener
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.idea.scratch.*
|
||||
import org.jetbrains.kotlin.idea.scratch.output.InlayScratchOutputHandler
|
||||
import org.jetbrains.kotlin.idea.scratch.output.ScratchOutputHandlerAdapter
|
||||
|
||||
class ScratchFileHook(val project: Project) : ProjectComponent {
|
||||
|
||||
override fun projectOpened() {
|
||||
project.messageBus.connect(project).subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, ScratchEditorListener())
|
||||
}
|
||||
|
||||
private inner class ScratchEditorListener : FileEditorManagerListener {
|
||||
override fun fileOpened(source: FileEditorManager, file: VirtualFile) {
|
||||
if (!isPluggable(file)) return
|
||||
|
||||
val editor = getEditorWithoutScratchFile(source, file) ?: return
|
||||
|
||||
val scratchFile = createScratchFile(project, file) ?: return
|
||||
|
||||
val inlayOutputHandler = InlayScratchOutputHandler(editor)
|
||||
scratchFile.compilingScratchExecutor?.addOutputHandler(inlayOutputHandler)
|
||||
scratchFile.replScratchExecutor?.addOutputHandler(inlayOutputHandler)
|
||||
editor.attachOutputHandler(inlayOutputHandler)
|
||||
|
||||
editor.addScratchPanel(ScratchTopPanel(scratchFile))
|
||||
|
||||
ScratchFileAutoRunner.addListener(project, editor)
|
||||
}
|
||||
|
||||
override fun fileClosed(source: FileEditorManager, file: VirtualFile) {}
|
||||
}
|
||||
|
||||
private fun isPluggable(file: VirtualFile): Boolean {
|
||||
if (!file.isValid) return false
|
||||
if (!(file.isKotlinScratch || file.isKotlinWorksheet)) return false
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file) ?: return false
|
||||
return ScratchFileLanguageProvider.get(psiFile.fileType) != null
|
||||
}
|
||||
}
|
||||
|
||||
private fun createScratchFile(project: Project, file: VirtualFile): ScratchFile? {
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file) ?: return null
|
||||
val scratchFile = ScratchFileLanguageProvider.get(psiFile.language)?.newScratchFile(project, file) ?: return null
|
||||
setupReplRestartingOutputHandler(project, scratchFile)
|
||||
|
||||
return scratchFile
|
||||
}
|
||||
|
||||
private fun setupReplRestartingOutputHandler(project: Project, scratchFile: ScratchFile) {
|
||||
scratchFile.replScratchExecutor?.addOutputHandler(object : ScratchOutputHandlerAdapter() {
|
||||
override fun onFinish(file: ScratchFile) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
if (!file.project.isDisposed) {
|
||||
val scratch = file.getPsiFile()
|
||||
if (scratch?.isValid == true) {
|
||||
DaemonCodeAnalyzer.getInstance(project).restart(scratch)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -29,17 +29,11 @@ import org.jetbrains.kotlin.idea.scratch.actions.StopScratchAction
|
||||
import org.jetbrains.kotlin.idea.scratch.output.ScratchOutputHandlerAdapter
|
||||
import javax.swing.JComponent
|
||||
|
||||
class ScratchTopPanel(val scratchFile: ScratchFile) : Disposable {
|
||||
override fun dispose() {
|
||||
scratchFile.replScratchExecutor?.stop()
|
||||
scratchFile.compilingScratchExecutor?.stop()
|
||||
}
|
||||
|
||||
class ScratchTopPanel(val scratchFile: ScratchFile) {
|
||||
private val moduleChooserAction: ModulesComboBoxAction = ModulesComboBoxAction(scratchFile)
|
||||
private val actionsToolbar: ActionToolbar
|
||||
val actionsToolbar: ActionToolbar
|
||||
|
||||
init {
|
||||
scratchFile.addModuleListener { _, _ -> updateToolbar() }
|
||||
setupTopPanelUpdateHandlers()
|
||||
|
||||
val toolbarGroup = DefaultActionGroup().apply {
|
||||
@@ -59,9 +53,9 @@ class ScratchTopPanel(val scratchFile: ScratchFile) : Disposable {
|
||||
actionsToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.EDITOR_TOOLBAR, toolbarGroup, true)
|
||||
}
|
||||
|
||||
val component: JComponent = actionsToolbar.component
|
||||
|
||||
private fun setupTopPanelUpdateHandlers() {
|
||||
scratchFile.addModuleListener { _, _ -> updateToolbar() }
|
||||
|
||||
val toolbarHandler = createUpdateToolbarHandler()
|
||||
scratchFile.replScratchExecutor?.addOutputHandler(toolbarHandler)
|
||||
scratchFile.compilingScratchExecutor?.addOutputHandler(toolbarHandler)
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
description="Add all transitive dependencies on MPP modules when Android project is imported"
|
||||
defaultValue="true"
|
||||
restartRequired="false"/>
|
||||
<fileEditorProvider implementation="org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorProvider"/>
|
||||
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -104,6 +104,7 @@
|
||||
description="Add all transitive dependencies on MPP modules when Android project is imported"
|
||||
defaultValue="true"
|
||||
restartRequired="false"/>
|
||||
<fileEditorProvider implementation="org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorProvider"/>
|
||||
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
description="Add all transitive dependencies on MPP modules when Android project is imported"
|
||||
defaultValue="true"
|
||||
restartRequired="false"/>
|
||||
<fileEditorProvider implementation="org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorProvider"/>
|
||||
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
description="Add all transitive dependencies on MPP modules when Android project is imported"
|
||||
defaultValue="true"
|
||||
restartRequired="false"/>
|
||||
<fileEditorProvider implementation="org.jetbrains.kotlin.idea.scratch.ui.KtScratchFileEditorProvider"/>
|
||||
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ui.ScratchFileHook</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider</implementation-class>
|
||||
</component>
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ui.ScratchFileHook</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider</implementation-class>
|
||||
</component>
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.configuration.ui.KotlinConfigurationCheckerComponent</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ui.ScratchFileHook</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.kotlin.idea.scratch.ScratchFileModuleInfoProvider</implementation-class>
|
||||
</component>
|
||||
|
||||
Reference in New Issue
Block a user