Support multiple breakpoints at one line (especially for lambdas)

This commit is contained in:
Natalia Ukhorskaya
2015-10-27 10:40:07 +03:00
parent c071bf5c63
commit e534636f03
20 changed files with 452 additions and 83 deletions
@@ -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.analyzeAndGetResult
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils 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.decompiler.JetClsFile
import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
import org.jetbrains.kotlin.idea.util.DebuggerUtils 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.BindingContext
import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.kotlin.utils.toReadOnlyList
import java.util.* import java.util.*
import com.intellij.debugger.engine.DebuggerUtils as JDebuggerUtils 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) val end = CodeInsightUtils.getEndLineOffset(file, lineNumber)
if (start == null || end == null) return null if (start == null || end == null) return null
val literalsOrFunctions = CodeInsightUtils. val literalsOrFunctions = getLambdasAtLineIfAny(file, lineNumber)
findElementsOfClassInRange(file, start, end, KtFunctionLiteral::class.java, KtNamedFunction::class.java).
filter { KtPsiUtil.getParentCallIfPresent(it as KtExpression) != null }
if (literalsOrFunctions.isEmpty()) return null; if (literalsOrFunctions.isEmpty()) return null;
val isInLibrary = LibraryUtil.findLibraryEntry(file.virtualFile, file.project) != 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 val currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName)).internalName
for (literal in literalsOrFunctions) { for (literal in literalsOrFunctions) {
val functionLiteral = literal as KtFunction if (isInlinedLambda(literal, typeMapper.bindingContext)) {
if (isInlinedLambda(functionLiteral, typeMapper.bindingContext)) { if (isInsideInlineArgument(literal, location, myDebugProcess as DebugProcessImpl)) {
if (isInsideInlineArgument(functionLiteral, location, myDebugProcess as DebugProcessImpl)) { return literal
return functionLiteral
} }
continue continue
} }
val internalClassName = getInternalClassNameForElement(literal.firstChild, typeMapper, file, isInLibrary).className val internalClassName = getInternalClassNameForElement(literal.firstChild, typeMapper, file, isInLibrary).className
if (internalClassName == currentLocationClassName) { 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> { private fun classNameForPositionAndInlinedOnes(sourcePosition: SourcePosition): List<String> {
val result = arrayListOf<String>() val result = hashSetOf<String>()
val name = classNameForPosition(sourcePosition) val name = classNameForPosition(sourcePosition)
if (name != null) { if (name != null) {
result.add(name) result.add(name)
@@ -240,7 +238,22 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult
val list = findInlinedCalls(sourcePosition.elementAt, sourcePosition.file) val list = findInlinedCalls(sourcePosition.elementAt, sourcePosition.file)
result.addAll(list) 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? { public fun classNameForPosition(sourcePosition: SourcePosition): String? {
@@ -17,17 +17,29 @@
package org.jetbrains.kotlin.idea.debugger.breakpoints; package org.jetbrains.kotlin.idea.debugger.breakpoints;
import com.intellij.debugger.SourcePosition; 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.JavaLineBreakpointType;
import com.intellij.debugger.ui.breakpoints.LineBreakpoint; import com.intellij.debugger.ui.breakpoints.LineBreakpoint;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil; 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.NotNull;
import org.jetbrains.annotations.Nullable; 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 org.jetbrains.kotlin.psi.KtFunction;
import javax.swing.*;
import java.util.List;
public class KotlinLineBreakpointType extends JavaLineBreakpointType { public class KotlinLineBreakpointType extends JavaLineBreakpointType {
public KotlinLineBreakpointType() { public KotlinLineBreakpointType() {
super("kotlin-line", "Kotlin Line Breakpoints"); super("kotlin-line", "Kotlin Line Breakpoints");
@@ -35,11 +47,16 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType {
@Override @Override
public boolean matchesPosition(@NotNull LineBreakpoint<?> breakpoint, @NotNull SourcePosition position) { 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); PsiElement containingMethod = getContainingMethod(breakpoint);
if (containingMethod == null) return false; if (containingMethod == null) return false;
return inTheMethod(position, containingMethod); return inTheMethod(position, containingMethod);
}
return true;
} }
@Override @Override
@@ -48,9 +65,34 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType {
SourcePosition position = breakpoint.getSourcePosition(); SourcePosition position = breakpoint.getSourcePosition();
if (position == null) return null; 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()); 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 @Nullable
public static PsiElement getContainingMethod(@Nullable PsiElement elem) { public static PsiElement getContainingMethod(@Nullable PsiElement elem) {
//noinspection unchecked //noinspection unchecked
@@ -68,5 +110,42 @@ public class KotlinLineBreakpointType extends JavaLineBreakpointType {
return BreakpointTypeUtilsKt.canPutAt(file, line, project, getClass()); 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 package org.jetbrains.kotlin.idea.debugger.breakpoints
import com.intellij.debugger.SourcePosition
import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType
import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile 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.psi.util.PsiTreeUtil
import com.intellij.xdebugger.XDebuggerUtil 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.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.resolve.analyze 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.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import java.util.*
fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass: Class<*>): Boolean { fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass: Class<*>): Boolean {
val psiFile = PsiManager.getInstance(project).findFile(file) val psiFile = PsiManager.getInstance(project).findFile(file)
@@ -80,4 +93,73 @@ fun canPutAt(file: VirtualFile, line: Int, project: Project, breakpointTypeClass
return result == 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 private val myLastStatementLine: Int
init { init {
if (lambda.isMultiLine()) { val body = lambda.bodyExpression
if (body != null && lambda.isMultiLine()) {
var firstStatementPosition: SourcePosition? = null var firstStatementPosition: SourcePosition? = null
var lastStatementPosition: SourcePosition? = null var lastStatementPosition: SourcePosition? = null
val body = lambda.bodyExpression as KtBlockExpression val statements = (body as? KtBlockExpression)?.statements ?: listOf(body)
val statements = body.statements
if (statements.isNotEmpty()) { if (statements.isNotEmpty()) {
firstStatementPosition = SourcePosition.createFromElement(statements.first()) firstStatementPosition = SourcePosition.createFromElement(statements.first())
if (firstStatementPosition != null) { 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 !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' Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
ceAnonymousObjectCapturedInClosure.kt:7 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 -1
View File
@@ -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 !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' Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
severalFunLiterals.kt:6 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 !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' Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
severalFunLiteralsInClass.kt:20 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 !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' Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
smartStepIntoInlinedFunLiteral.kt:6 smartStepIntoInlinedFunLiteral.kt:6
smartStepIntoInlinedFunLiteral.kt:9 smartStepIntoInlinedFunLiteral.kt:11
smartStepIntoInlinedFunLiteral.kt:10 smartStepIntoInlinedFunLiteral.kt:12
smartStepIntoInlinedFunLiteral.kt:13 smartStepIntoInlinedFunLiteral.kt:17
smartStepIntoInlinedFunLiteral.kt:14
smartStepIntoInlinedFunLiteral.kt:18 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' Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0 Process finished with exit code 0
@@ -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 !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' Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
smartStepIntoInlinedFunctionalExpression.kt:6 smartStepIntoInlinedFunctionalExpression.kt:6
smartStepIntoInlinedFunctionalExpression.kt:9 smartStepIntoInlinedFunctionalExpression.kt:11
smartStepIntoInlinedFunctionalExpression.kt:10 smartStepIntoInlinedFunctionalExpression.kt:12
smartStepIntoInlinedFunctionalExpression.kt:13 smartStepIntoInlinedFunctionalExpression.kt:17
smartStepIntoInlinedFunctionalExpression.kt:14
smartStepIntoInlinedFunctionalExpression.kt:18 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' Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0 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 !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' Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
twoLambdasOnOneLineFirst.kt:9 twoLambdasOnOneLineFirst.kt:9
@@ -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
}
}
@@ -3,7 +3,7 @@ package ceAnonymousObjectCapturedInClosure
fun main(args: Array<String>) { fun main(args: Array<String>) {
val localObject = object { fun test() = 1 } val localObject = object { fun test() = 1 }
var localObjectVar = object { fun test() = 1 } var localObjectVar = object { fun test() = 1 }
//Breakpoint! //Breakpoint! (-1)
lambda { localObjectVar.test() } lambda { localObjectVar.test() }
} }
@@ -5,7 +5,7 @@ fun main(args: Array<String>) {
// EXPRESSION: it // EXPRESSION: it
// RESULT: 1: I // RESULT: 1: I
// STEP_INTO: 2 // STEP_INTO: 2
//Breakpoint! //Breakpoint! (-1)
a.foo { a }.foo { a } a.foo { a }.foo { a }
} }
@@ -2,7 +2,7 @@ package severalFunLiterals
fun main(args: Array<String>) { fun main(args: Array<String>) {
val myClass = MyClass() val myClass = MyClass()
//Breakpoint! //Breakpoint! (-1)
myClass.f1 { test() }.f2 { myClass.f1 { test() }.f2 {
test() test()
} }
@@ -16,7 +16,7 @@ class MyClass {
} }
fun inClass() { fun inClass() {
//Breakpoint! //Breakpoint! (-1)
f1 { test() }.f2 { f1 { test() }.f2 {
test() test()
} }
@@ -5,20 +5,31 @@ fun main(args: Array<String>) {
//Breakpoint! //Breakpoint!
val myClass = MyClass() val myClass = MyClass()
// STEP_OVER: 1
// SMART_STEP_INTO_BY_INDEX: 4
// smart step into f2.invoke(), one-line lambda // smart step into f2.invoke(), one-line lambda
myClass.f1 { test() } myClass.f1 { test() }
.f2 { test() } .f2 { test() }
// STEP_OVER: 1
// SMART_STEP_INTO_BY_INDEX: 2
// smart step into map.invoke(), multiline lambda // smart step into map.invoke(), multiline lambda
array.map { array.map {
it *2 it *2
} }
// STEP_OVER: 1
// SMART_STEP_INTO_BY_INDEX: 4
// smart step into filter.invoke() // smart step into filter.invoke()
array.map { it * 2 } array.map { it * 2 }
.filter { .filter {
it > 2 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 { class MyClass {
@@ -36,10 +47,3 @@ class MyClass {
} }
fun test() {} 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
@@ -5,20 +5,32 @@ fun main(args: Array<String>) {
//Breakpoint! //Breakpoint!
val myClass = MyClass() val myClass = MyClass()
// STEP_OVER: 1
// SMART_STEP_INTO_BY_INDEX: 4
// smart step into f2.invoke(), one-line lambda // smart step into f2.invoke(), one-line lambda
myClass.f1(fun () { test() }) myClass.f1(fun () { test() })
.f2(fun () { test() }) .f2(fun () { test() })
// STEP_OVER: 1
// SMART_STEP_INTO_BY_INDEX: 2
// smart step into map.invoke(), multiline lambda // smart step into map.invoke(), multiline lambda
array.map(fun (it): Int { array.map(fun (it): Int {
return it * 2 return it * 2
}) })
// STEP_OVER: 1
// SMART_STEP_INTO_BY_INDEX: 4
// smart step into filter.invoke() // smart step into filter.invoke()
array.map(fun (it): Int { return it * 2 }) array.map(fun (it): Int { return it * 2 })
.filter(fun (it): Boolean { .filter(fun (it): Boolean {
return it > 2 return it > 2
}) })
// STEP_OVER: 1
// SMART_STEP_INTO_BY_INDEX: 2
myClass.f3(fun () = myClass.f3 {
println()
})
} }
class MyClass { class MyClass {
@@ -33,13 +45,11 @@ class MyClass {
f1Param() f1Param()
return this return this
} }
inline fun f3(f1Param: () -> Unit): Unit {
test()
f1Param()
}
} }
fun test() {} 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
@@ -26,25 +26,28 @@ import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.impl.DebuggerContextImpl import com.intellij.debugger.impl.DebuggerContextImpl
import com.intellij.debugger.impl.PositionUtil import com.intellij.debugger.impl.PositionUtil
import com.intellij.debugger.settings.DebuggerSettings 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.BreakpointManager
import com.intellij.debugger.ui.breakpoints.LineBreakpoint
import com.intellij.execution.process.ProcessOutputTypes import com.intellij.execution.process.ProcessOutputTypes
import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.roots.JdkOrderEntry import com.intellij.openapi.roots.JdkOrderEntry
import com.intellij.openapi.roots.libraries.LibraryUtil import com.intellij.openapi.roots.libraries.LibraryUtil
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
import com.intellij.psi.search.FilenameIndex import com.intellij.psi.search.FilenameIndex
import com.intellij.xdebugger.XDebuggerManager import com.intellij.xdebugger.XDebuggerManager
import com.intellij.xdebugger.XDebuggerUtil import com.intellij.xdebugger.XDebuggerUtil
import com.intellij.xdebugger.breakpoints.XBreakpoint import com.intellij.xdebugger.breakpoints.*
import com.intellij.xdebugger.breakpoints.XBreakpointProperties import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties
import com.intellij.xdebugger.breakpoints.XBreakpointType import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties
import com.intellij.xdebugger.breakpoints.XLineBreakpointType
import org.jetbrains.kotlin.idea.core.refactoring.getLineNumber import org.jetbrains.kotlin.idea.core.refactoring.getLineNumber
import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpoint import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpoint
import org.jetbrains.kotlin.idea.debugger.breakpoints.KotlinFieldBreakpointType 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.debugger.stepping.*
import org.jetbrains.kotlin.idea.test.JetJdkAndLibraryProjectDescriptor import org.jetbrains.kotlin.idea.test.JetJdkAndLibraryProjectDescriptor
import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.util.application.runReadAction
@@ -261,49 +264,68 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() {
} }
override fun createBreakpoints(file: PsiFile?) { override fun createBreakpoints(file: PsiFile?) {
super.createBreakpoints(file)
if (file == null) return 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 breakpointManager = XDebuggerManager.getInstance(myProject).getBreakpointManager()
val breakpointType = javaClass<KotlinFieldBreakpointType>() as Class<out XBreakpointType<XBreakpoint<XBreakpointProperties<*>>, XBreakpointProperties<*>>> val kotlinFieldBreakpointType = findBreakpointType(KotlinFieldBreakpointType::class.java)
val type = XDebuggerUtil.getInstance().findBreakpointType<XBreakpoint<XBreakpointProperties<*>>>(breakpointType) as KotlinFieldBreakpointType val kotlinLineBreakpointType = findBreakpointType(KotlinLineBreakpointType::class.java)
val virtualFile = file.getVirtualFile() val virtualFile = file.getVirtualFile()
val runnable = { val runnable = {
var offset = -1; var offset = -1;
while (true) { while (true) {
val fileText = document.getText() val fileText = document.getText()
offset = fileText.indexOf("FieldWatchpoint!", offset + 1) offset = fileText.indexOf("point!", offset + 1)
if (offset == -1) break if (offset == -1) break
val commentLine = document.getLineNumber(offset) 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 lineIndex = commentLine + 1
val fieldName = comment.substringAfter("//FieldWatchpoint! (").substringBefore(")")
if (!type.canPutAt(virtualFile, lineIndex, myProject)) continue if (comment.startsWith("//FieldWatchpoint!")) {
val javaBreakpoint = createBreakpointOfType(
val xBreakpoint = runWriteAction { breakpointManager,
breakpointManager.addLineBreakpoint( kotlinFieldBreakpointType as XLineBreakpointType<XBreakpointProperties<*>>,
type as XLineBreakpointType<XBreakpointProperties<*>>,
virtualFile.getUrl(),
lineIndex, 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 (comment.contains("(")) {
if (javaBreakpoint is KotlinFieldBreakpoint) { val ordinal = comment.substringAfter("//Breakpoint! (").substringBefore(")").toInt()
javaBreakpoint.setFieldName(fieldName)
javaBreakpoint.setWatchAccess(fileText.getValueForSetting("WATCH_FIELD_ACCESS", true)) val properties = javaBreakpoint.xBreakpoint.properties as? JavaLineBreakpointProperties ?: continue
javaBreakpoint.setWatchModification(fileText.getValueForSetting("WATCH_FIELD_MODIFICATION", true)) properties.lambdaOrdinal = ordinal
javaBreakpoint.setWatchInitialization(fileText.getValueForSetting("WATCH_FIELD_INITIALISATION", false))
BreakpointManager.addBreakpoint(javaBreakpoint) BreakpointManager.addBreakpoint(javaBreakpoint)
println("KotlinFieldBreakpoint created at ${file.getVirtualFile().getName()}:${lineIndex + 1}", ProcessOutputTypes.SYSTEM) 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) { protected fun createAdditionalBreakpoints(fileText: String) {
val breakpoints = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// ADDITIONAL_BREAKPOINT: ") val breakpoints = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// ADDITIONAL_BREAKPOINT: ")
for (breakpoint in breakpoints) { for (breakpoint in breakpoints) {
@@ -688,6 +688,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
doMultipleBreakpointsTest(fileName); 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") @TestMetadata("whenEntry.kt")
public void testWhenEntry() throws Exception { public void testWhenEntry() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/whenEntry.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/whenEntry.kt");
@@ -706,6 +712,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
doMultipleBreakpointsTest(fileName); 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") @TestMetadata("withoutBodyTypeParameters.kt")
public void testWithoutBodyTypeParameters() throws Exception { public void testWithoutBodyTypeParameters() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/withoutBodyTypeParameters.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/withoutBodyTypeParameters.kt");