Disable "Decompile" button if bytecode generation threw exception
#KT-13791 Fixed
This commit is contained in:
@@ -48,6 +48,11 @@ import javax.swing.JButton
|
|||||||
import javax.swing.JCheckBox
|
import javax.swing.JCheckBox
|
||||||
import javax.swing.JPanel
|
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 {
|
class KotlinBytecodeToolWindow(private val myProject: Project, private val toolWindow: ToolWindow) : JPanel(BorderLayout()), Disposable {
|
||||||
private val LOG = Logger.getInstance(KotlinBytecodeToolWindow::class.java)
|
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 jvm8Target: JCheckBox
|
||||||
private val ir: JCheckBox
|
private val ir: JCheckBox
|
||||||
|
|
||||||
private inner class UpdateBytecodeToolWindowTask : LongRunningReadTask<Location, String>() {
|
private inner class UpdateBytecodeToolWindowTask : LongRunningReadTask<Location, BytecodeGenerationResult>() {
|
||||||
override fun prepareRequestInfo(): Location? {
|
override fun prepareRequestInfo(): Location? {
|
||||||
if (!toolWindow.isVisible) {
|
if (!toolWindow.isVisible) {
|
||||||
return null
|
return null
|
||||||
@@ -87,7 +92,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
setText(DEFAULT_TEXT)
|
setText(DEFAULT_TEXT)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun processRequest(location: Location): String {
|
override fun processRequest(location: Location): BytecodeGenerationResult {
|
||||||
val ktFile = location.kFile!!
|
val ktFile = location.kFile!!
|
||||||
|
|
||||||
val configuration = CompilerConfiguration()
|
val configuration = CompilerConfiguration()
|
||||||
@@ -115,39 +120,48 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
return getBytecodeForFile(ktFile, configuration)
|
return getBytecodeForFile(ktFile, configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResultReady(requestInfo: Location, resultText: String?) {
|
override fun onResultReady(requestInfo: Location, result: BytecodeGenerationResult?) {
|
||||||
val editor = requestInfo.getEditor()!!
|
val editor = requestInfo.getEditor()!!
|
||||||
|
|
||||||
if (resultText == null) {
|
if (result == null) {
|
||||||
return
|
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 fileStartOffset = requestInfo.getStartOffset()
|
||||||
val fileEndOffset = requestInfo.getEndOffset()
|
val fileEndOffset = requestInfo.getEndOffset()
|
||||||
|
|
||||||
val document = editor.document
|
val document = editor.document
|
||||||
val startLine = document.getLineNumber(fileStartOffset)
|
val startLine = document.getLineNumber(fileStartOffset)
|
||||||
var endLine = document.getLineNumber(fileEndOffset)
|
var endLine = document.getLineNumber(fileEndOffset)
|
||||||
if (endLine > startLine && fileEndOffset > 0 && document.charsSequence[fileEndOffset - 1] == '\n') {
|
if (endLine > startLine && fileEndOffset > 0 && document.charsSequence[fileEndOffset - 1] == '\n') {
|
||||||
endLine--
|
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
|
// public for tests
|
||||||
fun getBytecodeForFile(ktFile: KtFile, configuration: CompilerConfiguration): String {
|
fun getBytecodeForFile(ktFile: KtFile, configuration: CompilerConfiguration): BytecodeGenerationResult {
|
||||||
val state: GenerationState
|
val state: GenerationState
|
||||||
try {
|
try {
|
||||||
state = compileSingleFile(ktFile, configuration)
|
state = compileSingleFile(ktFile, configuration)
|
||||||
} catch (e: ProcessCanceledException) {
|
} catch (e: ProcessCanceledException) {
|
||||||
throw e
|
throw e
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return printStackTraceToString(e)
|
return BytecodeGenerationResult.Error(printStackTraceToString(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
val answer = StringBuilder()
|
val answer = StringBuilder()
|
||||||
@@ -252,7 +266,7 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
|
|||||||
answer.append(outputFile.asText()).append("\n\n")
|
answer.append(outputFile.asText()).append("\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
return answer.toString()
|
return BytecodeGenerationResult.Bytecode(answer.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun compileSingleFile(
|
fun compileSingleFile(
|
||||||
|
|||||||
@@ -1,17 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
* 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.
|
||||||
* 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.internal
|
package org.jetbrains.kotlin.idea.internal
|
||||||
@@ -51,8 +40,8 @@ abstract class AbstractBytecodeToolWindowTest: KotlinLightCodeInsightFixtureTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
val bytecodes = KotlinBytecodeToolWindow.getBytecodeForFile(file, configuration)
|
val bytecodes = KotlinBytecodeToolWindow.getBytecodeForFile(file, configuration)
|
||||||
assert(bytecodes.contains("// ================")) {
|
assert(bytecodes is BytecodeGenerationResult.Bytecode) {
|
||||||
"The header \"// ================\" is missing.\n This means that there is an exception failed during compilation:\n$bytecodes"
|
"Exception failed during compilation:\n$bytecodes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user