Support multiple breakpoints at one line (especially for lambdas)
This commit is contained in:
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.fileClasses.getInternalName
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny
|
||||
import org.jetbrains.kotlin.idea.decompiler.JetClsFile
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
|
||||
import org.jetbrains.kotlin.idea.util.DebuggerUtils
|
||||
@@ -64,6 +65,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.utils.toReadOnlyList
|
||||
import java.util.*
|
||||
import com.intellij.debugger.engine.DebuggerUtils as JDebuggerUtils
|
||||
|
||||
@@ -135,10 +137,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
val end = CodeInsightUtils.getEndLineOffset(file, lineNumber)
|
||||
if (start == null || end == null) return null
|
||||
|
||||
val literalsOrFunctions = CodeInsightUtils.
|
||||
findElementsOfClassInRange(file, start, end, KtFunctionLiteral::class.java, KtNamedFunction::class.java).
|
||||
filter { KtPsiUtil.getParentCallIfPresent(it as KtExpression) != null }
|
||||
|
||||
val literalsOrFunctions = getLambdasAtLineIfAny(file, lineNumber)
|
||||
if (literalsOrFunctions.isEmpty()) return null;
|
||||
|
||||
val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != null
|
||||
@@ -149,17 +148,16 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
|
||||
val currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName)).internalName
|
||||
for (literal in literalsOrFunctions) {
|
||||
val functionLiteral = literal as KtFunction
|
||||
if (isInlinedLambda(functionLiteral, typeMapper.bindingContext)) {
|
||||
if (isInsideInlineArgument(functionLiteral, location, myDebugProcess as DebugProcessImpl)) {
|
||||
return functionLiteral
|
||||
if (isInlinedLambda(literal, typeMapper.bindingContext)) {
|
||||
if (isInsideInlineArgument(literal, location, myDebugProcess as DebugProcessImpl)) {
|
||||
return literal
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
val internalClassName = getInternalClassNameForElement(literal.firstChild, typeMapper, file, isInLibrary).className
|
||||
if (internalClassName == currentLocationClassName) {
|
||||
return functionLiteral
|
||||
return literal
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +230,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
}
|
||||
|
||||
private fun classNameForPositionAndInlinedOnes(sourcePosition: SourcePosition): List<String> {
|
||||
val result = arrayListOf<String>()
|
||||
val result = hashSetOf<String>()
|
||||
val name = classNameForPosition(sourcePosition)
|
||||
if (name != null) {
|
||||
result.add(name)
|
||||
@@ -240,7 +238,22 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
|
||||
val list = findInlinedCalls(sourcePosition.elementAt, sourcePosition.file)
|
||||
result.addAll(list)
|
||||
|
||||
return result;
|
||||
val lambdas = findLambdas(sourcePosition)
|
||||
result.addAll(lambdas)
|
||||
|
||||
return result.toReadOnlyList();
|
||||
}
|
||||
|
||||
private fun findLambdas(sourcePosition: SourcePosition): List<String> {
|
||||
return runReadAction {
|
||||
val lambdas = getLambdasAtLineIfAny(sourcePosition)
|
||||
val file = sourcePosition.file.containingFile as KtFile
|
||||
val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != null
|
||||
lambdas.map {
|
||||
val typeMapper = if (!isInLibrary) prepareTypeMapper(file) else createTypeMapperForLibraryFile(it, file)
|
||||
getInternalClassNameForElement(it, typeMapper, file, isInLibrary).className
|
||||
}.filterNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
public fun classNameForPosition(sourcePosition: SourcePosition): String? {
|
||||
|
||||
+83
-4
@@ -17,17 +17,29 @@
|
||||
package org.jetbrains.kotlin.idea.debugger.breakpoints;
|
||||
|
||||
import com.intellij.debugger.SourcePosition;
|
||||
import com.intellij.debugger.ui.breakpoints.Breakpoint;
|
||||
import com.intellij.debugger.ui.breakpoints.BreakpointManager;
|
||||
import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType;
|
||||
import com.intellij.debugger.ui.breakpoints.LineBreakpoint;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint;
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;
|
||||
import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties;
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons;
|
||||
import org.jetbrains.kotlin.psi.KtFunction;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.List;
|
||||
|
||||
public class KotlinLineBreakpointType extends JavaLineBreakpointType {
|
||||
public KotlinLineBreakpointType() {
|
||||
super("kotlin-line", "Kotlin Line Breakpoints");
|
||||
@@ -35,11 +47,16 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType {
|
||||
|
||||
@Override
|
||||
public boolean matchesPosition(@NotNull LineBreakpoint<?> breakpoint, @NotNull SourcePosition position) {
|
||||
if (super.matchesPosition(breakpoint, position)) return true;
|
||||
JavaBreakpointProperties properties = getProperties(breakpoint);
|
||||
if (properties == null || properties instanceof JavaLineBreakpointProperties) {
|
||||
if (properties != null && ((JavaLineBreakpointProperties)properties).getLambdaOrdinal() == null) return true;
|
||||
|
||||
PsiElement containingMethod = getContainingMethod(breakpoint);
|
||||
if (containingMethod == null) return false;
|
||||
return inTheMethod(position, containingMethod);
|
||||
PsiElement containingMethod = getContainingMethod(breakpoint);
|
||||
if (containingMethod == null) return false;
|
||||
return inTheMethod(position, containingMethod);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,9 +65,34 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType {
|
||||
SourcePosition position = breakpoint.getSourcePosition();
|
||||
if (position == null) return null;
|
||||
|
||||
JavaBreakpointProperties properties = getProperties(breakpoint);
|
||||
if (properties instanceof JavaLineBreakpointProperties) {
|
||||
Integer ordinal = ((JavaLineBreakpointProperties) properties).getLambdaOrdinal();
|
||||
PsiElement lambda = getLambdaByOrdinal(position, ordinal);
|
||||
if (lambda != null) return lambda;
|
||||
}
|
||||
|
||||
return getContainingMethod(position.getElementAt());
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static JavaBreakpointProperties getProperties(@NotNull LineBreakpoint<?> breakpoint) {
|
||||
XBreakpoint<?> xBreakpoint = breakpoint.getXBreakpoint();
|
||||
return xBreakpoint != null ? (JavaBreakpointProperties) xBreakpoint.getProperties() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static KtFunction getLambdaByOrdinal(SourcePosition position, Integer ordinal) {
|
||||
if (ordinal != null && ordinal >= 0) {
|
||||
List<KtFunction> lambdas = BreakpointTypeUtilsKt.getLambdasAtLineIfAny(position);
|
||||
if (lambdas.size() >= ordinal) {
|
||||
return lambdas.get(ordinal);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getContainingMethod(@Nullable PsiElement elem) {
|
||||
//noinspection unchecked
|
||||
@@ -68,5 +110,42 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType {
|
||||
return BreakpointTypeUtilsKt.canPutAt(file, line, project, getClass());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JavaBreakpointVariant> computeVariants(@NotNull Project project, @NotNull XSourcePosition position) {
|
||||
return BreakpointTypeUtilsKt.computeVariants(project, position, this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TextRange getHighlightRange(XLineBreakpoint<JavaLineBreakpointProperties> breakpoint) {
|
||||
JavaLineBreakpointProperties properties = breakpoint.getProperties();
|
||||
if (properties != null) {
|
||||
Integer ordinal = properties.getLambdaOrdinal();
|
||||
if (ordinal != null) {
|
||||
Breakpoint javaBreakpoint = BreakpointManager.getJavaBreakpoint(breakpoint);
|
||||
if (javaBreakpoint instanceof LineBreakpoint) {
|
||||
SourcePosition position = ((LineBreakpoint) javaBreakpoint).getSourcePosition();
|
||||
if (position != null) {
|
||||
KtFunction lambda = getLambdaByOrdinal(position, ordinal);
|
||||
if (lambda != null) {
|
||||
return lambda.getTextRange();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public class ExactKotlinJavaBreakpointVariant extends ExactJavaBreakpointVariant {
|
||||
public ExactKotlinJavaBreakpointVariant(XSourcePosition position, KtFunction function, Integer lambdaOrdinal) {
|
||||
super(position, function, lambdaOrdinal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return KotlinIcons.LAMBDA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,19 +16,32 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.debugger.breakpoints
|
||||
|
||||
import com.intellij.debugger.SourcePosition
|
||||
import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.xdebugger.XDebuggerUtil
|
||||
import com.intellij.xdebugger.XSourcePosition
|
||||
import com.intellij.xdebugger.impl.XSourcePositionImpl
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.getLineEndOffset
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.getLineNumber
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.getLineStartOffset
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import java.util.*
|
||||
|
||||
fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass: Class<*>): Boolean {
|
||||
val psiFile = PsiManager.getInstance(project).findFile(file)
|
||||
@@ -80,4 +93,73 @@ fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass
|
||||
return result == breakpointTypeClass
|
||||
}
|
||||
|
||||
fun computeVariants(
|
||||
project: Project, position: XSourcePosition,
|
||||
kotlinBreakpointType: KotlinLineBreakpointType
|
||||
): List<JavaLineBreakpointType.JavaBreakpointVariant> {
|
||||
val file = PsiManager.getInstance(project).findFile(position.file) as? KtFile ?: return emptyList()
|
||||
|
||||
val pos = SourcePosition.createFromLine(file, position.line)
|
||||
val lambdas = getLambdasAtLineIfAny(pos)
|
||||
if (lambdas.isEmpty()) return emptyList()
|
||||
|
||||
val result = LinkedList<JavaLineBreakpointType.JavaBreakpointVariant>()
|
||||
|
||||
val mainMethod = KotlinLineBreakpointType.getContainingMethod(pos.elementAt)
|
||||
if (mainMethod != null) {
|
||||
result.add((kotlinBreakpointType as JavaLineBreakpointType).ExactJavaBreakpointVariant(
|
||||
XSourcePositionImpl.createByElement(mainMethod),
|
||||
mainMethod, -1))
|
||||
}
|
||||
|
||||
lambdas.forEachIndexed { ordinal, lambda ->
|
||||
result.add(kotlinBreakpointType.ExactKotlinJavaBreakpointVariant(
|
||||
XSourcePositionImpl.createByElement(lambda.bodyExpression), lambda, ordinal))
|
||||
}
|
||||
|
||||
if (result.size > 1) {
|
||||
val allBreakpoint = (kotlinBreakpointType as JavaLineBreakpointType).JavaBreakpointVariant(position)
|
||||
result.addFirst(allBreakpoint)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun getLambdasAtLineIfAny(sourcePosition: SourcePosition): List<KtFunction> {
|
||||
val file = sourcePosition.file as? KtFile ?: return emptyList()
|
||||
val lineNumber = sourcePosition.line
|
||||
return getLambdasAtLineIfAny(file, lineNumber)
|
||||
}
|
||||
|
||||
fun getLambdasAtLineIfAny(file: KtFile, line: Int): List<KtFunction> {
|
||||
var lineStartOffset = file.getLineStartOffset(line) ?: return emptyList()
|
||||
var lineEndOffset = file.getLineEndOffset(line) ?: return emptyList()
|
||||
|
||||
var topMostElement: PsiElement? = null
|
||||
var elementAt: PsiElement?
|
||||
while (topMostElement !is KtElement && lineStartOffset < lineEndOffset) {
|
||||
elementAt = file.findElementAt(lineStartOffset)
|
||||
if (elementAt != null) {
|
||||
topMostElement = CodeInsightUtils.getTopmostElementAtOffset(elementAt, lineStartOffset)
|
||||
}
|
||||
lineStartOffset++
|
||||
}
|
||||
|
||||
if (topMostElement !is KtElement) return emptyList()
|
||||
|
||||
val start = topMostElement.startOffset
|
||||
val end = topMostElement.endOffset
|
||||
|
||||
val allInlineFunctionCalls = CodeInsightUtils.
|
||||
findElementsOfClassInRange(file, start, end, KtFunction::class.java)
|
||||
.filter { KtPsiUtil.getParentCallIfPresent(it as KtExpression) != null }
|
||||
.filterIsInstance<KtFunction>()
|
||||
.toSet()
|
||||
|
||||
return allInlineFunctionCalls.filter {
|
||||
val statement = (it.bodyExpression as? KtBlockExpression)?.statements?.firstOrNull() ?: it
|
||||
statement.getLineNumber() == line && statement.getLineNumber(false) == line
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,11 +36,11 @@ public class KotlinLambdaMethodFilter(
|
||||
private val myLastStatementLine: Int
|
||||
|
||||
init {
|
||||
if (lambda.isMultiLine()) {
|
||||
val body = lambda.bodyExpression
|
||||
if (body != null && lambda.isMultiLine()) {
|
||||
var firstStatementPosition: SourcePosition? = null
|
||||
var lastStatementPosition: SourcePosition? = null
|
||||
val body = lambda.bodyExpression as KtBlockExpression
|
||||
val statements = body.statements
|
||||
val statements = (body as? KtBlockExpression)?.statements ?: listOf(body)
|
||||
if (statements.isNotEmpty()) {
|
||||
firstStatementPosition = SourcePosition.createFromElement(statements.first())
|
||||
if (firstStatementPosition != null) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
LineBreakpoint created at ceAnonymousObjectCapturedInClosure.kt:7
|
||||
LineBreakpoint created at ceAnonymousObjectCapturedInClosure.kt:7 lambdaOrdinal = -1
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! ceAnonymousObjectCapturedInClosure.CeAnonymousObjectCapturedInClosureKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
ceAnonymousObjectCapturedInClosure.kt:7
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:9 lambdaOrdinal = -1
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:14 lambdaOrdinal = 0
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:19 lambdaOrdinal = 1
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:30
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:38 lambdaOrdinal = -1
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:43 lambdaOrdinal = 0
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:48 lambdaOrdinal = 1
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:62
|
||||
LineBreakpoint created at multipleBreakpointsAtLine.kt:67 lambdaOrdinal = 1
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! multipleBreakpointsAtLine.MultipleBreakpointsAtLineKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
multipleBreakpointsAtLine.kt:9
|
||||
multipleBreakpointsAtLine.kt:14
|
||||
Compile bytecode for it + 2
|
||||
multipleBreakpointsAtLine.kt:19
|
||||
Compile bytecode for it + 3
|
||||
multipleBreakpointsAtLine.kt:30
|
||||
multipleBreakpointsAtLine.kt:30
|
||||
Compile bytecode for it + 5
|
||||
multipleBreakpointsAtLine.kt:30
|
||||
Compile bytecode for it + 6
|
||||
multipleBreakpointsAtLine.kt:38
|
||||
multipleBreakpointsAtLine.kt:38
|
||||
multipleBreakpointsAtLine.kt:43
|
||||
Compile bytecode for it + 9
|
||||
multipleBreakpointsAtLine.kt:48
|
||||
Compile bytecode for it + 10
|
||||
multipleBreakpointsAtLine.kt:62
|
||||
multipleBreakpointsAtLine.kt:62
|
||||
Compile bytecode for it + 12
|
||||
multipleBreakpointsAtLine.kt:62
|
||||
multipleBreakpointsAtLine.kt:62
|
||||
Compile bytecode for it + 14
|
||||
multipleBreakpointsAtLine.kt:67
|
||||
Compile bytecode for it + 15
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
@@ -1,4 +1,4 @@
|
||||
LineBreakpoint created at severalFunLiterals.kt:6
|
||||
LineBreakpoint created at severalFunLiterals.kt:6 lambdaOrdinal = -1
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! severalFunLiterals.SeveralFunLiteralsKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
severalFunLiterals.kt:6
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
LineBreakpoint created at severalFunLiteralsInClass.kt:20
|
||||
LineBreakpoint created at severalFunLiteralsInClass.kt:20 lambdaOrdinal = -1
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! severalFunLiteralsInClass.SeveralFunLiteralsInClassKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
severalFunLiteralsInClass.kt:20
|
||||
|
||||
@@ -2,12 +2,14 @@ LineBreakpoint created at smartStepIntoInlinedFunLiteral.kt:6
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! smartStepIntoInlinedFunLiteral.SmartStepIntoInlinedFunLiteralKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
smartStepIntoInlinedFunLiteral.kt:6
|
||||
smartStepIntoInlinedFunLiteral.kt:9
|
||||
smartStepIntoInlinedFunLiteral.kt:10
|
||||
smartStepIntoInlinedFunLiteral.kt:13
|
||||
smartStepIntoInlinedFunLiteral.kt:14
|
||||
smartStepIntoInlinedFunLiteral.kt:11
|
||||
smartStepIntoInlinedFunLiteral.kt:12
|
||||
smartStepIntoInlinedFunLiteral.kt:17
|
||||
smartStepIntoInlinedFunLiteral.kt:18
|
||||
smartStepIntoInlinedFunLiteral.kt:20
|
||||
smartStepIntoInlinedFunLiteral.kt:24
|
||||
smartStepIntoInlinedFunLiteral.kt:26
|
||||
smartStepIntoInlinedFunLiteral.kt:32
|
||||
smartStepIntoInlinedFunLiteral.kt:32
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
+7
-5
@@ -2,12 +2,14 @@ LineBreakpoint created at smartStepIntoInlinedFunctionalExpression.kt:6
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! smartStepIntoInlinedFunctionalExpression.SmartStepIntoInlinedFunctionalExpressionKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
smartStepIntoInlinedFunctionalExpression.kt:6
|
||||
smartStepIntoInlinedFunctionalExpression.kt:9
|
||||
smartStepIntoInlinedFunctionalExpression.kt:10
|
||||
smartStepIntoInlinedFunctionalExpression.kt:13
|
||||
smartStepIntoInlinedFunctionalExpression.kt:14
|
||||
smartStepIntoInlinedFunctionalExpression.kt:11
|
||||
smartStepIntoInlinedFunctionalExpression.kt:12
|
||||
smartStepIntoInlinedFunctionalExpression.kt:17
|
||||
smartStepIntoInlinedFunctionalExpression.kt:18
|
||||
smartStepIntoInlinedFunctionalExpression.kt:20
|
||||
smartStepIntoInlinedFunctionalExpression.kt:24
|
||||
smartStepIntoInlinedFunctionalExpression.kt:26
|
||||
smartStepIntoInlinedFunctionalExpression.kt:31
|
||||
smartStepIntoInlinedFunctionalExpression.kt:31
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
LineBreakpoint created at twoLambdasOnOneLineFirst.kt:9
|
||||
LineBreakpoint created at twoLambdasOnOneLineFirst.kt:9 lambdaOrdinal = -1
|
||||
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! twoLambdasOnOneLineFirst.TwoLambdasOnOneLineFirstKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
twoLambdasOnOneLineFirst.kt:9
|
||||
|
||||
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
package multipleBreakpointsAtLine
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val a = A()
|
||||
|
||||
// EXPRESSION: it + 1
|
||||
// RESULT: Unresolved reference: it
|
||||
//Breakpoint! (-1)
|
||||
a.foo(1) { 1 }.foo(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 2
|
||||
// RESULT: 3: I
|
||||
//Breakpoint! (0)
|
||||
a.foo(1) { 1 }.foo(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 3
|
||||
// RESULT: 5: I
|
||||
//Breakpoint! (1)
|
||||
a.foo(1) { 1 }.foo(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 4
|
||||
// RESULT: Unresolved reference: it
|
||||
|
||||
// EXPRESSION: it + 5
|
||||
// RESULT: 6: I
|
||||
|
||||
// EXPRESSION: it + 6
|
||||
// RESULT: 8: I
|
||||
//Breakpoint!
|
||||
a.foo(1) { 1 }.foo(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 7
|
||||
// RESULT: Unresolved reference: it
|
||||
|
||||
// EXPRESSION: it + 8
|
||||
// RESULT: Unresolved reference: it
|
||||
//Breakpoint! (-1)
|
||||
a.bar(1) { 1 }.bar(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 9
|
||||
// RESULT: 10: I
|
||||
//Breakpoint! (0)
|
||||
a.bar(1) { 1 }.bar(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 10
|
||||
// RESULT: 12: I
|
||||
//Breakpoint! (1)
|
||||
a.bar(1) { 1 }.bar(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 11
|
||||
// RESULT: Unresolved reference: it
|
||||
|
||||
// EXPRESSION: it + 12
|
||||
// RESULT: 13: I
|
||||
|
||||
// EXPRESSION: it + 13
|
||||
// RESULT: Unresolved reference: it
|
||||
|
||||
// EXPRESSION: it + 14
|
||||
// RESULT: 16: I
|
||||
//Breakpoint!
|
||||
a.bar(1) { 1 }.bar(2) { 1 }
|
||||
|
||||
// EXPRESSION: it + 15
|
||||
// RESULT: 17: I
|
||||
//Breakpoint! (1)
|
||||
a.bar(1) { 1 }.bar(2) { 1 + 1
|
||||
1 + 1
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
fun foo(i: Int, f: (i: Int) -> Int): A {
|
||||
f(i)
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun bar(i: Int, f: (i: Int) -> Int): A {
|
||||
f(i)
|
||||
return this
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,7 @@ package ceAnonymousObjectCapturedInClosure
|
||||
fun main(args: Array<String>) {
|
||||
val localObject = object { fun test() = 1 }
|
||||
var localObjectVar = object { fun test() = 1 }
|
||||
//Breakpoint!
|
||||
//Breakpoint! (-1)
|
||||
lambda { localObjectVar.test() }
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -5,7 +5,7 @@ fun main(args: Array<String>) {
|
||||
// EXPRESSION: it
|
||||
// RESULT: 1: I
|
||||
// STEP_INTO: 2
|
||||
//Breakpoint!
|
||||
//Breakpoint! (-1)
|
||||
a.foo { a }.foo { a }
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package severalFunLiterals
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val myClass = MyClass()
|
||||
//Breakpoint!
|
||||
//Breakpoint! (-1)
|
||||
myClass.f1 { test() }.f2 {
|
||||
test()
|
||||
}
|
||||
@@ -22,4 +22,4 @@ class MyClass {
|
||||
|
||||
fun test() {}
|
||||
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ class MyClass {
|
||||
}
|
||||
|
||||
fun inClass() {
|
||||
//Breakpoint!
|
||||
//Breakpoint! (-1)
|
||||
f1 { test() }.f2 {
|
||||
test()
|
||||
}
|
||||
@@ -25,4 +25,4 @@ class MyClass {
|
||||
|
||||
fun test() {}
|
||||
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
|
||||
+12
-8
@@ -5,20 +5,31 @@ fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
val myClass = MyClass()
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// smart step into f2.invoke(), one-line lambda
|
||||
myClass.f1 { test() }
|
||||
.f2 { test() }
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 2
|
||||
// smart step into map.invoke(), multiline lambda
|
||||
array.map {
|
||||
it *2
|
||||
}
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// smart step into filter.invoke()
|
||||
array.map { it * 2 }
|
||||
.filter {
|
||||
it > 2
|
||||
}
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// smart step into f2.invoke(), one-line lambda
|
||||
myClass.f1 { test() }.f2 { test() }
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
@@ -35,11 +46,4 @@ class MyClass {
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {}
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 2
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
fun test() {}
|
||||
Vendored
+18
-8
@@ -5,20 +5,32 @@ fun main(args: Array<String>) {
|
||||
//Breakpoint!
|
||||
val myClass = MyClass()
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// smart step into f2.invoke(), one-line lambda
|
||||
myClass.f1(fun () { test() })
|
||||
.f2(fun () { test() })
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 2
|
||||
// smart step into map.invoke(), multiline lambda
|
||||
array.map(fun (it): Int {
|
||||
return it * 2
|
||||
})
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// smart step into filter.invoke()
|
||||
array.map(fun (it): Int { return it * 2 })
|
||||
.filter(fun (it): Boolean {
|
||||
return it > 2
|
||||
})
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 2
|
||||
myClass.f3(fun () = myClass.f3 {
|
||||
println()
|
||||
})
|
||||
}
|
||||
|
||||
class MyClass {
|
||||
@@ -33,13 +45,11 @@ class MyClass {
|
||||
f1Param()
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun f3(f1Param: () -> Unit): Unit {
|
||||
test()
|
||||
f1Param()
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {}
|
||||
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 2
|
||||
// STEP_OVER: 1
|
||||
// SMART_STEP_INTO_BY_INDEX: 4
|
||||
fun test() {}
|
||||
@@ -26,25 +26,28 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl
|
||||
import com.intellij.debugger.impl.PositionUtil
|
||||
import com.intellij.debugger.settings.DebuggerSettings
|
||||
import com.intellij.debugger.ui.breakpoints.Breakpoint
|
||||
import com.intellij.debugger.ui.breakpoints.BreakpointManager
|
||||
import com.intellij.debugger.ui.breakpoints.LineBreakpoint
|
||||
import com.intellij.execution.process.ProcessOutputTypes
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.roots.JdkOrderEntry
|
||||
import com.intellij.openapi.roots.libraries.LibraryUtil
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.search.FilenameIndex
|
||||
import com.intellij.xdebugger.XDebuggerManager
|
||||
import com.intellij.xdebugger.XDebuggerUtil
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpoint
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointProperties
|
||||
import com.intellij.xdebugger.breakpoints.XBreakpointType
|
||||
import com.intellij.xdebugger.breakpoints.XLineBreakpointType
|
||||
import com.intellij.xdebugger.breakpoints.*
|
||||
import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties
|
||||
import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.getLineNumber
|
||||
import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpoint
|
||||
import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpointType
|
||||
import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinLineBreakpointType
|
||||
import org.jetbrains.kotlin.idea.debugger.stepping.*
|
||||
import org.jetbrains.kotlin.idea.test.JetJdkAndLibraryProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
@@ -261,49 +264,68 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
|
||||
}
|
||||
|
||||
override fun createBreakpoints(file: PsiFile?) {
|
||||
super.createBreakpoints(file)
|
||||
|
||||
if (file == null) return
|
||||
|
||||
val document = PsiDocumentManager.getInstance(myProject).getDocument(file) ?: return
|
||||
val document = runReadAction { PsiDocumentManager.getInstance(myProject).getDocument(file) } ?: return
|
||||
val breakpointManager = XDebuggerManager.getInstance(myProject).getBreakpointManager()
|
||||
val breakpointType = javaClass<KotlinFieldBreakpointType>() as Class<out XBreakpointType<XBreakpoint<XBreakpointProperties<*>>, XBreakpointProperties<*>>>
|
||||
val type = XDebuggerUtil.getInstance().findBreakpointType<XBreakpoint<XBreakpointProperties<*>>>(breakpointType) as KotlinFieldBreakpointType
|
||||
val kotlinFieldBreakpointType = findBreakpointType(KotlinFieldBreakpointType::class.java)
|
||||
val kotlinLineBreakpointType = findBreakpointType(KotlinLineBreakpointType::class.java)
|
||||
val virtualFile = file.getVirtualFile()
|
||||
|
||||
val runnable = {
|
||||
var offset = -1;
|
||||
while (true) {
|
||||
val fileText = document.getText()
|
||||
offset = fileText.indexOf("FieldWatchpoint!", offset + 1)
|
||||
offset = fileText.indexOf("point!", offset + 1)
|
||||
if (offset == -1) break
|
||||
|
||||
val commentLine = document.getLineNumber(offset)
|
||||
|
||||
val comment = fileText.substring(document.getLineStartOffset(commentLine), document.getLineEndOffset(commentLine))
|
||||
val comment = fileText.substring(document.getLineStartOffset(commentLine), document.getLineEndOffset(commentLine)).trim()
|
||||
|
||||
val lineIndex = commentLine + 1
|
||||
val fieldName = comment.substringAfter("//FieldWatchpoint! (").substringBefore(")")
|
||||
|
||||
if (!type.canPutAt(virtualFile, lineIndex, myProject)) continue
|
||||
|
||||
val xBreakpoint = runWriteAction {
|
||||
breakpointManager.addLineBreakpoint(
|
||||
type as XLineBreakpointType<XBreakpointProperties<*>>,
|
||||
virtualFile.getUrl(),
|
||||
if (comment.startsWith("//FieldWatchpoint!")) {
|
||||
val javaBreakpoint = createBreakpointOfType(
|
||||
breakpointManager,
|
||||
kotlinFieldBreakpointType as XLineBreakpointType<XBreakpointProperties<*>>,
|
||||
lineIndex,
|
||||
type.createBreakpointProperties(virtualFile, lineIndex)
|
||||
)
|
||||
virtualFile)
|
||||
if (javaBreakpoint is KotlinFieldBreakpoint) {
|
||||
val fieldName = comment.substringAfter("//FieldWatchpoint! (").substringBefore(")")
|
||||
javaBreakpoint.setFieldName(fieldName)
|
||||
javaBreakpoint.setWatchAccess(fileText.getValueForSetting("WATCH_FIELD_ACCESS", true))
|
||||
javaBreakpoint.setWatchModification(fileText.getValueForSetting("WATCH_FIELD_MODIFICATION", true))
|
||||
javaBreakpoint.setWatchInitialization(fileText.getValueForSetting("WATCH_FIELD_INITIALISATION", false))
|
||||
BreakpointManager.addBreakpoint(javaBreakpoint)
|
||||
println("KotlinFieldBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1}", ProcessOutputTypes.SYSTEM)
|
||||
}
|
||||
}
|
||||
else if (comment.startsWith("//Breakpoint!")) {
|
||||
val javaBreakpoint = createBreakpointOfType(
|
||||
breakpointManager,
|
||||
kotlinLineBreakpointType as XLineBreakpointType<XBreakpointProperties<*>>,
|
||||
lineIndex,
|
||||
virtualFile)
|
||||
if (javaBreakpoint is LineBreakpoint<*>) {
|
||||
|
||||
val javaBreakpoint = BreakpointManager.getJavaBreakpoint(xBreakpoint)
|
||||
if (javaBreakpoint is KotlinFieldBreakpoint) {
|
||||
javaBreakpoint.setFieldName(fieldName)
|
||||
javaBreakpoint.setWatchAccess(fileText.getValueForSetting("WATCH_FIELD_ACCESS", true))
|
||||
javaBreakpoint.setWatchModification(fileText.getValueForSetting("WATCH_FIELD_MODIFICATION", true))
|
||||
javaBreakpoint.setWatchInitialization(fileText.getValueForSetting("WATCH_FIELD_INITIALISATION", false))
|
||||
BreakpointManager.addBreakpoint(javaBreakpoint)
|
||||
println("KotlinFieldBreakpoint created at ${file.getVirtualFile().getName()}:${lineIndex + 1}", ProcessOutputTypes.SYSTEM)
|
||||
if (comment.contains("(")) {
|
||||
val ordinal = comment.substringAfter("//Breakpoint! (").substringBefore(")").toInt()
|
||||
|
||||
val properties = javaBreakpoint.xBreakpoint.properties as? JavaLineBreakpointProperties ?: continue
|
||||
properties.lambdaOrdinal = ordinal
|
||||
|
||||
BreakpointManager.addBreakpoint(javaBreakpoint)
|
||||
println("LineBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1} lambdaOrdinal = $ordinal", ProcessOutputTypes.SYSTEM)
|
||||
}
|
||||
else {
|
||||
BreakpointManager.addBreakpoint(javaBreakpoint)
|
||||
println("LineBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1}", ProcessOutputTypes.SYSTEM)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw AssertionError("Cannot create breakpoint at line ${lineIndex + 1}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,6 +338,29 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createBreakpointOfType(
|
||||
breakpointManager: XBreakpointManager,
|
||||
breakpointType: XLineBreakpointType<XBreakpointProperties<*>>,
|
||||
lineIndex: Int,
|
||||
virtualFile: VirtualFile
|
||||
): Breakpoint<out JavaBreakpointProperties<*>>? {
|
||||
if (!breakpointType.canPutAt(virtualFile, lineIndex, myProject)) return null
|
||||
val xBreakpoint = runWriteAction {
|
||||
breakpointManager.addLineBreakpoint(
|
||||
breakpointType,
|
||||
virtualFile.url,
|
||||
lineIndex,
|
||||
breakpointType.createBreakpointProperties(virtualFile, lineIndex)
|
||||
)
|
||||
}
|
||||
return BreakpointManager.getJavaBreakpoint(xBreakpoint)
|
||||
}
|
||||
|
||||
private inline fun <reified T> findBreakpointType(javaClass: Class<T>): T {
|
||||
val kotlinFieldBreakpointTypeClass = javaClass as Class<out XBreakpointType<XBreakpoint<XBreakpointProperties<*>>, XBreakpointProperties<*>>>
|
||||
return XDebuggerUtil.getInstance().findBreakpointType<XBreakpoint<XBreakpointProperties<*>>>(kotlinFieldBreakpointTypeClass) as T
|
||||
}
|
||||
|
||||
protected fun createAdditionalBreakpoints(fileText: String) {
|
||||
val breakpoints = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// ADDITIONAL_BREAKPOINT: ")
|
||||
for (breakpoint in breakpoints) {
|
||||
|
||||
+12
@@ -688,6 +688,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
doMultipleBreakpointsTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleBreakpointsAtLine.kt")
|
||||
public void testMultipleBreakpointsAtLine() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/multipleBreakpointsAtLine.kt");
|
||||
doMultipleBreakpointsTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whenEntry.kt")
|
||||
public void testWhenEntry() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/whenEntry.kt");
|
||||
@@ -706,6 +712,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
doMultipleBreakpointsTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withoutBodyProperties2.kt")
|
||||
public void testWithoutBodyProperties2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/withoutBodyProperties2.kt");
|
||||
doMultipleBreakpointsTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withoutBodyTypeParameters.kt")
|
||||
public void testWithoutBodyTypeParameters() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/withoutBodyTypeParameters.kt");
|
||||
|
||||
Reference in New Issue
Block a user