Debugger: breakpoints in library source files

This commit is contained in:
Natalia Ukhorskaya
2014-08-19 12:23:40 +04:00
parent 91f7f2479d
commit 453592edf4
21 changed files with 403 additions and 11 deletions
@@ -69,10 +69,15 @@ public class PackagePartClassUtils {
@NotNull
public static String getPackagePartInternalName(@NotNull JetFile file) {
FqName fqName = getPackagePartFqName(getPackageClassFqName(file.getPackageFqName()), file.getVirtualFile());
FqName fqName = getPackagePartFqName(file);
return JvmClassName.byFqNameWithoutInnerClasses(fqName).getInternalName();
}
@NotNull
public static FqName getPackagePartFqName(@NotNull JetFile file) {
return getPackagePartFqName(getPackageClassFqName(file.getPackageFqName()), file.getVirtualFile());
}
@NotNull
public static FqName getPackagePartFqName(@NotNull DeserializedCallableMemberDescriptor callable) {
FqName packageFqName = ((PackageFragmentDescriptor) callable.getContainingDeclaration()).getFqName();
@@ -565,7 +565,7 @@ fun main(args: Array<String>) {
testClass(javaClass<AbstractKotlinEvaluateExpressionTest>()) {
model("debugger/tinyApp/src/evaluate/singleBreakpoint", testMethod = "doSingleBreakpointTest")
model("debugger/tinyApp/src/evaluate/multipleBreakpoints", testMethod = "doMultipleBreakpointsTest")
model("debugger/tinyApp/src/evaluate/multipleBreakpoints", testMethod = "doMultipleBreakpointsTest", recursive = true)
model("debugger/tinyApp/src/evaluate/frame", testMethod = "doSingleBreakpointTest")
}
@@ -45,4 +45,7 @@ public class JetClsFile(val provider: JetClassFileViewProvider) : ClsFileImpl(pr
fun getRenderedDescriptorsToRange(): Map<String, TextRange> {
return provider.decompiledText.renderedDescriptorsToRange
}
override fun getTextLength() = decompiledFile.getTextLength()
override fun getText() = decompiledFile.getText()
}
@@ -16,6 +16,8 @@
package org.jetbrains.jet.plugin.debugger;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.intellij.debugger.NoDataException;
import com.intellij.debugger.PositionManager;
import com.intellij.debugger.SourcePosition;
@@ -23,6 +25,7 @@ import com.intellij.debugger.engine.DebugProcess;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.libraries.LibraryUtil;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -53,6 +56,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.lang.InlineStrategy;
import org.jetbrains.jet.lang.types.lang.InlineUtil;
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies;
import org.jetbrains.jet.plugin.util.DebuggerUtils;
import org.jetbrains.org.objectweb.asm.Type;
@@ -137,9 +141,9 @@ public class JetPositionManager implements PositionManager {
@SuppressWarnings("unchecked")
public void run() {
JetFile file = (JetFile) sourcePosition.getFile();
JetTypeMapper typeMapper = prepareTypeMapper(file);
result.set(getClassNameForElement(sourcePosition.getElementAt(), typeMapper, file));
boolean isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null;
JetTypeMapper typeMapper = !isInLibrary ? prepareTypeMapper(file) : createTypeMapperForLibraryFile(sourcePosition);
result.set(getClassNameForElement(sourcePosition.getElementAt(), typeMapper, file, isInLibrary));
}
});
@@ -148,7 +152,12 @@ public class JetPositionManager implements PositionManager {
}
@SuppressWarnings("unchecked")
private static String getClassNameForElement(@Nullable PsiElement notPositionedElement, @NotNull JetTypeMapper typeMapper, @NotNull JetFile file) {
public static String getClassNameForElement(
@Nullable PsiElement notPositionedElement,
@NotNull JetTypeMapper typeMapper,
@NotNull JetFile file,
boolean isInLibrary
) {
PsiElement element = PsiTreeUtil.getParentOfType(notPositionedElement, JetClassOrObject.class, JetFunctionLiteral.class, JetNamedFunction.class);
if (element instanceof JetClassOrObject) {
@@ -156,7 +165,7 @@ public class JetPositionManager implements PositionManager {
}
else if (element instanceof JetFunctionLiteral) {
if (isInlinedLambda((JetFunctionLiteral) element, typeMapper.getBindingContext())) {
return getClassNameForElement(element.getParent(), typeMapper, file);
return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary);
} else {
Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), ((JetFunctionLiteral) element));
return asmType.getInternalName();
@@ -173,10 +182,22 @@ public class JetPositionManager implements PositionManager {
}
}
if (isInLibrary) {
JetElement elementAtForLibraryFile = getElementToCreateTypeMapperForLibraryFile(notPositionedElement);
assert elementAtForLibraryFile != null : "Couldn't find element at breakpoint for library file " + file.getName()
+ (notPositionedElement == null ? "" : ", notPositionedElement = " + JetPsiUtil.getElementTextWithContext( (JetElement) notPositionedElement));
return DebuggerPackage.findPackagePartInternalNameForLibraryFile(elementAtForLibraryFile);
}
return PackagePartClassUtils.getPackagePartInternalName(file);
}
@Nullable
private static JetElement getElementToCreateTypeMapperForLibraryFile(@Nullable PsiElement notPositionedElement) {
return PsiTreeUtil.getParentOfType(notPositionedElement, JetElement.class);
}
@Nullable
private static String getJvmInternalNameForImpl(JetTypeMapper typeMapper, JetClassOrObject jetClass) {
ClassDescriptor classDescriptor = typeMapper.getBindingContext().get(BindingContext.CLASS, jetClass);
@@ -191,6 +212,20 @@ public class JetPositionManager implements PositionManager {
return typeMapper.mapClass(classDescriptor).getInternalName();
}
private static JetTypeMapper createTypeMapperForLibraryFile(@NotNull SourcePosition position) {
JetElement element = getElementToCreateTypeMapperForLibraryFile(position.getElementAt());
ResolveSessionForBodies resolveSession = ResolvePackage.getLazyResolveSession(element);
JetFile file = (JetFile) position.getFile();
GenerationState state = new GenerationState(file.getProject(), ClassBuilderFactories.THROW_EXCEPTION,
resolveSession.getModuleDescriptor(),
resolveSession.resolveToElement(element),
Collections.singletonList(file)
);
state.beforeCompile();
return state.getTypeMapper();
}
private JetTypeMapper prepareTypeMapper(final JetFile file) {
final FqName fqName = file.getPackageFqName();
CachedValue<JetTypeMapper> value = myTypeMappers.get(fqName);
@@ -0,0 +1,142 @@
/*
* Copyright 2010-2014 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.
*/
package org.jetbrains.jet.plugin.debugger
import com.intellij.psi.search.FilenameIndex
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.descriptors.serialization.JavaProtoBuf
import org.jetbrains.jet.renderer.DescriptorRenderer
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
import com.intellij.psi.PsiElement
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import com.intellij.openapi.roots.libraries.LibraryUtil
import com.intellij.openapi.module.impl.scopes.LibraryScope
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
import org.jetbrains.jet.lang.resolve.BindingContext
import com.intellij.openapi.module.impl.scopes.JdkScope
import com.intellij.openapi.roots.JdkOrderEntry
import org.jetbrains.jet.lang.psi.JetPsiUtil
import org.jetbrains.jet.lang.resolve.java.JvmClassName
private val LOG = Logger.getInstance("org.jetbrains.jet.plugin.debugger")
/**
* This method finds class name for top-level declaration in source file attached to library.
* The problem is that package-part class file has hash in className and it depends on machine where library was built,
* so we couldn't predict it.
* 1. find all .class files with package-part prefix, if there is one - return it
* 2. find all descriptors with same signature, if there is one - return it
* 3. else -> return null, because it means that there is more than one function with same signature in project
*/
fun findPackagePartInternalNameForLibraryFile(elementAt: JetElement): String? {
val topLevelDeclaration = PsiTreeUtil.getTopmostParentOfType(elementAt, javaClass<JetDeclaration>())
if (topLevelDeclaration == null) {
reportError(elementAt, null)
return null
}
val packagePartFile = findPackagePartFileNamesForElement(topLevelDeclaration).singleOrNull()
if (packagePartFile != null) return packagePartFile
val resolveSession = topLevelDeclaration.getLazyResolveSession()
val descriptor = resolveSession.resolveToDescriptor(topLevelDeclaration)
if (descriptor !is CallableDescriptor) return null
val packageFqName = topLevelDeclaration.getContainingJetFile().getPackageFqName()
val packageDescriptor = resolveSession.getModuleDescriptor().getPackage(packageFqName)
if (packageDescriptor == null) {
reportError(topLevelDeclaration, descriptor)
return null
}
val descFromSourceText = render(descriptor)
val descriptors: Collection<CallableDescriptor> = when (descriptor) {
is FunctionDescriptor -> packageDescriptor.getMemberScope().getFunctions(descriptor.getName())
is PropertyDescriptor -> packageDescriptor.getMemberScope().getProperties(descriptor.getName())
else -> {
reportError(topLevelDeclaration, descriptor)
listOf()
}
}
val deserializedDescriptor = descriptors
.filterIsInstance(javaClass<DeserializedCallableMemberDescriptor>())
.filter { render(it) == descFromSourceText }
.singleOrNull()
if (deserializedDescriptor == null) {
reportError(topLevelDeclaration, descriptor)
return null
}
val proto = deserializedDescriptor.proto
if (proto.hasExtension(JavaProtoBuf.implClassName)) {
val name = deserializedDescriptor.nameResolver.getName(proto.getExtension(JavaProtoBuf.implClassName)!!)
return JvmClassName.byFqNameWithoutInnerClasses(packageFqName.child(name)).getInternalName()
}
return null
}
private fun findPackagePartFileNamesForElement(elementAt: JetElement): List<String> {
val project = elementAt.getProject()
val file = elementAt.getContainingJetFile()
val packagePartName = PackagePartClassUtils.getPackagePartFqName(file).shortName().asString()
val packagePartNameWoHash = packagePartName.substring(0, packagePartName.lastIndexOf("-"))
val libraryEntry = LibraryUtil.findLibraryEntry(file.getVirtualFile(), project)
val scope = if (libraryEntry is LibraryOrderEntry){
LibraryScope(project, libraryEntry.getLibrary() ?: throw AssertionError("Cannot find library for file ${file.getVirtualFile()?.getPath()}"))
}
else {
JdkScope(project, libraryEntry as JdkOrderEntry)
}
val packagePartFiles = FilenameIndex.getAllFilesByExt(project, "class", scope)
.filter { it.getName().startsWith(packagePartNameWoHash) }
.map {
val packageFqName = file.getPackageFqName()
if (packageFqName.isRoot()) {
it.getNameWithoutExtension()
} else {
"${packageFqName.asString()}.${it.getNameWithoutExtension()}"
}
}
return packagePartFiles
}
private fun render(desc: DeclarationDescriptor) = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(desc)
private fun reportError(element: JetElement, descriptor: CallableDescriptor?) {
LOG.error("Couldn't calculate class name for element in library scope:\n" +
JetPsiUtil.getElementTextWithContext(element) +
if (descriptor != null) "\ndescriptor = ${render(descriptor)}" else ""
)
}
@@ -0,0 +1,6 @@
package customLib.breakpointOnLocalProperty
public fun breakpointOnLocalPropertyFun(): Int {
val a = 1
return 1
}
@@ -0,0 +1,5 @@
package customLib.breakpointOnLocalProperty
public fun breakpointOnLocalPropertyFun2(): Int {
return 1
}
@@ -0,0 +1,4 @@
package customLib.property
public val foo: Int =
1
@@ -0,0 +1,5 @@
package customLib.property
public fun someFun(): Int {
return 1
}
@@ -0,0 +1,17 @@
LineBreakpoint created at 1.kt:3
LineBreakpoint created at 1.kt:3
LineBreakpoint created at 1.kt:3
LineBreakpoint created at 1.kt:3
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! customLibClassName.CustomLibClassNamePackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
1.kt:3
Compile bytecode for 1 + 1
1.kt:3
Compile bytecode for 1 + 2
1.kt:3
Compile bytecode for 1 + 3
1.kt:3
Compile bytecode for 1 + 4
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -0,0 +1,8 @@
LineBreakpoint created at Delegation.kt:48
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stdlibDelegatedProperty.StdlibDelegatedPropertyPackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Delegation.kt:48
Compile bytecode for value.toString()
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -0,0 +1,8 @@
LineBreakpoint created at Ranges.kt:7
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stdlibRange.StdlibRangePackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Ranges.kt:7
Compile bytecode for start <= item
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -0,0 +1,8 @@
LineBreakpoint created at StringsJVM.kt:163
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stdlibSlice.StdlibSlicePackage
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
StringsJVM.kt:163
Compile bytecode for range.start
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -0,0 +1,24 @@
package customLibClassName
fun main(args: Array<String>) {
customLib.oneFunSameFileName.oneFunSameFileNameFun()
customLib.twoFunDifferentSignature.twoFunDifferentSignatureFun()
customLib.property.foo
customLib.breakpointOnLocalProperty.breakpointOnLocalPropertyFun()
}
// ADDITIONAL_BREAKPOINT: 1.kt:public fun oneFunSameFileNameFun(): Int {
// EXPRESSION: 1 + 1
// RESULT: 2: I
// ADDITIONAL_BREAKPOINT: 1.kt:public fun twoFunDifferentSignatureFun(): Int {
// EXPRESSION: 1 + 2
// RESULT: 3: I
// ADDITIONAL_BREAKPOINT: 1.kt:public val foo: Int =
// EXPRESSION: 1 + 3
// RESULT: 4: I
// ADDITIONAL_BREAKPOINT: 1.kt:public fun breakpointOnLocalPropertyFun(): Int {
// EXPRESSION: 1 + 4
// RESULT: 5: I
@@ -0,0 +1,15 @@
package stdlibDelegatedProperty
import kotlin.properties.Delegates
var prop: Int by Delegates.notNull()
fun main(args: Array<String>) {
prop = 3
val a = prop
}
// ADDITIONAL_BREAKPOINT: Delegation.kt:public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
// EXPRESSION: value.toString()
// RESULT: "3": Ljava/lang/String;
@@ -0,0 +1,14 @@
package stdlibRange
fun main(args: Array<String>) {
A().rangeTo(A()).contains(A())
}
class A: Comparable<A> {
override fun compareTo(other: A) = 0
}
// ADDITIONAL_BREAKPOINT: Ranges.kt:override fun contains(item: T): Boolean {
// EXPRESSION: start <= item
// RESULT: 1: Z
@@ -0,0 +1,11 @@
package stdlibSlice
fun main(args: Array<String>) {
val c: CharSequence = "CharSequence"
c.slice(0..1)
}
// ADDITIONAL_BREAKPOINT: StringsJVM.kt:CharSequence.slice(range: IntRange): CharSequence
// EXPRESSION: range.start
// RESULT: 0: I
@@ -210,6 +210,6 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
@Override
protected Sdk getTestProjectJdk() {
return PluginTestCaseBase.jdkFromIdeaHome();
return PluginTestCaseBase.fullJdk();
}
}
@@ -53,7 +53,11 @@ import com.intellij.debugger.ui.impl.watch.ThisDescriptorImpl
import com.intellij.debugger.ui.tree.FieldDescriptor
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.util.Computable
import com.intellij.psi.search.FilenameIndex
import com.intellij.psi.PsiManager
import com.intellij.debugger.DebuggerManagerEx
import com.intellij.psi.PsiDocumentManager
import com.intellij.openapi.application.ModalityState
public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestCase() {
private val logger = Logger.getLogger(javaClass<KotlinEvaluateExpressionCache>())!!
@@ -87,6 +91,8 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC
val file = File(path)
val fileText = FileUtil.loadFile(file, true)
createAdditionalBreakpoints(fileText)
val shouldPrintFrame = InTextDirectivesUtils.isDirectiveDefined(fileText, "// PRINT_FRAME")
val expressions = loadTestDirectivesPairs(fileText, "// EXPRESSION: ", "// RESULT: ")
@@ -127,10 +133,15 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC
}
fun doMultipleBreakpointsTest(path: String) {
val expressions = loadTestDirectivesPairs(FileUtil.loadFile(File(path), true), "// EXPRESSION: ", "// RESULT: ")
val file = File(path)
val fileText = FileUtil.loadFile(file, true)
createAdditionalBreakpoints(fileText)
createDebugProcess(path)
val expressions = loadTestDirectivesPairs(fileText, "// EXPRESSION: ", "// RESULT: ")
val exceptions = linkedMapOf<String, Throwable>()
for ((expression, expected) in expressions) {
mayThrow(exceptions, expression) {
@@ -150,6 +161,42 @@ public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestC
finish()
}
private fun createAdditionalBreakpoints(fileText: String) {
val breakpoints = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileText, "// ADDITIONAL_BREAKPOINT: ")
for (breakpoint in breakpoints) {
val position = breakpoint.split(".kt:")
assert(position.size == 2, "Couldn't parse position from test directive: directive = ${breakpoint}")
createBreakpoint(position[0], position[1])
}
}
private fun createBreakpoint(fileName: String, lineMarker: String) {
val project = getProject()!!
val sourceFiles = FilenameIndex.getAllFilesByExt(project, "kt").filter {
it.getName().contains(fileName) &&
it.contentsToByteArray().toString("UTF-8").contains(lineMarker)
}
assert(sourceFiles.size() == 1, "One source file should be found: name = $fileName, sourceFiles = $sourceFiles")
val runnable = Runnable() {
val psiSourceFile = PsiManager.getInstance(project).findFile(sourceFiles.first())!!
val breakpointManager = DebuggerManagerEx.getInstanceEx(project)?.getBreakpointManager()!!
val document = PsiDocumentManager.getInstance(project).getDocument(psiSourceFile)!!
val index = psiSourceFile.getText()!!.indexOf(lineMarker)
val lineNumber = document.getLineNumber(index) + 1
val breakpoint = breakpointManager.addLineBreakpoint(document, lineNumber)
if (breakpoint != null) {
println("LineBreakpoint created at " + psiSourceFile.getName() + ":" + lineNumber, ProcessOutputTypes.SYSTEM);
}
}
DebuggerInvocationUtil.invokeAndWait(project, runnable, ModalityState.defaultModalityState())
}
private fun SuspendContextImpl.printFrame() {
val tree = FrameVariablesTree(getProject()!!)
Disposer.register(getTestRootDisposable()!!, tree);
@@ -143,6 +143,7 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
}
@TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints")
@InnerTestClasses({MultipleBreakpoints.Library.class})
public static class MultipleBreakpoints extends AbstractKotlinEvaluateExpressionTest {
public void testAllFilesPresentInMultipleBreakpoints() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -178,6 +179,40 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/withoutBodyTypeParameters.kt");
}
@TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/library")
public static class Library extends AbstractKotlinEvaluateExpressionTest {
public void testAllFilesPresentInLibrary() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/library"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("customLibClassName.kt")
public void testCustomLibClassName() throws Exception {
doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/library/customLibClassName.kt");
}
@TestMetadata("stdlibDelegatedProperty.kt")
public void testStdlibDelegatedProperty() throws Exception {
doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/library/stdlibDelegatedProperty.kt");
}
@TestMetadata("stdlibRange.kt")
public void testStdlibRange() throws Exception {
doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/library/stdlibRange.kt");
}
@TestMetadata("stdlibSlice.kt")
public void testStdlibSlice() throws Exception {
doMultipleBreakpointsTest("idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/library/stdlibSlice.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("MultipleBreakpoints");
suite.addTestSuite(MultipleBreakpoints.class);
suite.addTestSuite(Library.class);
return suite;
}
}
@TestMetadata("idea/testData/debugger/tinyApp/src/evaluate/frame")
@@ -261,7 +296,7 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
public static Test suite() {
TestSuite suite = new TestSuite("KotlinEvaluateExpressionTestGenerated");
suite.addTestSuite(SingleBreakpoint.class);
suite.addTestSuite(MultipleBreakpoints.class);
suite.addTest(MultipleBreakpoints.innerSuite());
suite.addTestSuite(Frame.class);
return suite;
}