idea: cleanup code

This commit is contained in:
Dmitry Gridin
2019-12-13 22:11:25 +07:00
parent e77d8657f4
commit 8dbbd64beb
897 changed files with 13161 additions and 18514 deletions
@@ -1,17 +1,6 @@
/*
* 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.
* 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.eval4j
@@ -182,7 +171,11 @@ class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(
when {
value == NULL_VALUE -> NULL_VALUE
eval.isInstanceOf(value, targetType) -> ObjectValue(value.obj(), targetType)
else -> throwInterpretingException(ClassCastException("${value.asmType.className} cannot be cast to ${targetType.className}"))
else -> throwInterpretingException(
ClassCastException(
"${value.asmType.className} cannot be cast to ${targetType.className}"
)
)
}
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.eval4j.jdi
@@ -444,10 +433,13 @@ open class JDIEval(
listOf(instance, mirrorOfArgs(args))
)
if (methodDesc.returnType.sort != Type.OBJECT && methodDesc.returnType.sort != Type.ARRAY && methodDesc.returnType.sort != Type.VOID) {
return unboxType(invocationResult, methodDesc.returnType)
}
return invocationResult
return if (methodDesc.returnType.sort != Type.OBJECT &&
methodDesc.returnType.sort != Type.ARRAY &&
methodDesc.returnType.sort != Type.VOID
)
unboxType(invocationResult, methodDesc.returnType)
else
invocationResult
}
private fun mirrorOfArgs(args: List<jdi_Value?>): Value {
@@ -1,17 +1,6 @@
/*
* 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.
* 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.eval4j.jdi.test
@@ -57,8 +46,8 @@ fun suite(): TestSuite {
req.enable()
val latch = CountDownLatch(1)
var classLoader : ClassLoaderReference? = null
var thread : ThreadReference? = null
var classLoader: ClassLoaderReference? = null
var thread: ThreadReference? = null
Thread {
val eventQueue = vm.eventQueue()
@@ -89,7 +78,8 @@ fun suite(): TestSuite {
break@mainLoop
}
else -> {}
else -> {
}
}
}
}
@@ -101,8 +91,7 @@ fun suite(): TestSuite {
var remainingTests = AtomicInteger(0)
val suite = buildTestSuite {
methodNode, ownerClass, expected ->
val suite = buildTestSuite { methodNode, ownerClass, expected ->
remainingTests.incrementAndGet()
object : TestCase(getTestName(methodNode.name)) {
@@ -112,47 +101,45 @@ fun suite(): TestSuite {
val args = if ((methodNode.access and Opcodes.ACC_STATIC) == 0) {
// Instance method
val newInstance = eval.newInstance(Type.getType(ownerClass))
val thisValue = eval.invokeMethod(newInstance, MethodDescription(ownerClass.name, "<init>", "()V", false), listOf(), true)
val thisValue =
eval.invokeMethod(newInstance, MethodDescription(ownerClass.name, "<init>", "()V", false), listOf(), true)
listOf(thisValue)
}
else {
} else {
listOf()
}
val value = interpreterLoop(
methodNode,
makeInitialFrame(methodNode, args),
eval
methodNode,
makeInitialFrame(methodNode, args),
eval
)
fun ObjectReference?.callToString(): String? {
if (this == null) return "null"
return (eval.invokeMethod(
this.asValue(),
MethodDescription(
"java/lang/Object",
"toString",
"()Ljava/lang/String;",
false
),
listOf()).jdiObj as StringReference).value()
this.asValue(),
MethodDescription(
"java/lang/Object",
"toString",
"()Ljava/lang/String;",
false
),
listOf()
).jdiObj as StringReference).value()
}
try {
if (expected is ValueReturned && value is ValueReturned && value.result is ObjectValue) {
assertEquals(expected.result.obj().toString(), value.result.jdiObj.callToString())
}
else if (expected is ExceptionThrown && value is ExceptionThrown) {
} else if (expected is ExceptionThrown && value is ExceptionThrown) {
val valueObj = value.exception.obj()
val actual = if (valueObj is ObjectReference) valueObj.callToString() else valueObj.toString()
assertEquals(expected.exception.obj().toString(), actual)
}
else {
} else {
assertEquals(expected, value)
}
}
finally {
} finally {
if (remainingTests.decrementAndGet() == 0) vm.resume()
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.eval4j.test
@@ -28,45 +17,42 @@ import org.junit.Assert.assertTrue
import java.lang.reflect.*
import java.lang.reflect.Array as JArray
fun suite(): TestSuite = buildTestSuite {
methodNode, ownerClass, expected ->
fun suite(): TestSuite = buildTestSuite { methodNode, ownerClass, expected ->
object : TestCase(getTestName(methodNode.name)) {
override fun runTest() {
if (!isIgnored(methodNode)) {
val value = interpreterLoop(
methodNode,
initFrame(
ownerClass.getInternalName(),
methodNode
),
REFLECTION_EVAL
)
if (expected is ExceptionThrown && value is ExceptionThrown) {
assertEquals(expected.exception.toString(), value.exception.toString())
}
else {
assertEquals(expected.toString(), value.toString())
}
override fun runTest() {
if (!isIgnored(methodNode)) {
val value = interpreterLoop(
methodNode,
initFrame(
ownerClass.getInternalName(),
methodNode
),
REFLECTION_EVAL
)
if (expected is ExceptionThrown && value is ExceptionThrown) {
assertEquals(expected.exception.toString(), value.exception.toString())
} else {
assertEquals(expected.toString(), value.toString())
}
}
private fun isIgnored(methodNode: MethodNode): Boolean {
return methodNode.visibleAnnotations?.any {
val annotationDesc = it.desc
annotationDesc != null &&
Type.getType(annotationDesc) == Type.getType(IgnoreInReflectionTests::class.java)
} ?: false
}
}
private fun isIgnored(methodNode: MethodNode): Boolean {
return methodNode.visibleAnnotations?.any {
val annotationDesc = it.desc
annotationDesc != null && Type.getType(annotationDesc) == Type.getType(IgnoreInReflectionTests::class.java)
} ?: false
}
}
}
fun Class<*>.getInternalName(): String = Type.getType(this).internalName
fun initFrame(
owner: String,
m: MethodNode
owner: String,
m: MethodNode
): Frame<Value> {
val current = Frame<Value>(m.maxLocals, m.maxStack)
current.setReturn(makeNotInitializedValue(Type.getReturnType(m.desc)))
@@ -80,7 +66,7 @@ fun initFrame(
}
val args = Type.getArgumentTypes(m.desc)
for (i in 0..args.size - 1) {
for (i in args.indices) {
current.setLocal(local++, makeNotInitializedValue(args[i]))
if (args[i].size == 2) {
current.setLocal(local++, NOT_A_VALUE)
@@ -198,12 +184,10 @@ object REFLECTION_EVAL : Eval {
try {
try {
return f()
} catch (ite: InvocationTargetException) {
throw ite.cause ?: ite
}
catch (ite: InvocationTargetException) {
throw ite.cause ?: ite
}
}
catch (e: Throwable) {
} catch (e: Throwable) {
throw ThrownFromEvaluatedCodeException(ObjectValue(e, Type.getType(e::class.java)))
}
}
@@ -211,14 +195,14 @@ object REFLECTION_EVAL : Eval {
override fun getStaticField(fieldDesc: FieldDescription): Value {
val field = findStaticField(fieldDesc)
val result = mayThrow {field.get(null)}
val result = mayThrow { field.get(null) }
return objectToValue(result, fieldDesc.fieldType)
}
override fun setStaticField(fieldDesc: FieldDescription, newValue: Value) {
val field = findStaticField(fieldDesc)
val obj = newValue.obj(fieldDesc.fieldType)
mayThrow {field.set(null, obj)}
mayThrow { field.set(null, obj) }
}
fun findStaticField(fieldDesc: FieldDescription): Field {
@@ -234,7 +218,7 @@ object REFLECTION_EVAL : Eval {
val method = findClass(methodDesc).findMethod(methodDesc)
assertNotNull("Method not found: $methodDesc", method)
val args = mapArguments(arguments, methodDesc.parameterTypes).toTypedArray()
val result = mayThrow {method!!.invoke(null, *args)}
val result = mayThrow { method!!.invoke(null, *args) }
return objectToValue(result, methodDesc.returnType)
}
@@ -250,7 +234,7 @@ object REFLECTION_EVAL : Eval {
val obj = instance.obj().checkNull()
val field = findInstanceField(obj, fieldDesc)
return objectToValue(mayThrow {field.get(obj)}, fieldDesc.fieldType)
return objectToValue(mayThrow { field.get(obj) }, fieldDesc.fieldType)
}
override fun setField(instance: Value, fieldDesc: FieldDescription, newValue: Value) {
@@ -258,7 +242,7 @@ object REFLECTION_EVAL : Eval {
val field = findInstanceField(obj, fieldDesc)
val newObj = newValue.obj(fieldDesc.fieldType)
mayThrow {field.set(obj, newObj)}
mayThrow { field.set(obj, newObj) }
}
fun findInstanceField(obj: Any, fieldDesc: FieldDescription): Field {
@@ -277,11 +261,10 @@ object REFLECTION_EVAL : Eval {
val ctor = _class.findConstructor(methodDesc)
assertNotNull("Constructor not found: $methodDesc", ctor)
val args = mapArguments(arguments, methodDesc.parameterTypes).toTypedArray()
val result = mayThrow {ctor!!.newInstance(*args)}
val result = mayThrow { ctor!!.newInstance(*args) }
instance.value = result
return objectToValue(result, instance.asmType)
}
else {
} else {
// TODO
throw UnsupportedOperationException("invokespecial is not suported in reflection eval")
}
@@ -290,7 +273,7 @@ object REFLECTION_EVAL : Eval {
val method = obj::class.java.findMethod(methodDesc)
assertNotNull("Method not found: $methodDesc", method)
val args = mapArguments(arguments, methodDesc.parameterTypes).toTypedArray()
val result = mayThrow {method!!.invoke(obj, *args)}
val result = mayThrow { method!!.invoke(obj, *args) }
return objectToValue(result, methodDesc.returnType)
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.eval4j.test
@@ -29,23 +18,26 @@ import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.lang.reflect.Modifier
import java.lang.reflect.Array as JArray
fun buildTestSuite(
create: (MethodNode, Class<*>, InterpreterResult?) -> TestCase
create: (MethodNode, Class<*>, InterpreterResult?) -> TestCase
): TestSuite {
val suite = TestSuite()
val ownerClass = TestData::class.java
ownerClass.classLoader!!.getResourceAsStream(ownerClass.getInternalName() + ".class")!!.use { inputStream ->
ClassReader(inputStream).accept(object : ClassVisitor(API_VERSION) {
override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
return object : MethodNode(API_VERSION, access, name, desc, signature, exceptions) {
override fun visitEnd() {
val testCase = buildTestCase(ownerClass, this, create)
if (testCase != null) {
suite.addTest(testCase)
}
override fun visitMethod(
access: Int,
name: String,
desc: String,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor? = object : MethodNode(API_VERSION, access, name, desc, signature, exceptions) {
override fun visitEnd() {
val testCase = buildTestCase(ownerClass, this, create)
if (testCase != null) {
suite.addTest(testCase)
}
}
}
@@ -55,32 +47,33 @@ fun buildTestSuite(
return suite
}
private fun buildTestCase(ownerClass: Class<TestData>,
methodNode: MethodNode,
create: (MethodNode, Class<out Any?>, InterpreterResult?) -> TestCase): TestCase? {
private fun buildTestCase(
ownerClass: Class<TestData>,
methodNode: MethodNode,
create: (MethodNode, Class<out Any?>, InterpreterResult?) -> TestCase
): TestCase? {
var expected: InterpreterResult? = null
for (method in ownerClass.declaredMethods) {
if (method.name == methodNode.name) {
val isStatic = (method.modifiers and Modifier.STATIC) != 0
if (method.parameterTypes!!.size > 0) {
if (method.parameterTypes!!.isNotEmpty()) {
println("Skipping method with parameters: $method")
}
else if (!isStatic && !method.name!!.startsWith("test")) {
} else if (!isStatic && !method.name!!.startsWith("test")) {
println("Skipping instance method (should be started with 'test') : $method")
}
else {
} else {
method.isAccessible = true
try {
val result = method.invoke(if (isStatic) null else ownerClass.newInstance())
val returnType = Type.getType(method.returnType!!)
expected = ValueReturned(objectToValue(result, returnType))
}
catch (e: UnsupportedOperationException) {
} catch (e: UnsupportedOperationException) {
println("Skipping $method: $e")
}
catch (e: Throwable) {
} catch (e: Throwable) {
val cause = e.cause ?: e
expected = ExceptionThrown(objectToValue(cause, Type.getType(cause::class.java)) as ObjectValue, ExceptionThrown.ExceptionKind.FROM_EVALUATOR)
expected = ExceptionThrown(
objectToValue(cause, Type.getType(cause::class.java)) as ObjectValue,
ExceptionThrown.ExceptionKind.FROM_EVALUATOR
)
}
}
}
@@ -13,9 +13,9 @@ import com.intellij.debugger.jdi.GeneratedLocation
import com.intellij.debugger.memory.utils.StackFrameItem
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl
import com.intellij.xdebugger.frame.XNamedValue
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
import com.sun.jdi.*
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_VARIABLE_NAME
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
class AsyncStackTraceContext(
val context: ExecutionContext,
@@ -23,7 +23,7 @@ class AsyncStackTraceContext(
private val debugMetadataKtType: ClassType
) {
fun getAsyncStackTraceForSuspendLambda() : List<StackFrameItem>? {
fun getAsyncStackTraceForSuspendLambda(): List<StackFrameItem>? {
if (method.name() != "invokeSuspend" || method.signature() != "(Ljava/lang/Object;)Ljava/lang/Object;") {
return null
}
@@ -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 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.debugger
@@ -43,15 +32,14 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
class InlineCallableUsagesSearcher(private val myDebugProcess: DebugProcess) {
fun findInlinedCalls(
declaration: KtDeclaration,
alreadyVisited: Set<PsiElement>,
bindingContext: BindingContext = KotlinDebuggerCaches.getOrCreateTypeMapper(declaration).bindingContext,
transformer: (PsiElement, Set<PsiElement>) -> ComputedClassNames
declaration: KtDeclaration,
alreadyVisited: Set<PsiElement>,
bindingContext: BindingContext = KotlinDebuggerCaches.getOrCreateTypeMapper(declaration).bindingContext,
transformer: (PsiElement, Set<PsiElement>) -> ComputedClassNames
): ComputedClassNames {
if (!checkIfInline(declaration, bindingContext)) {
return ComputedClassNames.EMPTY
}
else {
} else {
val searchResult = hashSetOf<PsiElement>()
val declarationName = runReadAction { declaration.name }
@@ -65,12 +53,12 @@ class InlineCallableUsagesSearcher(private val myDebugProcess: DebugProcess) {
val applicationEx = ApplicationManagerEx.getApplicationEx()
if (applicationEx.isDispatchThread) {
isSuccess = ProgressManager.getInstance().runProcessWithProgressSynchronously(
task,
"Compute class names for declaration $declarationName",
true,
myDebugProcess.project)
}
else {
task,
"Compute class names for declaration $declarationName",
true,
myDebugProcess.project
)
} else {
try {
ProgressManager.getInstance().runProcess(task, EmptyProgressIndicator())
} catch (e: InterruptedException) {
@@ -80,8 +68,8 @@ class InlineCallableUsagesSearcher(private val myDebugProcess: DebugProcess) {
if (!isSuccess) {
XDebuggerManagerImpl.NOTIFICATION_GROUP.createNotification(
"Debugger can skip some executions of $declarationName because the computation of class names was interrupted",
MessageType.WARNING
"Debugger can skip some executions of $declarationName because the computation of class names was interrupted",
MessageType.WARNING
).notify(myDebugProcess.project)
}
@@ -119,9 +107,9 @@ class InlineCallableUsagesSearcher(private val myDebugProcess: DebugProcess) {
val virtualFile = runReadAction { inlineDeclaration.containingFile.virtualFile }
return if (virtualFile != null && ProjectRootsUtil.isLibraryFile(myDebugProcess.project, virtualFile)) {
myDebugProcess.searchScope.uniteWith(
KotlinSourceFilterScope.librarySources(GlobalSearchScope.allScope(myDebugProcess.project), myDebugProcess.project))
}
else {
KotlinSourceFilterScope.librarySources(GlobalSearchScope.allScope(myDebugProcess.project), myDebugProcess.project)
)
} else {
myDebugProcess.searchScope
}
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger
@@ -40,7 +29,8 @@ import com.intellij.xdebugger.impl.ui.DebuggerUIUtil
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil.findFilesWithExactPackage
import org.jetbrains.kotlin.psi.KtFile
class KotlinAlternativeSourceNotificationProvider(private val myProject: Project) : EditorNotifications.Provider<EditorNotificationPanel>() {
class KotlinAlternativeSourceNotificationProvider(private val myProject: Project) :
EditorNotifications.Provider<EditorNotificationPanel>() {
override fun getKey(): Key<EditorNotificationPanel> {
return KEY
}
@@ -69,9 +59,11 @@ class KotlinAlternativeSourceNotificationProvider(private val myProject: Project
val packageFqName = ktFile.packageFqName
val fileName = ktFile.name
val alternativeKtFiles = findFilesWithExactPackage(packageFqName, GlobalSearchScope.allScope(myProject), myProject).filterTo(HashSet()) {
it.name == fileName
}
val alternativeKtFiles = findFilesWithExactPackage(
packageFqName,
GlobalSearchScope.allScope(myProject),
myProject
).filterTo(HashSet()) { it.name == fileName }
FILE_PROCESSED_KEY.set(file, true)
@@ -81,8 +73,7 @@ class KotlinAlternativeSourceNotificationProvider(private val myProject: Project
val currentFirstAlternatives: Collection<KtFile> = listOf(ktFile) + alternativeKtFiles.filter { it != ktFile }
val frame = session.currentStackFrame
val locationDeclName: String? = when (frame) {
val locationDeclName: String? = when (val frame = session.currentStackFrame) {
is JavaStackFrame -> {
val location = frame.descriptor.location
location?.declaringType()?.name()
@@ -94,10 +85,10 @@ class KotlinAlternativeSourceNotificationProvider(private val myProject: Project
}
private class AlternativeSourceNotificationPanel(
alternatives: Collection<KtFile>,
project: Project,
file: VirtualFile,
locationDeclName: String?
alternatives: Collection<KtFile>,
project: Project,
file: VirtualFile,
locationDeclName: String?
) : EditorNotificationPanel() {
private class ComboBoxFileElement(val ktFile: KtFile) {
private val label: String by lazy(LazyThreadSafetyMode.NONE) {
@@ -119,34 +110,34 @@ class KotlinAlternativeSourceNotificationProvider(private val myProject: Project
val items = alternatives.map { ComboBoxFileElement(it) }
myLinksPanel.add(
ComboBox<ComboBoxFileElement>(items.toTypedArray()).apply {
addActionListener {
val context = DebuggerManagerEx.getInstanceEx(project).context
val session = context.debuggerSession
val ktFile = (selectedItem as ComboBoxFileElement).ktFile
val vFile = ktFile.containingFile.virtualFile
ComboBox<ComboBoxFileElement>(items.toTypedArray()).apply {
addActionListener {
val context = DebuggerManagerEx.getInstanceEx(project).context
val session = context.debuggerSession
val ktFile = (selectedItem as ComboBoxFileElement).ktFile
val vFile = ktFile.containingFile.virtualFile
when {
session != null && vFile != null ->
session.process.managerThread.schedule(object : DebuggerCommandImpl() {
override fun action() {
if (!StringUtil.isEmpty(locationDeclName)) {
DebuggerUtilsEx.setAlternativeSourceUrl(locationDeclName, vFile.url, project)
}
DebuggerUIUtil.invokeLater {
FileEditorManager.getInstance(project).closeFile(file)
session.refresh(true)
}
when {
session != null && vFile != null ->
session.process.managerThread.schedule(object : DebuggerCommandImpl() {
override fun action() {
if (!StringUtil.isEmpty(locationDeclName)) {
DebuggerUtilsEx.setAlternativeSourceUrl(locationDeclName, vFile.url, project)
}
})
else -> {
FileEditorManager.getInstance(project).closeFile(file)
ktFile.navigate(true)
}
DebuggerUIUtil.invokeLater {
FileEditorManager.getInstance(project).closeFile(file)
session.refresh(true)
}
}
})
else -> {
FileEditorManager.getInstance(project).closeFile(file)
ktFile.navigate(true)
}
}
})
}
})
createActionLabel("Disable") {
DebuggerSettings.getInstance().SHOW_ALTERNATIVE_SOURCE = false
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2000-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.
*/
@@ -29,22 +29,26 @@ class KotlinDebuggerSettings : XDebuggerSettings<KotlinDebuggerSettings>("kotlin
}
}
override fun createConfigurables(category: DebuggerSettingsCategory): Collection<Configurable?> {
return when (category) {
DebuggerSettingsCategory.STEPPING ->
listOf(SimpleConfigurable.create(
"reference.idesettings.debugger.kotlin.stepping",
"Kotlin",
KotlinSteppingConfigurableUi::class.java,
this))
DebuggerSettingsCategory.DATA_VIEWS ->
listOf(SimpleConfigurable.create(
"reference.idesettings.debugger.kotlin.data.view",
"Kotlin",
KotlinDelegatedPropertyRendererConfigurableUi::class.java,
this))
else -> listOf()
}
override fun createConfigurables(category: DebuggerSettingsCategory): Collection<Configurable?> = when (category) {
DebuggerSettingsCategory.STEPPING ->
listOf(
SimpleConfigurable.create(
"reference.idesettings.debugger.kotlin.stepping",
"Kotlin",
KotlinSteppingConfigurableUi::class.java,
this
)
)
DebuggerSettingsCategory.DATA_VIEWS ->
listOf(
SimpleConfigurable.create(
"reference.idesettings.debugger.kotlin.data.view",
"Kotlin",
KotlinDelegatedPropertyRendererConfigurableUi::class.java,
this
)
)
else -> listOf()
}
override fun getState() = this
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger
@@ -50,9 +39,8 @@ class KotlinFrameExtraVariablesProvider : FrameExtraVariablesProvider {
}
override fun collectVariables(
sourcePosition: SourcePosition, evalContext: EvaluationContext, alreadyCollected: MutableSet<String>): Set<TextWithImports> {
return runReadAction { findAdditionalExpressions(sourcePosition) }
}
sourcePosition: SourcePosition, evalContext: EvaluationContext, alreadyCollected: MutableSet<String>
): Set<TextWithImports> = runReadAction { findAdditionalExpressions(sourcePosition) }
}
private fun findAdditionalExpressions(position: SourcePosition): Set<TextWithImports> {
@@ -99,7 +87,8 @@ private fun findAdditionalExpressions(position: SourcePosition): Set<TextWithImp
}
private fun getContainingElement(element: PsiElement): KtElement? {
val contElement = PsiTreeUtil.getParentOfType(element, KtDeclaration::class.java) ?: PsiTreeUtil.getParentOfType(element, KtElement::class.java)
val contElement =
PsiTreeUtil.getParentOfType(element, KtDeclaration::class.java) ?: PsiTreeUtil.getParentOfType(element, KtElement::class.java)
if (contElement is KtProperty && contElement.isLocal) {
val parent = contElement.parent
return getContainingElement(parent)
@@ -129,8 +118,8 @@ private fun shouldSkipLine(file: PsiFile, doc: Document, line: Int): Boolean {
}
private class VariablesCollector(
private val myLineRange: TextRange,
private val myExpressions: MutableSet<TextWithImports>
private val myLineRange: TextRange,
private val myExpressions: MutableSet<TextWithImports>
) : KtTreeVisitorVoid() {
override fun visitKtElement(element: KtElement) {
@@ -160,8 +149,7 @@ private class VariablesCollector(
val descriptor = context[BindingContext.REFERENCE_TARGET, expression]
if (descriptor is PropertyDescriptor) {
val getter = descriptor.getter
return (getter == null || context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getter] == null) &&
descriptor.compileTimeInitializer == null
return (getter == null || context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getter] == null) && descriptor.compileTimeInitializer == null
}
return false
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger
@@ -62,41 +51,39 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import com.intellij.debugger.engine.DebuggerUtils as JDebuggerUtils
class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiRequestPositionManager, PositionManagerEx() {
private val allKotlinFilesScope =
object : DelegatingGlobalSearchScope(
KotlinSourceFilterScope.projectAndLibrariesSources(GlobalSearchScope.allScope(myDebugProcess.project), myDebugProcess.project)
) {
private val projectIndex = ProjectRootManager.getInstance(myDebugProcess.project).fileIndex
private val scopeComparator =
Comparator.comparing(projectIndex::isInSourceContent)
.thenComparing(projectIndex::isInLibrarySource)
.thenComparing { file1, file2 -> super.compare(file1, file2) }
private val allKotlinFilesScope = object : DelegatingGlobalSearchScope(
KotlinSourceFilterScope.projectAndLibrariesSources(GlobalSearchScope.allScope(myDebugProcess.project), myDebugProcess.project)
) {
private val projectIndex = ProjectRootManager.getInstance(myDebugProcess.project).fileIndex
private val scopeComparator = Comparator.comparing(projectIndex::isInSourceContent).thenComparing(projectIndex::isInLibrarySource)
.thenComparing { file1, file2 -> super.compare(file1, file2) }
override fun compare(file1: VirtualFile, file2: VirtualFile): Int {
return scopeComparator.compare(file1, file2)
}
}
override fun compare(file1: VirtualFile, file2: VirtualFile): Int = scopeComparator.compare(file1, file2)
}
private val sourceSearchScopes: List<GlobalSearchScope> = listOf(
myDebugProcess.searchScope,
allKotlinFilesScope
myDebugProcess.searchScope,
allKotlinFilesScope
)
override fun getAcceptedFileTypes(): Set<FileType> = KotlinFileTypeFactory.KOTLIN_FILE_TYPES_SET
override fun evaluateCondition(context: EvaluationContext, frame: StackFrameProxyImpl, location: Location, expression: String): ThreeState? {
override fun evaluateCondition(
context: EvaluationContext,
frame: StackFrameProxyImpl,
location: Location,
expression: String
): ThreeState? {
return ThreeState.UNSURE
}
override fun createStackFrame(frame: StackFrameProxyImpl, debugProcess: DebugProcessImpl, location: Location): XStackFrame? {
if (location.isInKotlinSources()) {
return KotlinStackFrame(frame)
}
return null
}
override fun createStackFrame(frame: StackFrameProxyImpl, debugProcess: DebugProcessImpl, location: Location): XStackFrame? =
if (location.isInKotlinSources())
KotlinStackFrame(frame)
else
null
override fun getSourcePosition(location: Location?): SourcePosition? {
if (location == null) throw NoDataException.INSTANCE
@@ -120,13 +107,13 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
val project = myDebugProcess.project
val defaultPsiFile = DebuggerUtils.findSourceFileForClass(
project, sourceSearchScopes, javaClassName, javaSourceFileName, location)
project, sourceSearchScopes, javaClassName, javaSourceFileName, location
)
if (defaultPsiFile != null) {
return SourcePosition.createFromLine(defaultPsiFile, 0)
}
}
catch (e: AbsentInformationException) {
} catch (e: AbsentInformationException) {
// ignored
}
}
@@ -225,8 +212,8 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
val elementAt = file.findElementAt(start) ?: return null
val typeMapper = KotlinDebuggerCaches.getOrCreateTypeMapper(elementAt)
val currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName))
.internalName.replace('/', '.')
val currentLocationClassName =
JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName)).internalName.replace('/', '.')
for (literal in literalsOrFunctions) {
if (InlineUtil.isInlinedArgument(literal, typeMapper.bindingContext, true)) {
@@ -236,9 +223,10 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
continue
}
val internalClassNames = DebuggerClassNameProvider(myDebugProcess, alwaysReturnLambdaParentClass = false)
.getOuterClassNamesForElement(literal.firstChild, emptySet())
.classNames
val internalClassNames = DebuggerClassNameProvider(
myDebugProcess,
alwaysReturnLambdaParentClass = false
).getOuterClassNamesForElement(literal.firstChild, emptySet()).classNames
if (internalClassNames.any { it == currentLocationClassName }) {
return literal
@@ -255,12 +243,10 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
if (location.declaringType().containsKotlinStrata()) {
//replace is required for windows
location.sourcePath().replace('\\', '/')
}
else {
} else {
defaultInternalName(location)
}
}
catch (e: AbsentInformationException) {
} catch (e: AbsentInformationException) {
defaultInternalName(location)
}
@@ -307,7 +293,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
try {
if (myDebugProcess.isDexDebug()) {
val inlineLocations = runReadAction { getLocationsOfInlinedLine(type, position, myDebugProcess.searchScope) }
if (!inlineLocations.isEmpty()) {
if (inlineLocations.isNotEmpty()) {
return inlineLocations
}
}
@@ -320,8 +306,7 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
}
return locations.filter { it.sourceName(KOTLIN_STRATA_NAME) == position.file.name }
}
catch (e: AbsentInformationException) {
} catch (e: AbsentInformationException) {
throw NoDataException.INSTANCE
}
}
@@ -340,8 +325,8 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq
val classNames = DebuggerClassNameProvider(myDebugProcess).getOuterClassNamesForPosition(position)
classNames.flatMap { name ->
listOfNotNull(
myDebugProcess.requestsManager.createClassPrepareRequest(requestor, name),
myDebugProcess.requestsManager.createClassPrepareRequest(requestor, "$name$*")
myDebugProcess.requestsManager.createClassPrepareRequest(requestor, name),
myDebugProcess.requestsManager.createClassPrepareRequest(requestor, "$name$*")
)
}
})
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger
@@ -21,7 +10,7 @@ import com.intellij.debugger.engine.SourcePositionHighlighter
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.psi.KtFunctionLiteral
class KotlinSourcePositionHighlighter: SourcePositionHighlighter() {
class KotlinSourcePositionHighlighter : SourcePositionHighlighter() {
override fun getHighlightRange(sourcePosition: SourcePosition?): TextRange? {
val lambda = sourcePosition?.elementAt?.parent
if (lambda is KtFunctionLiteral) {
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger
@@ -25,14 +14,18 @@ import com.intellij.debugger.ui.tree.FieldDescriptor
import com.intellij.debugger.ui.tree.LocalVariableDescriptor
import com.intellij.debugger.ui.tree.NodeDescriptor
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import com.sun.jdi.AbsentInformationException
import com.sun.jdi.ClassNotPreparedException
import com.sun.jdi.ReferenceType
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -41,7 +34,12 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.resolve.source.getPsi
class KotlinSourcePositionProvider : SourcePositionProvider() {
override fun computeSourcePosition(descriptor: NodeDescriptor, project: Project, context: DebuggerContextImpl, nearest: Boolean): SourcePosition? {
override fun computeSourcePosition(
descriptor: NodeDescriptor,
project: Project,
context: DebuggerContextImpl,
nearest: Boolean
): SourcePosition? {
if (context.frameProxy == null) return null
if (descriptor is FieldDescriptor) {
@@ -84,7 +82,12 @@ class KotlinSourcePositionProvider : SourcePositionProvider() {
return null
}
private fun computeSourcePosition(descriptor: FieldDescriptor, project: Project, context: DebuggerContextImpl, nearest: Boolean): SourcePosition? {
private fun computeSourcePosition(
descriptor: FieldDescriptor,
project: Project,
context: DebuggerContextImpl,
nearest: Boolean
): SourcePosition? {
val fieldName = descriptor.field.name()
if (fieldName == AsmUtil.CAPTURED_THIS_FIELD
@@ -128,14 +131,12 @@ class KotlinSourcePositionProvider : SourcePositionProvider() {
if (debugProcess != null) {
try {
val locations = type.safeAllLineLocations()
if (!locations.isEmpty()) {
val lastLocation = locations.get(locations.size - 1)
if (locations.isNotEmpty()) {
val lastLocation = locations[locations.size - 1]
return debugProcess.positionManager.getSourcePosition(lastLocation)
}
}
catch (ignored: AbsentInformationException) {
}
catch (ignored: ClassNotPreparedException) {
} catch (ignored: AbsentInformationException) {
} catch (ignored: ClassNotPreparedException) {
}
}
return null
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.breakpoints
@@ -55,9 +44,9 @@ import org.jetbrains.kotlin.resolve.BindingContext
import javax.swing.Icon
class KotlinFieldBreakpoint(
project: Project,
breakpoint: XBreakpoint<KotlinPropertyBreakpointProperties>
): BreakpointWithHighlighter<KotlinPropertyBreakpointProperties>(project, breakpoint) {
project: Project,
breakpoint: XBreakpoint<KotlinPropertyBreakpointProperties>
) : BreakpointWithHighlighter<KotlinPropertyBreakpointProperties>(project, breakpoint) {
companion object {
private val LOG = Logger.getInstance("#org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpoint")
private val CATEGORY: Key<FieldBreakpoint> = BreakpointCategory.lookup<FieldBreakpoint>("field_breakpoints")
@@ -130,18 +119,18 @@ class KotlinFieldBreakpoint(
val sourcePosition = sourcePosition
if (sourcePosition != null) {
debugProcess.positionManager
.locationsOfLine(refType, sourcePosition)
.filter { it.method().isConstructor || it.method().isStaticInitializer }
.forEach {
val request = debugProcess.requestsManager.createBreakpointRequest(this, it)
debugProcess.requestsManager.enableRequest(request)
if (LOG.isDebugEnabled) {
LOG.debug("Breakpoint request added")
}
.locationsOfLine(refType, sourcePosition)
.filter { it.method().isConstructor || it.method().isStaticInitializer }
.forEach {
val request = debugProcess.requestsManager.createBreakpointRequest(this, it)
debugProcess.requestsManager.enableRequest(request)
if (LOG.isDebugEnabled) {
LOG.debug("Breakpoint request added")
}
}
}
}
when (breakpointType) {
BreakpointType.FIELD -> {
val field = refType.fieldByName(getFieldName())
@@ -181,8 +170,7 @@ class KotlinFieldBreakpoint(
}
}
}
}
catch (ex: Exception) {
} catch (ex: Exception) {
LOG.debug(ex)
}
}
@@ -198,12 +186,10 @@ class KotlinFieldBreakpoint(
if (descriptor is PropertyDescriptor) {
if (bindingContext.get(BindingContext.BACKING_FIELD_REQUIRED, descriptor)!!) {
BreakpointType.FIELD
}
else {
} else {
BreakpointType.METHOD
}
}
else {
} else {
null
}
}
@@ -218,16 +204,14 @@ class KotlinFieldBreakpoint(
if (LOG.isDebugEnabled) {
LOG.debug("Breakpoint request added")
}
}
else {
} else {
var entryRequest: MethodEntryRequest? = findRequest(debugProcess, MethodEntryRequest::class.java, this)
if (entryRequest == null) {
entryRequest = manager.createMethodEntryRequest(this)!!
if (LOG.isDebugEnabled) {
LOG.debug("Method entry request added (method = ${accessor.name()}; refType = ${refType.name()})")
}
}
else {
} else {
entryRequest.disable()
}
entryRequest.addClassFilter(refType)
@@ -235,7 +219,11 @@ class KotlinFieldBreakpoint(
}
}
inline private fun <reified T : EventRequest> findRequest(debugProcess: DebugProcessImpl, requestClass: Class<T>, requestor: Requestor): T? {
inline private fun <reified T : EventRequest> findRequest(
debugProcess: DebugProcessImpl,
requestClass: Class<T>,
requestor: Requestor
): T? {
val requests = debugProcess.requestsManager.findRequests(requestor)
for (eventRequest in requests) {
if (eventRequest::class.java == requestClass) {
@@ -268,60 +256,63 @@ class KotlinFieldBreakpoint(
val locationQName = location.declaringType().name() + "." + location.method().name()
val locationFileName = try {
location.sourceName()
}
catch (e: AbsentInformationException) {
} catch (e: AbsentInformationException) {
fileName
}
catch (e: InternalError) {
} catch (e: InternalError) {
fileName
}
val locationLine = location.lineNumber()
when (event) {
is ModificationWatchpointEvent-> {
is ModificationWatchpointEvent -> {
val field = event.field()
return DebuggerBundle.message(
"status.static.field.watchpoint.reached.access",
field.declaringType().name(),
field.name(),
locationQName,
locationFileName,
locationLine)
"status.static.field.watchpoint.reached.access",
field.declaringType().name(),
field.name(),
locationQName,
locationFileName,
locationLine
)
}
is AccessWatchpointEvent -> {
val field = event.field()
return DebuggerBundle.message(
"status.static.field.watchpoint.reached.access",
field.declaringType().name(),
field.name(),
locationQName,
locationFileName,
locationLine)
"status.static.field.watchpoint.reached.access",
field.declaringType().name(),
field.name(),
locationQName,
locationFileName,
locationLine
)
}
is MethodEntryEvent -> {
val method = event.method()
return DebuggerBundle.message(
"status.method.entry.breakpoint.reached",
method.declaringType().name() + "." + method.name() + "()",
locationQName,
locationFileName,
locationLine)
"status.method.entry.breakpoint.reached",
method.declaringType().name() + "." + method.name() + "()",
locationQName,
locationFileName,
locationLine
)
}
is MethodExitEvent -> {
val method = event.method()
return DebuggerBundle.message(
"status.method.exit.breakpoint.reached",
method.declaringType().name() + "." + method.name() + "()",
locationQName,
locationFileName,
locationLine)
"status.method.exit.breakpoint.reached",
method.declaringType().name() + "." + method.name() + "()",
locationQName,
locationFileName,
locationLine
)
}
}
return DebuggerBundle.message(
"status.line.breakpoint.reached",
locationQName,
locationFileName,
locationLine)
"status.line.breakpoint.reached",
locationQName,
locationFileName,
locationLine
)
}
fun setFieldName(fieldName: String) {
@@ -376,7 +367,7 @@ class KotlinFieldBreakpoint(
return DebuggerBundle.message("status.breakpoint.invalid")
}
val className = className
return if (className != null && !className.isEmpty()) className + "." + getFieldName() else getFieldName()
return if (className != null && className.isNotEmpty()) className + "." + getFieldName() else getFieldName()
}
private fun getFieldName(): String {
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.breakpoints
@@ -30,15 +19,17 @@ import javax.swing.JComponent
import javax.swing.JPanel
import kotlin.properties.Delegates
class KotlinFieldBreakpointPropertiesPanel: XBreakpointCustomPropertiesPanel<XLineBreakpoint<KotlinPropertyBreakpointProperties>>() {
class KotlinFieldBreakpointPropertiesPanel : XBreakpointCustomPropertiesPanel<XLineBreakpoint<KotlinPropertyBreakpointProperties>>() {
private var myWatchInitializationCheckBox: JCheckBox by Delegates.notNull()
private var myWatchAccessCheckBox: JCheckBox by Delegates.notNull()
private var myWatchModificationCheckBox: JCheckBox by Delegates.notNull()
override fun getComponent(): JComponent {
myWatchInitializationCheckBox = JCheckBox(KotlinBundle.message("debugger.field.watchpoints.properties.panel.field.initialization.label"))
myWatchInitializationCheckBox =
JCheckBox(KotlinBundle.message("debugger.field.watchpoints.properties.panel.field.initialization.label"))
myWatchAccessCheckBox = JCheckBox(KotlinBundle.message("debugger.field.watchpoints.properties.panel.field.access.label"))
myWatchModificationCheckBox = JCheckBox(KotlinBundle.message("debugger.field.watchpoints.properties.panel.field.modification.label"))
myWatchModificationCheckBox =
JCheckBox(KotlinBundle.message("debugger.field.watchpoints.properties.panel.field.modification.label"))
DialogUtil.registerMnemonic(myWatchInitializationCheckBox)
DialogUtil.registerMnemonic(myWatchAccessCheckBox)
@@ -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 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.debugger.breakpoints
@@ -34,8 +23,8 @@ import com.intellij.xdebugger.breakpoints.XLineBreakpoint
import com.intellij.xdebugger.breakpoints.XLineBreakpointType
import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.debugger.breakpoints.dialog.AddFieldBreakpointDialog
import org.jetbrains.kotlin.idea.util.application.runWriteAction
@@ -48,9 +37,11 @@ import javax.swing.JComponent
class KotlinFieldBreakpointType :
JavaBreakpointType<KotlinPropertyBreakpointProperties>,
XLineBreakpointType<KotlinPropertyBreakpointProperties>("kotlin-field", KotlinBundle.message("debugger.field.watchpoints.tab.title")),
KotlinBreakpointType
{
override fun createJavaBreakpoint(project: Project, breakpoint: XBreakpoint<KotlinPropertyBreakpointProperties>): Breakpoint<KotlinPropertyBreakpointProperties> {
KotlinBreakpointType {
override fun createJavaBreakpoint(
project: Project,
breakpoint: XBreakpoint<KotlinPropertyBreakpointProperties>
): Breakpoint<KotlinPropertyBreakpointProperties> {
return KotlinFieldBreakpoint(project, breakpoint)
}
@@ -94,9 +85,10 @@ class KotlinFieldBreakpointType :
}
result = when (psiClass) {
is KtLightClassForFacade -> {
psiClass.files.asSequence().mapNotNull { createBreakpointIfPropertyExists(it, it, className, fieldName) }.firstOrNull()
}
is KtLightClassForFacade -> psiClass.files.asSequence().mapNotNull {
createBreakpointIfPropertyExists(it, it, className, fieldName)
}.firstOrNull()
is KtLightClassForSourceDeclaration -> {
val jetClass = psiClass.kotlinOrigin
createBreakpointIfPropertyExists(jetClass, jetClass.containingKtFile, className, fieldName)
@@ -117,10 +109,10 @@ class KotlinFieldBreakpointType :
}
private fun createBreakpointIfPropertyExists(
declaration: KtDeclarationContainer,
file: KtFile,
className: String,
fieldName: String
declaration: KtDeclarationContainer,
file: KtFile,
className: String,
fieldName: String
): XLineBreakpoint<KotlinPropertyBreakpointProperties>? {
val project = file.project
val property = declaration.declarations.firstOrNull { it is KtProperty && it.name == fieldName } ?: return null
@@ -129,10 +121,10 @@ class KotlinFieldBreakpointType :
val line = document.getLineNumber(property.textOffset)
return runWriteAction {
XDebuggerManager.getInstance(project).breakpointManager.addLineBreakpoint(
this,
file.virtualFile.url,
line,
KotlinPropertyBreakpointProperties(fieldName, className)
this,
file.virtualFile.url,
line,
KotlinPropertyBreakpointProperties(fieldName, className)
)
}
}
@@ -156,7 +148,7 @@ class KotlinFieldBreakpointType :
override fun getShortText(breakpoint: XLineBreakpoint<KotlinPropertyBreakpointProperties>): String? {
val properties = breakpoint.properties
val className = properties.myClassName
return if (!className.isEmpty()) className + "." + properties.myFieldName else properties.myFieldName
return if (className.isNotEmpty()) className + "." + properties.myFieldName else properties.myFieldName
}
override fun createProperties(): KotlinPropertyBreakpointProperties? {
@@ -169,12 +161,7 @@ class KotlinFieldBreakpointType :
override fun getDisplayText(breakpoint: XLineBreakpoint<KotlinPropertyBreakpointProperties>): String? {
val kotlinBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint) as? BreakpointWithHighlighter
return if (kotlinBreakpoint != null) {
kotlinBreakpoint.description
}
else {
super.getDisplayText(breakpoint)
}
return kotlinBreakpoint?.description ?: super.getDisplayText(breakpoint)
}
override fun getEditorsProvider() = null
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.breakpoints
@@ -20,9 +9,9 @@ import com.intellij.util.xmlb.annotations.Attribute
import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties
class KotlinPropertyBreakpointProperties(
@Attribute var myFieldName: String = "",
@Attribute var myClassName: String = ""
): JavaBreakpointProperties<KotlinPropertyBreakpointProperties>() {
@Attribute var myFieldName: String = "",
@Attribute var myClassName: String = ""
) : JavaBreakpointProperties<KotlinPropertyBreakpointProperties>() {
var WATCH_MODIFICATION: Boolean = true
var WATCH_ACCESS: Boolean = false
var WATCH_INITIALIZATION: Boolean = false
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.breakpoints
@@ -31,13 +20,15 @@ import com.intellij.xdebugger.impl.XSourcePositionImpl
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
import org.jetbrains.kotlin.idea.core.util.attachmentByPsiFile
import org.jetbrains.kotlin.idea.core.util.getLineNumber
import org.jetbrains.kotlin.idea.debugger.findElementAtLine
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -179,12 +170,11 @@ fun getLambdasAtLineIfAny(file: KtFile, line: Int): List<KtFunction> {
val start = lineElement.startOffset
val end = lineElement.endOffset
val allLiterals = CodeInsightUtils.
findElementsOfClassInRange(file, start, end, KtFunction::class.java)
.filterIsInstance<KtFunction>()
// filter function literals and functional expressions
.filter { it is KtFunctionLiteral || it.name == null }
.toSet()
val allLiterals = CodeInsightUtils.findElementsOfClassInRange(file, start, end, KtFunction::class.java)
.filterIsInstance<KtFunction>()
// filter function literals and functional expressions
.filter { it is KtFunctionLiteral || it.name == null }
.toSet()
return allLiterals.filter {
val statement = it.bodyBlockExpression?.statements?.firstOrNull() ?: it
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -100,14 +100,11 @@ private fun Location.visibleVariables(debugProcess: DebugProcessImpl): List<Loca
}
// For Kotlin up to 1.3.10
private fun lambdaOrdinalByLocalVariable(name: String): Int {
try {
val nameWithoutPrefix = name.removePrefix(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT)
return Integer.parseInt(nameWithoutPrefix.substringBefore("$", nameWithoutPrefix))
}
catch(e: NumberFormatException) {
return 0
}
private fun lambdaOrdinalByLocalVariable(name: String): Int = try {
val nameWithoutPrefix = name.removePrefix(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT)
Integer.parseInt(nameWithoutPrefix.substringBefore("$", nameWithoutPrefix))
} catch (e: NumberFormatException) {
0
}
// For Kotlin up to 1.3.10
@@ -130,7 +127,7 @@ private class MockStackFrame(private val location: Location, private val vm: Vir
for (variable in allVariables) {
if (variable.isVisible(this)) {
map.put(variable.name(), variable)
map[variable.name()] = variable
}
}
visibleVariables = map
@@ -140,7 +137,7 @@ private class MockStackFrame(private val location: Location, private val vm: Vir
override fun visibleVariables(): List<LocalVariable> {
createVisibleVariables()
val mapAsList = ArrayList(visibleVariables!!.values)
Collections.sort(mapAsList)
mapAsList.sort()
return mapAsList
}
@@ -235,14 +232,11 @@ fun findCallByEndToken(element: PsiElement): KtCallExpression? {
return when (element.node.elementType) {
KtTokens.RPAR -> (element.parent as? KtValueArgumentList)?.parent as? KtCallExpression
KtTokens.RBRACE -> {
val braceParent = CodeInsightUtils.getTopParentWithEndOffset(element, KtCallExpression::class.java)
when (braceParent) {
is KtCallExpression -> braceParent
is KtLambdaArgument -> braceParent.parent as? KtCallExpression
is KtValueArgument -> (braceParent.parent as? KtValueArgumentList)?.parent as? KtCallExpression
else -> null
}
KtTokens.RBRACE -> when (val braceParent = CodeInsightUtils.getTopParentWithEndOffset(element, KtCallExpression::class.java)) {
is KtCallExpression -> braceParent
is KtLambdaArgument -> braceParent.parent as? KtCallExpression
is KtValueArgument -> (braceParent.parent as? KtValueArgumentList)?.parent as? KtCallExpression
else -> null
}
else -> null
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.filter
@@ -21,11 +10,11 @@ import com.intellij.ui.classFilter.DebuggerClassFilterProvider
import org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings
private val FILTERS = listOf(
ClassFilter("kotlin.jvm*"),
ClassFilter("kotlin.reflect*"),
ClassFilter("kotlin.NoWhenBranchMatchedException"),
ClassFilter("kotlin.TypeCastException"),
ClassFilter("kotlin.KotlinNullPointerException")
ClassFilter("kotlin.jvm*"),
ClassFilter("kotlin.reflect*"),
ClassFilter("kotlin.NoWhenBranchMatchedException"),
ClassFilter("kotlin.TypeCastException"),
ClassFilter("kotlin.KotlinNullPointerException")
)
class KotlinDebuggerInternalClassesFilterProvider : DebuggerClassFilterProvider {
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.filter
@@ -25,7 +14,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import kotlin.jvm.internal.FunctionReference
import kotlin.jvm.internal.PropertyReference
abstract class KotlinSyntheticTypeComponentProviderBase: SyntheticTypeComponentProvider {
abstract class KotlinSyntheticTypeComponentProviderBase : SyntheticTypeComponentProvider {
override fun isSynthetic(typeComponent: TypeComponent?): Boolean {
if (typeComponent !is Method) return false
@@ -48,11 +37,9 @@ abstract class KotlinSyntheticTypeComponentProviderBase: SyntheticTypeComponentP
}
return !typeComponent.declaringType().safeAllLineLocations().any { it.lineNumber() != 1 }
}
catch(e: AbsentInformationException) {
} catch (e: AbsentInformationException) {
return false
}
catch(e: UnsupportedOperationException) {
} catch (e: UnsupportedOperationException) {
return false
}
}
@@ -126,6 +113,6 @@ abstract class KotlinSyntheticTypeComponentProviderBase: SyntheticTypeComponentP
val interfaces = declaringType.allInterfaces()
val vm = declaringType.virtualMachine()
val traitImpls = interfaces.flatMap { vm.classesByName(it.name() + JvmAbi.DEFAULT_IMPLS_SUFFIX) }
return traitImpls.any { !it.methodsByName(method.name()).isEmpty() }
return traitImpls.any { it.methodsByName(method.name()).isNotEmpty() }
}
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.render
@@ -27,10 +16,10 @@ import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
class DelegatedPropertyFieldDescriptor(
project: Project,
objectRef: ObjectReference,
val delegate: Field,
private val renderDelegatedProperty: Boolean
project: Project,
objectRef: ObjectReference,
val delegate: Field,
private val renderDelegatedProperty: Boolean
) : FieldDescriptorImpl(project, objectRef, delegate) {
override fun calcValue(evaluationContext: EvaluationContextImpl?): Value? {
@@ -43,17 +32,16 @@ class DelegatedPropertyFieldDescriptor(
return super.calcValue(evaluationContext)
}
try {
return evaluationContext.debugProcess.invokeInstanceMethod(
evaluationContext,
`object`,
method,
listOf<Nothing>(),
evaluationContext.suspendContext.suspendPolicy
return try {
evaluationContext.debugProcess.invokeInstanceMethod(
evaluationContext,
`object`,
method,
listOf<Nothing>(),
evaluationContext.suspendContext.suspendPolicy
)
}
catch(e: EvaluateException) {
return e.exceptionFromTargetVM
} catch (e: EvaluateException) {
e.exceptionFromTargetVM
}
}
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger.render
@@ -30,14 +19,11 @@ import com.intellij.debugger.ui.tree.render.DescriptorLabelListener
import com.intellij.openapi.diagnostic.Logger
import com.intellij.xdebugger.settings.XDebuggerSettingsManager
import com.sun.jdi.*
import com.sun.jdi.Type
import org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings
import org.jetbrains.kotlin.idea.debugger.ToggleKotlinVariablesState
import org.jetbrains.kotlin.idea.debugger.canRunEvaluation
import org.jetbrains.kotlin.load.java.JvmAbi
import java.util.*
import com.sun.jdi.Type as JdiType
import org.jetbrains.org.objectweb.asm.Type as AsmType
private val LOG = Logger.getInstance(KotlinClassWithDelegatedPropertyRenderer::class.java)
private fun notPreparedClassMessage(referenceType: ReferenceType) =
@@ -45,7 +31,7 @@ private fun notPreparedClassMessage(referenceType: ReferenceType) =
class KotlinClassWithDelegatedPropertyRenderer : ClassRenderer() {
private val rendererSettings = NodeRendererSettings.getInstance()
override fun isApplicable(jdiType: Type?): Boolean {
if (!super.isApplicable(jdiType)) return false
@@ -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 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.debugger.evaluate
@@ -34,7 +23,8 @@ import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiTypesUtil
import com.intellij.util.IncorrectOperationException
import com.intellij.util.concurrency.Semaphore
import com.sun.jdi.*
import com.sun.jdi.AbsentInformationException
import com.sun.jdi.InvalidStackFrameException
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.core.util.getKotlinJvmRuntimeMarkerClass
@@ -94,7 +84,9 @@ class KotlinCodeFragmentFactory : CodeFragmentFactory() {
val debuggerContext = DebuggerManagerEx.getInstanceEx(project).context
val debuggerSession = debuggerContext.debuggerSession
if ((debuggerSession == null || debuggerContext.suspendContext == null) && !ApplicationManager.getApplication().isUnitTestMode) {
if ((debuggerSession == null || debuggerContext.suspendContext == null) &&
!ApplicationManager.getApplication().isUnitTestMode
) {
LOG.warn("Couldn't create fake context element for java file, debugger isn't paused on breakpoint")
return@putCopyableUserData emptyFile
}
@@ -18,13 +18,15 @@ import org.jetbrains.kotlin.idea.debugger.evaluate.DebuggerFieldPropertyDescript
import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationError
import org.jetbrains.kotlin.idea.debugger.evaluate.EvaluationStatus
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.CodeFragmentParameter.*
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory.Companion.FAKE_JAVA_CONTEXT_FUNCTION_NAME
import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.CodeFragmentParameter.*
import org.jetbrains.kotlin.idea.debugger.safeLocation
import org.jetbrains.kotlin.idea.debugger.safeMethod
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.psi.psiUtil.isDotSelector
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_1_3_FQ_NAME
@@ -310,6 +312,7 @@ class CodeFragmentParameterAnalyzer(
parameters.getOrPut(target) {
val type = target.type
@Suppress("DEPRECATION")
val kind = if (target is LocalVariableDescriptor && target.isDelegated) Kind.DELEGATED else Kind.ORDINARY
Smart(Dumb(kind, target.name.asString()), type, target, isLValue)
@@ -11,12 +11,11 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.xdebugger.impl.XDebugSessionImpl
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup
import org.jetbrains.kotlin.builtins.PrimitiveType
import com.sun.jdi.*
import org.jetbrains.kotlin.backend.common.SimpleMemberScope
import com.sun.jdi.Type as JdiType
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorImpl
@@ -26,13 +25,14 @@ import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.idea.debugger.getClassDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.externalDescriptors
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.externalDescriptors
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
import com.sun.jdi.Type as JdiType
import org.jetbrains.org.objectweb.asm.Type as AsmType
class DebugLabelPropertyDescriptorProvider(val codeFragment: KtCodeFragment, val debugProcess: DebugProcessImpl) {
@@ -144,10 +144,8 @@ class DebugLabelPropertyDescriptorProvider(val codeFragment: KtCodeFragment, val
}
}
private object DebugLabelModuleDescriptor
: DeclarationDescriptorImpl(Annotations.EMPTY, Name.identifier("DebugLabelExtensions")),
ModuleDescriptor
{
private object DebugLabelModuleDescriptor : DeclarationDescriptorImpl(Annotations.EMPTY, Name.identifier("DebugLabelExtensions")),
ModuleDescriptor {
override val builtIns: KotlinBuiltIns
get() = DefaultBuiltIns.Instance
@@ -1,6 +1,6 @@
/*
* 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.
* Copyright 2000-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.debugger.surroundWith
@@ -20,9 +20,9 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinRuntimeTypeEvaluator
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.core.surroundWith.KotlinExpressionSurrounder
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinRuntimeTypeEvaluator
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -30,7 +30,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
class KotlinRuntimeTypeCastSurrounder: KotlinExpressionSurrounder() {
class KotlinRuntimeTypeCastSurrounder : KotlinExpressionSurrounder() {
override fun isApplicable(expression: KtExpression): Boolean {
if (!super.isApplicable(expression)) return false
@@ -61,11 +61,11 @@ class KotlinRuntimeTypeCastSurrounder: KotlinExpressionSurrounder() {
}
private inner class SurroundWithCastWorker(
private val myEditor: Editor,
expression: KtExpression,
context: DebuggerContextImpl,
indicator: ProgressIndicator
): KotlinRuntimeTypeEvaluator(myEditor, expression, context, indicator) {
private val myEditor: Editor,
expression: KtExpression,
context: DebuggerContextImpl,
indicator: ProgressIndicator
) : KotlinRuntimeTypeEvaluator(myEditor, expression, context, indicator) {
override fun typeCalculationFinished(type: KotlinType?) {
if (type == null) return
@@ -74,29 +74,28 @@ class KotlinRuntimeTypeCastSurrounder: KotlinExpressionSurrounder() {
val project = myEditor.project
DebuggerInvocationUtil.invokeLater(project, Runnable {
object : WriteCommandAction<Any>(project, CodeInsightBundle.message("command.name.surround.with.runtime.cast")) {
override fun run(result: Result<Any>) {
try {
val factory = KtPsiFactory(myElement.project)
object : WriteCommandAction<Any>(project, CodeInsightBundle.message("command.name.surround.with.runtime.cast")) {
override fun run(result: Result<Any>) {
try {
val factory = KtPsiFactory(myElement.project)
val fqName = DescriptorUtils.getFqName(type.constructor.declarationDescriptor!!)
val parentCast = factory.createExpression("(expr as " + fqName.asString() + ")") as KtParenthesizedExpression
val cast = parentCast.expression as KtBinaryExpressionWithTypeRHS
cast.left.replace(myElement)
val expr = myElement.replace(parentCast) as KtExpression
val fqName = DescriptorUtils.getFqName(type.constructor.declarationDescriptor!!)
val parentCast = factory.createExpression("(expr as " + fqName.asString() + ")") as KtParenthesizedExpression
val cast = parentCast.expression as KtBinaryExpressionWithTypeRHS
cast.left.replace(myElement)
val expr = myElement.replace(parentCast) as KtExpression
ShortenReferences.DEFAULT.process(expr)
ShortenReferences.DEFAULT.process(expr)
val range = expr.textRange
myEditor.selectionModel.setSelection(range.startOffset, range.endOffset)
myEditor.caretModel.moveToOffset(range.endOffset)
myEditor.scrollingModel.scrollToCaret(ScrollType.RELATIVE)
}
finally {
release()
}
val range = expr.textRange
myEditor.selectionModel.setSelection(range.startOffset, range.endOffset)
myEditor.caretModel.moveToOffset(range.endOffset)
myEditor.scrollingModel.scrollToCaret(ScrollType.RELATIVE)
} finally {
release()
}
}.execute()
}
}.execute()
}, myProgressIndicator.modalityState)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2017 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2000-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.
*/
@@ -66,8 +66,7 @@ class KotlinChainTransformerImpl(private val typeExtractor: CallTypeExtractor) :
}
private fun createQualifier(expression: PsiElement, typeAfter: GenericType): QualifierExpression {
val parent = expression.parent as? KtDotQualifiedExpression
?: return QualifierExpressionImpl("", TextRange.EMPTY_RANGE, typeAfter)
val parent = expression.parent as? KtDotQualifiedExpression ?: return QualifierExpressionImpl("", TextRange.EMPTY_RANGE, typeAfter)
val receiver = parent.receiverExpression
return QualifierExpressionImpl(receiver.text, receiver.textRange, typeAfter)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.debugger.sequence.psi.java
import org.jetbrains.kotlin.idea.debugger.sequence.psi.CallCheckerWithNameHeuristics
import org.jetbrains.kotlin.idea.debugger.sequence.psi.StreamCallChecker
class StreamExCallChecker(nestedChecker: StreamCallChecker): CallCheckerWithNameHeuristics(nestedChecker) {
class StreamExCallChecker(nestedChecker: StreamCallChecker) : CallCheckerWithNameHeuristics(nestedChecker) {
private companion object {
val TERMINATION_CALLS: Set<String> = setOf(
"forEach", "toArray", "reduce", "collect", "min", "max", "count", "sum", "anyMatch", "allMatch", "noneMatch", "findFirst",
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2017 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2000-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.
*/
@@ -28,8 +28,8 @@ class SequenceTypeExtractor : CallTypeExtractor.Base() {
override fun getResultType(type: KotlinType): GenericType {
val typeName = KotlinPsiUtil.getTypeWithoutTypeParameters(type)
return KotlinSequenceTypes.primitiveTypeByName(typeName)
?: KotlinSequenceTypes.primitiveArrayByName(typeName)
?: ClassTypeImpl(KotlinPsiUtil.getTypeName(type))
?: KotlinSequenceTypes.primitiveArrayByName(typeName)
?: ClassTypeImpl(KotlinPsiUtil.getTypeName(type))
}
private fun tryToFindElementType(type: KotlinType): GenericType? {
@@ -15,7 +15,8 @@ import com.intellij.debugger.streams.trace.impl.handler.type.ArrayType
class KotlinArrayVariable(override val type: ArrayType, override val name: String) : VariableImpl(type, name), ArrayVariable {
override fun get(index: Expression): Expression = TextExpression("$name[${index.toCode()}]!!")
override operator fun set(index: Expression, value: Expression): Expression = TextExpression("$name[${index.toCode()}] = ${value.toCode()}")
override operator fun set(index: Expression, value: Expression): Expression =
TextExpression("$name[${index.toCode()}] = ${value.toCode()}")
override fun defaultDeclaration(size: Expression): VariableDeclaration =
KotlinVariableDeclaration(this, false, type.sizedDeclaration(size.toCode()))
@@ -4,6 +4,7 @@
*/
@file:JvmName("DebuggerTestUtils")
package org.jetbrains.kotlin.idea.debugger.test
import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -31,7 +31,7 @@ class MockMethod : Method {
override fun isAbstract() = throw UnsupportedOperationException()
override fun isVarArgs() = throw UnsupportedOperationException()
override fun returnTypeName() = throw UnsupportedOperationException()
override fun argumentTypes( ) = throw UnsupportedOperationException()
override fun argumentTypes() = throw UnsupportedOperationException()
override fun isConstructor() = throw UnsupportedOperationException()
override fun locationsOfLine(lineNumber: Int) = throw UnsupportedOperationException()
override fun locationsOfLine(stratum: String?, sourceName: String?, lineNumber: Int) = throw UnsupportedOperationException()
@@ -13,14 +13,14 @@ import org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings
import org.jetbrains.kotlin.idea.debugger.ToggleKotlinVariablesState
import org.jetbrains.kotlin.idea.debugger.emulateDexDebugInTests
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.DISABLE_KOTLIN_INTERNAL_CLASSES
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.EMULATE_DEX
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.IS_FILTER_FOR_STDLIB_ALREADY_ADDED
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.RENDER_DELEGATED_PROPERTIES
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.SKIP_CONSTRUCTORS
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.SKIP_CLASSLOADERS
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.SKIP_CONSTRUCTORS
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.SKIP_GETTERS
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.SKIP_SYNTHETIC_METHODS
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.TRACING_FILTERS_ENABLED
import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.EMULATE_DEX
import kotlin.reflect.KMutableProperty1
internal val SettingsMutators: List<SettingsMutator<*>> = listOf(
@@ -38,7 +38,7 @@ internal val SettingsMutators: List<SettingsMutator<*>> = listOf(
ForceRankingSettingsMutator
)
private class DexSettingsMutator(key: DebuggerPreferenceKey<Boolean>): SettingsMutator<Boolean>(key) {
private class DexSettingsMutator(key: DebuggerPreferenceKey<Boolean>) : SettingsMutator<Boolean>(key) {
override fun setValue(value: Boolean, project: Project): Boolean {
val oldValue = emulateDexDebugInTests
emulateDexDebugInTests = value
@@ -6,8 +6,8 @@ package org.jetbrains.kotlin.idea.debugger.test.sequence.psi.collection
import com.intellij.debugger.streams.wrapper.StreamChainBuilder
import org.jetbrains.kotlin.idea.debugger.sequence.lib.collections.KotlinCollectionSupportProvider
import org.jetbrains.kotlin.idea.debugger.test.sequence.psi.TypedChainTestCase
import org.jetbrains.kotlin.idea.debugger.sequence.trace.dsl.KotlinSequenceTypes
import org.jetbrains.kotlin.idea.debugger.test.sequence.psi.TypedChainTestCase
import org.jetbrains.kotlin.test.JUnit3WithIdeaConfigurationRunner
import org.junit.runner.RunWith
@@ -51,6 +51,9 @@ class TypedCollectionChainTest : TypedChainTestCase("collection/positive/types")
fun testNullableToNotNull() = doTest(KotlinSequenceTypes.NULLABLE_ANY, KotlinSequenceTypes.INT)
fun testNotNullToNullable() = doTest(KotlinSequenceTypes.DOUBLE, KotlinSequenceTypes.NULLABLE_ANY)
fun testFewTransitions1() = doTest(KotlinSequenceTypes.BYTE, KotlinSequenceTypes.ANY, KotlinSequenceTypes.NULLABLE_ANY, KotlinSequenceTypes.INT)
fun testFewTransitions2() = doTest(KotlinSequenceTypes.CHAR, KotlinSequenceTypes.BOOLEAN, KotlinSequenceTypes.DOUBLE, KotlinSequenceTypes.ANY)
fun testFewTransitions1() =
doTest(KotlinSequenceTypes.BYTE, KotlinSequenceTypes.ANY, KotlinSequenceTypes.NULLABLE_ANY, KotlinSequenceTypes.INT)
fun testFewTransitions2() =
doTest(KotlinSequenceTypes.CHAR, KotlinSequenceTypes.BOOLEAN, KotlinSequenceTypes.DOUBLE, KotlinSequenceTypes.ANY)
}
@@ -109,9 +109,9 @@ internal class KotlinOutputChecker(
val disconnectedIndex = lines.indexOfFirst { it.startsWith(DISCONNECT_PREFIX) }
lines[disconnectedIndex] = DISCONNECT_PREFIX
return lines.filter { !(it.matches(JDI_BUG_OUTPUT_PATTERN_1) || it.matches(
JDI_BUG_OUTPUT_PATTERN_2
)) }.joinToString("\n")
return lines.filter {
!(it.matches(JDI_BUG_OUTPUT_PATTERN_1) || it.matches(JDI_BUG_OUTPUT_PATTERN_2))
}.joinToString("\n")
}
private fun buildOutputString(): String {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -239,7 +239,7 @@ abstract class FileRankingCalculator(private val checkClassFqName: Boolean = tru
val containingClass = elementAt.getParentOfType<KtClassOrObject>(false) ?: return LOW
val constructorOrInitializer =
elementAt.getParentOfTypes2<KtConstructor<*>, KtClassInitializer>()?.takeIf { containingClass.isAncestor(it) }
?: containingClass.primaryConstructor?.takeIf { it.getLine() == containingClass.getLine() }
?: containingClass.primaryConstructor?.takeIf { it.getLine() == containingClass.getLine() }
if (constructorOrInitializer == null
&& locationLineNumber < containingClass.getLine()
@@ -1,17 +1,6 @@
/*
* 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.
* 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.debugger
@@ -102,8 +91,7 @@ class KotlinEditorTextProvider : EditorTextProvider {
val qualifier = context[BindingContext.QUALIFIER, ktElement]
if (qualifier != null && !DescriptorUtils.isObject(qualifier.descriptor)) {
null
}
else {
} else {
ktElement
}
}
@@ -113,11 +101,10 @@ class KotlinEditorTextProvider : EditorTextProvider {
}
private val NOT_ACCEPTED_AS_CONTEXT_TYPES =
arrayOf(KtUserType::class.java, KtImportDirective::class.java, KtPackageDirective::class.java, KtValueArgumentName::class.java)
arrayOf(KtUserType::class.java, KtImportDirective::class.java, KtPackageDirective::class.java, KtValueArgumentName::class.java)
fun isAcceptedAsCodeFragmentContext(element: PsiElement): Boolean {
return !NOT_ACCEPTED_AS_CONTEXT_TYPES.contains(element::class.java as Class<*>) &&
PsiTreeUtil.getParentOfType(element, *NOT_ACCEPTED_AS_CONTEXT_TYPES) == null
}
fun isAcceptedAsCodeFragmentContext(element: PsiElement): Boolean =
!NOT_ACCEPTED_AS_CONTEXT_TYPES.contains(element::class.java as Class<*>) &&
PsiTreeUtil.getParentOfType(element, *NOT_ACCEPTED_AS_CONTEXT_TYPES) == null
}
}
@@ -22,10 +22,10 @@ import com.sun.jdi.ReferenceType
import com.sun.jdi.VirtualMachine
import org.jetbrains.kotlin.idea.caches.project.implementingModules
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
import org.jetbrains.kotlin.idea.core.util.getLineCount
import org.jetbrains.kotlin.idea.core.util.getLineStartOffset
import org.jetbrains.kotlin.idea.core.util.toPsiFile
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.lexer.KtTokens
@@ -55,14 +55,18 @@ fun isInlineFunctionLineNumber(file: VirtualFile, lineNumber: Int, project: Proj
return true
}
fun readBytecodeInfo(project: Project,
jvmName: JvmClassName,
file: VirtualFile): BytecodeDebugInfo? {
fun readBytecodeInfo(
project: Project,
jvmName: JvmClassName,
file: VirtualFile
): BytecodeDebugInfo? {
return KotlinDebuggerCaches.getOrReadDebugInfoFromBytecode(project, jvmName, file)
}
fun ktLocationInfo(location: Location, isDexDebug: Boolean, project: Project,
preferInlined: Boolean = false, locationFile: KtFile? = null): Pair<Int, KtFile?> {
fun ktLocationInfo(
location: Location, isDexDebug: Boolean, project: Project,
preferInlined: Boolean = false, locationFile: KtFile? = null
): Pair<Int, KtFile?> {
if (isDexDebug && (locationFile == null || location.lineNumber() > locationFile.getLineCount())) {
if (!preferInlined) {
val thisFunLine = runReadAction { getLastLineNumberForLocation(location, project) }
@@ -85,7 +89,11 @@ fun ktLocationInfo(location: Location, isDexDebug: Boolean, project: Project,
* Only the first line number is stored for instruction in dex. It can be obtained through location.lineNumber().
* This method allows to get last stored linenumber for instruction.
*/
fun getLastLineNumberForLocation(location: Location, project: Project, searchScope: GlobalSearchScope = GlobalSearchScope.allScope(project)): Int? {
fun getLastLineNumberForLocation(
location: Location,
project: Project,
searchScope: GlobalSearchScope = GlobalSearchScope.allScope(project)
): Int? {
val lineNumber = location.lineNumber()
val fqName = FqName(location.declaringType().name())
val fileName = location.sourceName()
@@ -94,7 +102,8 @@ fun getLastLineNumberForLocation(location: Location, project: Project, searchSco
val name = method.name() ?: return null
val signature = method.signature() ?: return null
val debugInfo = findAndReadClassFile(fqName, fileName, project, searchScope, { isInlineFunctionLineNumber(it, lineNumber, project) }) ?: return null
val debugInfo =
findAndReadClassFile(fqName, fileName, project, searchScope, { isInlineFunctionLineNumber(it, lineNumber, project) }) ?: return null
val lineMapping = debugInfo.lineTableMapping[BytecodeMethodKey(name, signature)] ?: return null
return lineMapping.values.firstOrNull { it.contains(lineNumber) }?.last()
@@ -117,9 +126,11 @@ data class BytecodeMethodKey(val methodName: String, val signature: String)
data class BinaryCacheKey(val project: Project, val jvmName: JvmClassName, val file: VirtualFile)
private fun readClassFileImpl(project: Project,
jvmName: JvmClassName,
file: VirtualFile): ByteArray? {
private fun readClassFileImpl(
project: Project,
jvmName: JvmClassName,
file: VirtualFile
): ByteArray? {
val fqNameWithInners = jvmName.fqNameForClassNameWithoutDollars.tail(jvmName.packageFqName)
fun readFromLibrary(): ByteArray? {
@@ -175,13 +186,11 @@ private fun readClassFileImpl(project: Project,
fun readFromTestOutput(): ByteArray? = readFromOutput(true)
return readFromLibrary() ?:
readFromSourceOutput() ?:
readFromTestOutput()
return readFromLibrary() ?: readFromSourceOutput() ?: readFromTestOutput()
}
private fun findClassFileByPaths(packageName: String, className: String, paths: List<String>): File? =
paths.mapNotNull { path -> findClassFileByPath(packageName, className, path) }.maxBy { it.lastModified() }
paths.mapNotNull { path -> findClassFileByPath(packageName, className, path) }.maxBy { it.lastModified() }
private fun findClassFileByPath(packageName: String, className: String, outputDirPath: String): File? {
val outDirFile = File(outputDirPath).takeIf(File::exists) ?: return null
@@ -208,7 +217,13 @@ private fun readLineNumberTableMapping(bytes: ByteArray): Map<BytecodeMethodKey,
val lineNumberMapping = HashMap<BytecodeMethodKey, Map<String, Set<Int>>>()
ClassReader(bytes).accept(object : ClassVisitor(Opcodes.API_VERSION) {
override fun visitMethod(access: Int, name: String?, desc: String?, signature: String?, exceptions: Array<out String>?): MethodVisitor? {
override fun visitMethod(
access: Int,
name: String?,
desc: String?,
signature: String?,
exceptions: Array<out String>?
): MethodVisitor? {
if (name == null || desc == null) {
return null
}
@@ -236,16 +251,17 @@ internal fun getOriginalPositionOfInlinedLine(location: Location, project: Proje
val fileName = location.sourceName()
val searchScope = GlobalSearchScope.allScope(project)
val debugInfo = findAndReadClassFile(fqName, fileName, project, searchScope, { isInlineFunctionLineNumber(it, lineNumber, project) }) ?:
return null
val debugInfo =
findAndReadClassFile(fqName, fileName, project, searchScope) { isInlineFunctionLineNumber(it, lineNumber, project) } ?: return null
val smapData = debugInfo.smapData ?: return null
return mapStacktraceLineToSource(smapData, lineNumber, project, SourceLineKind.EXECUTED_LINE, searchScope)
}
private fun findAndReadClassFile(
fqName: FqName, fileName: String, project: Project, searchScope: GlobalSearchScope,
fileFilter: (VirtualFile) -> Boolean): BytecodeDebugInfo? {
fqName: FqName, fileName: String, project: Project, searchScope: GlobalSearchScope,
fileFilter: (VirtualFile) -> Boolean
): BytecodeDebugInfo? {
val internalName = fqName.asString().replace('.', '/')
val jvmClassName = JvmClassName.byInternalName(internalName)
@@ -285,7 +301,8 @@ fun isInCrossinlineArgument(ktElement: KtElement): Boolean {
val argumentFunctions = runReadAction {
ktElement.parents.filter {
when (it) {
is KtFunctionLiteral -> it.parent is KtLambdaExpression && (it.parent.parent is KtValueArgument || it.parent.parent is KtLambdaArgument)
is KtFunctionLiteral -> it.parent is KtLambdaExpression &&
(it.parent.parent is KtValueArgument || it.parent.parent is KtLambdaArgument)
is KtFunction -> it.parent is KtValueArgument
else -> false
}
@@ -301,14 +318,15 @@ fun isInCrossinlineArgument(ktElement: KtElement): Boolean {
private fun inlinedLinesNumbers(
inlineLineNumber: Int, inlineFileName: String,
destinationTypeFqName: FqName, destinationFileName: String,
project: Project, sourceSearchScope: GlobalSearchScope): List<Int> {
inlineLineNumber: Int, inlineFileName: String,
destinationTypeFqName: FqName, destinationFileName: String,
project: Project, sourceSearchScope: GlobalSearchScope
): List<Int> {
val internalName = destinationTypeFqName.asString().replace('.', '/')
val jvmClassName = JvmClassName.byInternalName(internalName)
val file = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(project, sourceSearchScope, jvmClassName, destinationFileName) ?:
return listOf()
val file = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(project, sourceSearchScope, jvmClassName, destinationFileName)
?: return listOf()
val virtualFile = file.virtualFile ?: return listOf()
@@ -320,14 +338,12 @@ private fun inlinedLinesNumbers(
val mappingsToInlinedFile = smap.fileMappings.filter { it.name == inlineFileName }
val mappingIntervals = mappingsToInlinedFile.flatMap { it.lineMappings }
return mappingIntervals.asSequence().
filter { rangeMapping -> rangeMapping.hasMappingForSource(inlineLineNumber) }.
map { rangeMapping -> rangeMapping.mapSourceToDest(inlineLineNumber) }.
filter { line -> line != -1 }.
toList()
return mappingIntervals.asSequence().filter { rangeMapping -> rangeMapping.hasMappingForSource(inlineLineNumber) }
.map { rangeMapping -> rangeMapping.mapSourceToDest(inlineLineNumber) }.filter { line -> line != -1 }.toList()
}
@Volatile var emulateDexDebugInTests: Boolean = false
@Volatile
var emulateDexDebugInTests: Boolean = false
fun DebugProcess.isDexDebug(): Boolean {
val virtualMachine = (this.virtualMachineProxy as? VirtualMachineProxyImpl)?.virtualMachine
@@ -23,7 +23,8 @@ inline fun <T : Any> hopelessAware(block: () -> T?): T? {
fun handleHopelessException(e: Exception) {
when (if (e is EvaluateException) e.cause ?: e else e) {
is IncompatibleThreadStateException, is VMDisconnectedException -> {}
is IncompatibleThreadStateException, is VMDisconnectedException -> {
}
else -> {
if (e is EvaluateException) {
LOG.debug("Cannot evaluate async stack trace", e)
@@ -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 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.debugger
@@ -32,15 +21,17 @@ enum class SourceLineKind {
EXECUTED_LINE
}
fun mapStacktraceLineToSource(smapData: SmapData,
line: Int,
project: Project,
lineKind: SourceLineKind,
searchScope: GlobalSearchScope): Pair<KtFile, Int>? {
fun mapStacktraceLineToSource(
smapData: SmapData,
line: Int,
project: Project,
lineKind: SourceLineKind,
searchScope: GlobalSearchScope
): Pair<KtFile, Int>? {
val smap = when (lineKind) {
SourceLineKind.CALL_LINE -> smapData.kotlinDebugStrata
SourceLineKind.EXECUTED_LINE -> smapData.kotlinStrata
} ?: return null
SourceLineKind.CALL_LINE -> smapData.kotlinDebugStrata
SourceLineKind.EXECUTED_LINE -> smapData.kotlinStrata
} ?: return null
val mappingInfo = smap.fileMappings.firstOrNull {
it.getIntervalIfContains(line) != null
@@ -48,7 +39,8 @@ fun mapStacktraceLineToSource(smapData: SmapData,
val jvmName = JvmClassName.byInternalName(mappingInfo.path)
val sourceFile = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(
project, searchScope, jvmName, mappingInfo.name) ?: return null
project, searchScope, jvmName, mappingInfo.name
) ?: return null
val interval = mappingInfo.getIntervalIfContains(line)!!
val sourceLine = when (lineKind) {