From e46f69bb36acb8758e4843f9ad6e7dfa5f992de6 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 12 Jan 2018 18:45:34 +0100 Subject: [PATCH] Disable "Decompile" button if bytecode generation threw exception #KT-13791 Fixed --- .../idea/internal/KotlinBytecodeToolWindow.kt | 74 +++++++++++-------- .../AbstractBytecodeToolWindowTest.kt | 19 +---- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.kt b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.kt index dce826b80f4..1976afe36e9 100644 --- a/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.kt +++ b/idea/idea-jvm/src/org/jetbrains/kotlin/idea/internal/KotlinBytecodeToolWindow.kt @@ -48,6 +48,11 @@ import javax.swing.JButton import javax.swing.JCheckBox import javax.swing.JPanel +sealed class BytecodeGenerationResult { + data class Bytecode(val text: String) : BytecodeGenerationResult() + data class Error(val text: String) : BytecodeGenerationResult() +} + class KotlinBytecodeToolWindow(private val myProject: Project, private val toolWindow: ToolWindow) : JPanel(BorderLayout()), Disposable { private val LOG = Logger.getInstance(KotlinBytecodeToolWindow::class.java) @@ -59,7 +64,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW private val jvm8Target: JCheckBox private val ir: JCheckBox - private inner class UpdateBytecodeToolWindowTask : LongRunningReadTask() { + private inner class UpdateBytecodeToolWindowTask : LongRunningReadTask() { override fun prepareRequestInfo(): Location? { if (!toolWindow.isVisible) { return null @@ -87,7 +92,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW setText(DEFAULT_TEXT) } - override fun processRequest(location: Location): String { + override fun processRequest(location: Location): BytecodeGenerationResult { val ktFile = location.kFile!! val configuration = CompilerConfiguration() @@ -115,39 +120,48 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW return getBytecodeForFile(ktFile, configuration) } - override fun onResultReady(requestInfo: Location, resultText: String?) { + override fun onResultReady(requestInfo: Location, result: BytecodeGenerationResult?) { val editor = requestInfo.getEditor()!! - if (resultText == null) { + if (result == null) { return } - setText(resultText) + when (result) { + is BytecodeGenerationResult.Error -> { + decompile.isEnabled = false + setText(result.text) + } + is BytecodeGenerationResult.Bytecode -> { + decompile.isEnabled = true + setText(result.text) - val fileStartOffset = requestInfo.getStartOffset() - val fileEndOffset = requestInfo.getEndOffset() + val fileStartOffset = requestInfo.getStartOffset() + val fileEndOffset = requestInfo.getEndOffset() - val document = editor.document - val startLine = document.getLineNumber(fileStartOffset) - var endLine = document.getLineNumber(fileEndOffset) - if (endLine > startLine && fileEndOffset > 0 && document.charsSequence[fileEndOffset - 1] == '\n') { - endLine-- + val document = editor.document + val startLine = document.getLineNumber(fileStartOffset) + var endLine = document.getLineNumber(fileEndOffset) + if (endLine > startLine && fileEndOffset > 0 && document.charsSequence[fileEndOffset - 1] == '\n') { + endLine-- + } + + val byteCodeDocument = myEditor.document + + val linesRange = mapLines(byteCodeDocument.text, startLine, endLine) + val endSelectionLineIndex = Math.min(linesRange.second + 1, byteCodeDocument.lineCount) + + val startOffset = byteCodeDocument.getLineStartOffset(linesRange.first) + val endOffset = Math.min(byteCodeDocument.getLineStartOffset(endSelectionLineIndex), byteCodeDocument.textLength) + + myEditor.caretModel.moveToOffset(endOffset) + myEditor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE) + myEditor.caretModel.moveToOffset(startOffset) + myEditor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE) + + myEditor.selectionModel.setSelection(startOffset, endOffset) + } } - - val byteCodeDocument = myEditor.document - - val linesRange = mapLines(byteCodeDocument.text, startLine, endLine) - val endSelectionLineIndex = Math.min(linesRange.second + 1, byteCodeDocument.lineCount) - - val startOffset = byteCodeDocument.getLineStartOffset(linesRange.first) - val endOffset = Math.min(byteCodeDocument.getLineStartOffset(endSelectionLineIndex), byteCodeDocument.textLength) - - myEditor.caretModel.moveToOffset(endOffset) - myEditor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE) - myEditor.caretModel.moveToOffset(startOffset) - myEditor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE) - - myEditor.selectionModel.setSelection(startOffset, endOffset) } } @@ -217,14 +231,14 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW "*/" // public for tests - fun getBytecodeForFile(ktFile: KtFile, configuration: CompilerConfiguration): String { + fun getBytecodeForFile(ktFile: KtFile, configuration: CompilerConfiguration): BytecodeGenerationResult { val state: GenerationState try { state = compileSingleFile(ktFile, configuration) } catch (e: ProcessCanceledException) { throw e } catch (e: Exception) { - return printStackTraceToString(e) + return BytecodeGenerationResult.Error(printStackTraceToString(e)) } val answer = StringBuilder() @@ -252,7 +266,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW answer.append(outputFile.asText()).append("\n\n") } - return answer.toString() + return BytecodeGenerationResult.Bytecode(answer.toString()) } fun compileSingleFile( diff --git a/idea/tests/org/jetbrains/kotlin/idea/internal/AbstractBytecodeToolWindowTest.kt b/idea/tests/org/jetbrains/kotlin/idea/internal/AbstractBytecodeToolWindowTest.kt index 203db2fc4d8..8567d53f30e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/internal/AbstractBytecodeToolWindowTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/internal/AbstractBytecodeToolWindowTest.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2016 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. + * Copyright 2000-2018 JetBrains s.r.o. 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.internal @@ -51,8 +40,8 @@ abstract class AbstractBytecodeToolWindowTest: KotlinLightCodeInsightFixtureTest } val bytecodes = KotlinBytecodeToolWindow.getBytecodeForFile(file, configuration) - assert(bytecodes.contains("// ================")) { - "The header \"// ================\" is missing.\n This means that there is an exception failed during compilation:\n$bytecodes" + assert(bytecodes is BytecodeGenerationResult.Bytecode) { + "Exception failed during compilation:\n$bytecodes" } } }