idea: cleanup code
This commit is contained in:
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
}
|
||||
|
||||
+18
-30
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+38
-47
@@ -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
|
||||
|
||||
+21
-17
@@ -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
|
||||
|
||||
+9
-21
@@ -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
|
||||
}
|
||||
|
||||
+38
-53
@@ -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$*")
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
+3
-14
@@ -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) {
|
||||
|
||||
+24
-23
@@ -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
|
||||
|
||||
+59
-68
@@ -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 {
|
||||
|
||||
+7
-16
@@ -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)
|
||||
|
||||
+22
-35
@@ -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
|
||||
|
||||
+5
-16
@@ -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
|
||||
|
||||
+11
-21
@@ -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
|
||||
|
||||
+13
-19
@@ -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
|
||||
}
|
||||
|
||||
+7
-18
@@ -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 {
|
||||
|
||||
+6
-19
@@ -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() }
|
||||
}
|
||||
}
|
||||
+15
-27
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-17
@@ -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
|
||||
|
||||
|
||||
+7
-15
@@ -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
|
||||
}
|
||||
|
||||
+5
-2
@@ -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)
|
||||
|
||||
+6
-8
@@ -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
|
||||
|
||||
|
||||
+27
-28
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+2
-3
@@ -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)
|
||||
|
||||
+2
-2
@@ -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",
|
||||
|
||||
+3
-3
@@ -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? {
|
||||
|
||||
+2
-1
@@ -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()))
|
||||
|
||||
+1
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
@file:JvmName("DebuggerTestUtils")
|
||||
|
||||
package org.jetbrains.kotlin.idea.debugger.test
|
||||
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
+3
-3
@@ -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
-3
@@ -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)
|
||||
}
|
||||
+3
-3
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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()
|
||||
|
||||
+7
-20
@@ -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
|
||||
}
|
||||
}
|
||||
+48
-32
@@ -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
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+14
-22
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user