[ide-console] Move warning messages about compilation inside consoleView
This commit is contained in:
committed by
Pavel V. Talanov
parent
058b539004
commit
fcc5fa13f3
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.console
|
||||
|
||||
import com.intellij.execution.ExecutionManager
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.ui.RunContentDescriptor
|
||||
import com.intellij.openapi.compiler.CompileContext
|
||||
import com.intellij.openapi.compiler.CompilerManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
public class KotlinConsoleCompilerHelper(
|
||||
private val project: Project,
|
||||
private val module: Module,
|
||||
private val executor: Executor,
|
||||
private val contentDescriptor: RunContentDescriptor
|
||||
) {
|
||||
|
||||
fun moduleIsUpToDate(): Boolean {
|
||||
val compilerManager = CompilerManager.getInstance(project)
|
||||
val compilerScope = compilerManager.createModuleCompileScope(module, true)
|
||||
return compilerManager.isUpToDate(compilerScope)
|
||||
}
|
||||
|
||||
fun compileModule() {
|
||||
if (ExecutionManager.getInstance(project).contentManager.removeRunContent(executor, contentDescriptor)) {
|
||||
CompilerManager.getInstance(project).make(module) {
|
||||
aborted: Boolean, errors: Int, warnings: Int, compileContext: CompileContext ->
|
||||
if (!module.isDisposed) {
|
||||
KotlinConsoleKeeper.getInstance(project).run(module, previousCompilationFailed = errors > 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,11 +44,11 @@ public class KotlinConsoleKeeper(val project: Project) {
|
||||
fun putVirtualFileToConsole(virtualFile: VirtualFile, console: KotlinConsoleRunner) = consoleMap.put(virtualFile, console)
|
||||
fun removeConsole(virtualFile: VirtualFile) = consoleMap.remove(virtualFile)
|
||||
|
||||
fun run(module: Module, previousCompilationFailed: Boolean = false, testMode: Boolean = false): KotlinConsoleRunner? {
|
||||
fun run(module: Module, testMode: Boolean = false, previousCompilationFailed: Boolean = false): KotlinConsoleRunner? {
|
||||
val path = module.moduleFilePath
|
||||
val cmdLine = createCommandLine(module) ?: return errorNotification(project, "Module SDK not found") let { null }
|
||||
|
||||
val consoleRunner = KotlinConsoleRunner(cmdLine, module, previousCompilationFailed, testMode, project, REPL_TITLE, path)
|
||||
val consoleRunner = KotlinConsoleRunner(module, cmdLine, testMode, previousCompilationFailed, project, REPL_TITLE, path)
|
||||
consoleRunner.initAndRun()
|
||||
consoleRunner.setupGutters()
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import com.intellij.openapi.editor.markup.*
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.util.Consumer
|
||||
import org.jetbrains.kotlin.console.actions.BuildAndRestartConsoleAction
|
||||
import org.jetbrains.kotlin.console.actions.KtExecuteCommandAction
|
||||
import org.jetbrains.kotlin.console.gutter.KotlinConsoleGutterContentProvider
|
||||
@@ -46,20 +45,21 @@ import javax.swing.Icon
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
public class KotlinConsoleRunner(
|
||||
val module: Module,
|
||||
private val cmdLine: GeneralCommandLine,
|
||||
private val module: Module,
|
||||
private val previousCompilationFailed: Boolean,
|
||||
private val testMode: Boolean,
|
||||
private val previousCompilationFailed: Boolean,
|
||||
myProject: Project,
|
||||
title: String,
|
||||
path: String?
|
||||
) : AbstractConsoleRunnerWithHistory<LanguageConsoleView>(myProject, title, path) {
|
||||
private val editorToIndicator = ConcurrentHashMap<EditorEx, RangeHighlighter>()
|
||||
private val historyManager = KotlinConsoleHistoryManager(this)
|
||||
val executor = KotlinConsoleExecutor(this, historyManager)
|
||||
|
||||
private var disposableDescriptor: RunContentDescriptor by Delegates.notNull()
|
||||
|
||||
val executor = KotlinConsoleExecutor(this, historyManager)
|
||||
var compilerHelper: KotlinConsoleCompilerHelper by Delegates.notNull()
|
||||
|
||||
override fun createProcess() = cmdLine.createProcess()
|
||||
|
||||
override fun createConsoleView(): LanguageConsoleView? {
|
||||
@@ -81,7 +81,9 @@ public class KotlinConsoleRunner(
|
||||
}
|
||||
|
||||
override fun createProcessHandler(process: Process): OSProcessHandler {
|
||||
val processHandler = KotlinReplOutputHandler(KotlinReplOutputHighlighter(this, historyManager), process, cmdLine.commandLineString)
|
||||
val processHandler = KotlinReplOutputHandler(
|
||||
KotlinReplOutputHighlighter(this, historyManager, testMode, previousCompilationFailed), process, cmdLine.commandLineString
|
||||
)
|
||||
val consoleFile = consoleView.virtualFile
|
||||
val keeper = KotlinConsoleKeeper.getInstance(project)
|
||||
|
||||
@@ -104,9 +106,10 @@ public class KotlinConsoleRunner(
|
||||
contentDescriptor: RunContentDescriptor
|
||||
): List<AnAction> {
|
||||
disposableDescriptor = contentDescriptor
|
||||
compilerHelper = KotlinConsoleCompilerHelper(project, module, defaultExecutor, contentDescriptor)
|
||||
|
||||
val actionList = arrayListOf<AnAction>(
|
||||
BuildAndRestartConsoleAction(project, module, defaultExecutor, contentDescriptor, previousCompilationFailed, testMode),
|
||||
BuildAndRestartConsoleAction(this),
|
||||
createConsoleExecAction(consoleExecuteActionHandler),
|
||||
createCloseAction(defaultExecutor, contentDescriptor)
|
||||
)
|
||||
|
||||
@@ -42,6 +42,7 @@ public class KotlinReplOutputHandler(
|
||||
commandLine: String
|
||||
) : OSProcessHandler(process, commandLine) {
|
||||
|
||||
private var isBuildInfoChecked = false
|
||||
private val dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
|
||||
override fun isSilentlyDestroyOnClose() = true
|
||||
@@ -56,7 +57,7 @@ public class KotlinReplOutputHandler(
|
||||
val content = StringUtil.replace(root.textContent, XML_REPLACEMENTS, SOURCE_CHARS)
|
||||
|
||||
when (outputType) {
|
||||
"INITIAL_PROMPT" -> outputHighlighter.printInitialPrompt(content)
|
||||
"INITIAL_PROMPT" -> buildWarningIfNeededBeforeInit(content)
|
||||
"HELP_PROMPT" -> outputHighlighter.printHelp(content)
|
||||
"USER_OUTPUT" -> outputHighlighter.printUserOutput(content)
|
||||
"REPL_RESULT" -> outputHighlighter.printResultWithGutterIcon(content)
|
||||
@@ -67,6 +68,14 @@ public class KotlinReplOutputHandler(
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildWarningIfNeededBeforeInit(content: String) {
|
||||
if (!isBuildInfoChecked) {
|
||||
outputHighlighter.printBuildInfoWarningIfNeeded()
|
||||
isBuildInfoChecked = true
|
||||
}
|
||||
outputHighlighter.printInitialPrompt(content)
|
||||
}
|
||||
|
||||
private fun strToSource(s: String, encoding: Charset = Charsets.UTF_8) = InputSource(ByteArrayInputStream(s.toByteArray(encoding)))
|
||||
|
||||
private fun createCompilerMessages(runtimeErrorsReport: String): List<SeverityDetails> {
|
||||
|
||||
+4
-66
@@ -16,76 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.console.actions
|
||||
|
||||
import com.intellij.execution.ExecutionManager
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.ui.RunContentDescriptor
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.notification.Notification
|
||||
import com.intellij.notification.NotificationListener
|
||||
import com.intellij.notification.NotificationType
|
||||
import com.intellij.notification.Notifications
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.compiler.CompileContext
|
||||
import com.intellij.openapi.compiler.CompilerManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.console.KotlinConsoleKeeper
|
||||
import javax.swing.event.HyperlinkEvent
|
||||
|
||||
private fun buildAndRestartMessage(module: Module) = "Build module '${module.name}' and restart"
|
||||
import org.jetbrains.kotlin.console.KotlinConsoleRunner
|
||||
|
||||
public class BuildAndRestartConsoleAction(
|
||||
private val project: Project,
|
||||
private val module: Module,
|
||||
private val executor: Executor,
|
||||
private val contentDescriptor: RunContentDescriptor,
|
||||
private val previousCompilationFailed: Boolean,
|
||||
private val testMode: Boolean
|
||||
) : AnAction("Build and restart", buildAndRestartMessage(module), AllIcons.Actions.Restart) {
|
||||
private val runner: KotlinConsoleRunner
|
||||
) : AnAction("Build and restart", "Build module '${runner.module.name}' and restart", AllIcons.Actions.Restart) {
|
||||
|
||||
init {
|
||||
if (!testMode && !previousCompilationFailed) showOutdatedClassesNotificationIfNeeded()
|
||||
}
|
||||
|
||||
override fun actionPerformed(_: AnActionEvent) = compileModule()
|
||||
|
||||
private fun compileModule() {
|
||||
if (ExecutionManager.getInstance(project).contentManager.removeRunContent(executor, contentDescriptor)) {
|
||||
CompilerManager.getInstance(project).make(module) {
|
||||
aborted: Boolean, errors: Int, warnings: Int, compileContext: CompileContext ->
|
||||
if (!module.isDisposed) {
|
||||
val compilationFailed = aborted || errors > 0
|
||||
if (compilationFailed) warningNotification("Compilation wasn't ended properly")
|
||||
|
||||
KotlinConsoleKeeper.getInstance(project).run(module, previousCompilationFailed = compilationFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showOutdatedClassesNotificationIfNeeded() {
|
||||
val compilerManager = CompilerManager.getInstance(project)
|
||||
val compilerScope = compilerManager.createModuleCompileScope(module, true)
|
||||
if (compilerManager.isUpToDate(compilerScope)) return
|
||||
|
||||
val message = "You’re running the REPL with outdated classes<br><a href=\"Build and restart\">${buildAndRestartMessage(module)}</a>"
|
||||
val hyperlinkListener = object : NotificationListener {
|
||||
override fun hyperlinkUpdate(notification: Notification, event: HyperlinkEvent) {
|
||||
if (event.eventType == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
compileModule()
|
||||
notification.expire()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
warningNotification(message, hyperlinkListener)
|
||||
}
|
||||
|
||||
private fun warningNotification(message: String, hyperlinkListener: NotificationListener? = null) {
|
||||
val warningTag = "KOTLIN REPL WARNING"
|
||||
val warningTitle = "Kotlin REPL Configuration Warning"
|
||||
|
||||
Notifications.Bus.notify(Notification(warningTag, warningTitle, message, NotificationType.WARNING, hyperlinkListener), project)
|
||||
}
|
||||
override fun actionPerformed(_: AnActionEvent) = runner.compilerHelper.compileModule()
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.idea.JetIcons
|
||||
import javax.swing.Icon
|
||||
|
||||
public object ReplIcons {
|
||||
public val BUILD_WARNING_INDICATOR: Icon = AllIcons.General.Information
|
||||
public val HISTORY_INDICATOR: Icon = AllIcons.General.MessageHistory
|
||||
public val EDITOR_INDICATOR: Icon = JetIcons.LAUNCH
|
||||
public val INCOMPLETE_INDICATOR: Icon = AllIcons.Nodes.Desktop
|
||||
|
||||
+30
-3
@@ -47,7 +47,9 @@ enum class ReplOutputType {
|
||||
|
||||
public class KotlinReplOutputHighlighter(
|
||||
private val runner: KotlinConsoleRunner,
|
||||
private val historyManager: KotlinConsoleHistoryManager
|
||||
private val historyManager: KotlinConsoleHistoryManager,
|
||||
private val testMode: Boolean,
|
||||
private val previousCompilationFailed: Boolean
|
||||
) {
|
||||
private val project = runner.project
|
||||
private val consoleView = runner.consoleView as LanguageConsoleImpl
|
||||
@@ -65,17 +67,42 @@ public class KotlinReplOutputHighlighter(
|
||||
return Pair(oldLen, newLen)
|
||||
}
|
||||
|
||||
private fun printOutput(output: String, contentType: ConsoleViewContentType, icon: Icon) {
|
||||
private fun printOutput(output: String, contentType: ConsoleViewContentType, icon: Icon? = null) {
|
||||
val (startOffset, endOffset) = textOffsets(output)
|
||||
|
||||
consoleView.print(output, contentType)
|
||||
consoleView.flushDeferredText()
|
||||
|
||||
if (icon == null) return
|
||||
|
||||
historyMarkup.addRangeHighlighter(
|
||||
startOffset, endOffset, HighlighterLayer.LAST, null, HighlighterTargetArea.EXACT_RANGE
|
||||
) apply { gutterIconRenderer = KotlinConsoleIndicatorRenderer(icon) }
|
||||
}
|
||||
|
||||
private fun printWarningMessage(message: String, isAddHyperlink: Boolean) = WriteCommandAction.runWriteCommandAction(project) {
|
||||
printOutput("\n", ConsoleViewContentType.NORMAL_OUTPUT)
|
||||
|
||||
printOutput(message, ReplColors.WARNING_INFO_CONTENT_TYPE, ReplIcons.BUILD_WARNING_INDICATOR)
|
||||
|
||||
if (isAddHyperlink) {
|
||||
consoleView.printHyperlink("Build module '${runner.module.name}' and restart") {
|
||||
runner.compilerHelper.compileModule()
|
||||
}
|
||||
}
|
||||
|
||||
printOutput("\n\n", ConsoleViewContentType.NORMAL_OUTPUT)
|
||||
}
|
||||
|
||||
fun printBuildInfoWarningIfNeeded() {
|
||||
if (testMode) return
|
||||
if (previousCompilationFailed) return printWarningMessage("There were compilation errors in module ${runner.module.name}", false)
|
||||
if (runner.compilerHelper.moduleIsUpToDate()) return
|
||||
|
||||
val compilerWarningMessage = "You’re running the REPL with outdated classes: "
|
||||
printWarningMessage(compilerWarningMessage, true)
|
||||
}
|
||||
|
||||
fun printInitialPrompt(command: String) = consoleView.print(command, ReplColors.INITIAL_PROMPT_CONTENT_TYPE)
|
||||
|
||||
fun printHelp(help: String) = WriteCommandAction.runWriteCommandAction(project) {
|
||||
@@ -105,7 +132,7 @@ public class KotlinReplOutputHighlighter(
|
||||
// remove line breaks after incomplete part
|
||||
val historyText = historyDocument.text
|
||||
val historyLength = historyText.length()
|
||||
val trimmedHistoryText = historyText.trim()
|
||||
val trimmedHistoryText = historyText.trimEnd()
|
||||
val whitespaceCharsToDelete = historyLength - trimmedHistoryText.length()
|
||||
|
||||
historyDocument.deleteString(historyLength - whitespaceCharsToDelete, historyLength)
|
||||
|
||||
@@ -28,6 +28,11 @@ public object ReplColors {
|
||||
public val EDITOR_GUTTER_COLOR: JBColor = JBColor(Gray.xCF, Gray.x31)
|
||||
public val PLACEHOLDER_COLOR: JBColor = JBColor.LIGHT_GRAY
|
||||
|
||||
public val WARNING_INFO_CONTENT_TYPE: ConsoleViewContentType =
|
||||
ConsoleViewContentType(
|
||||
"KOTLIN_CONSOLE_WARNING_INFO",
|
||||
TextAttributes() apply { fontType = Font.ITALIC; foregroundColor = JBColor.RED }
|
||||
)
|
||||
public val INITIAL_PROMPT_CONTENT_TYPE: ConsoleViewContentType =
|
||||
ConsoleViewContentType(
|
||||
"KOTLIN_CONSOLE_INITIAL_PROMPT",
|
||||
|
||||
Reference in New Issue
Block a user