diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java index 4ede2765c68..be8d0e23785 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java +++ b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java @@ -39,11 +39,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.codegen.AsmUtil; import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.JetTypeMapper; -import org.jetbrains.jet.lang.descriptors.ClassDescriptor; -import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage; @@ -208,6 +208,29 @@ public class JetPositionManager implements PositionManager { return asmType.getInternalName(); } } + else if (element instanceof JetClassInitializer) { + PsiElement parent = getElementToCalculateClassName(element.getParent()); + // Class-object initializer + if (parent instanceof JetObjectDeclaration && ((JetObjectDeclaration) parent).isClassObject()) { + return getClassNameForElement(parent.getParent(), typeMapper, file, isInLibrary); + } + return getClassNameForElement(element, typeMapper, file, isInLibrary); + } + else if (element instanceof JetProperty && (!((JetProperty) element).isTopLevel() || !isInLibrary)) { + if (isInPropertyAccessor(notPositionedElement)) { + JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class); + if (classOrObject != null) { + return getJvmInternalNameForImpl(typeMapper, classOrObject); + } + } + + VariableDescriptor descriptor = (VariableDescriptor) typeMapper.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); + if (!(descriptor instanceof PropertyDescriptor)) { + return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary); + } + + return getJvmInternalNameForPropertyOwner(typeMapper, (PropertyDescriptor) descriptor); + } else if (element instanceof JetNamedFunction) { PsiElement parent = getElementToCalculateClassName(element); if (parent instanceof JetClassOrObject) { @@ -230,14 +253,31 @@ public class JetPositionManager implements PositionManager { } @Nullable - private static JetNamedDeclaration getElementToCalculateClassName(@Nullable PsiElement notPositionedElement) { + private static JetDeclaration getElementToCalculateClassName(@Nullable PsiElement notPositionedElement) { //noinspection unchecked - return PsiTreeUtil.getParentOfType(notPositionedElement, JetClassOrObject.class, JetFunctionLiteral.class, JetNamedFunction.class); + return PsiTreeUtil.getParentOfType(notPositionedElement, + JetClassOrObject.class, + JetFunctionLiteral.class, JetNamedFunction.class, + JetProperty.class, + JetClassInitializer.class); + } + + @NotNull + public static String getJvmInternalNameForPropertyOwner(@NotNull JetTypeMapper typeMapper, @NotNull PropertyDescriptor descriptor) { + return typeMapper.mapOwner( + AsmUtil.isPropertyWithBackingFieldInOuterClass(descriptor) ? descriptor.getContainingDeclaration() : descriptor, + true) + .getInternalName(); + } + + private static boolean isInPropertyAccessor(@Nullable PsiElement element) { + //noinspection unchecked + return element instanceof JetPropertyAccessor || ((JetElement) PsiTreeUtil.getParentOfType(element, JetProperty.class, JetPropertyAccessor.class)) instanceof JetPropertyAccessor; } @Nullable - private static JetElement getElementToCreateTypeMapperForLibraryFile(@Nullable PsiElement notPositionedElement) { - return PsiTreeUtil.getParentOfType(notPositionedElement, JetElement.class); + private static JetElement getElementToCreateTypeMapperForLibraryFile(@Nullable PsiElement element) { + return element instanceof JetElement ? (JetElement) element : PsiTreeUtil.getParentOfType(element, JetElement.class); } @Nullable diff --git a/idea/testData/debugger/positionManager/classObject.kt b/idea/testData/debugger/positionManager/classObject.kt index 1abe83d493d..1a5c5c81864 100644 --- a/idea/testData/debugger/positionManager/classObject.kt +++ b/idea/testData/debugger/positionManager/classObject.kt @@ -1,7 +1,43 @@ class A { class object { - fun foo() { + + { + 1 + 1 // A + val a = 1 // A + fun foo() { + 1 // A\$object\$1 + } + } + + val prop = 1 // A + + val prop2: Int + get() { + val a = 1 + 1 // A\$object + return 1 // A\$object + } + + val prop3: Int + get() = 1 // A\$object + + fun foo() = 1 // A\$object + + fun foo2() { "" // A\$object + + val o = object { + val p = 1 // A\$object\$foo2\$o\$1 + val p2: Int + get() { + return 1 // A\$object\$foo2\$o\$1 + } + } } } } + +trait T { + class object { + val prop = 1 // T\$object + } +} diff --git a/idea/testData/debugger/tinyApp/customLibrary/simpleLibFile/simpleLibFile.kt b/idea/testData/debugger/tinyApp/customLibrary/simpleLibFile/simpleLibFile.kt index dccf55fc28e..4d60d4322eb 100644 --- a/idea/testData/debugger/tinyApp/customLibrary/simpleLibFile/simpleLibFile.kt +++ b/idea/testData/debugger/tinyApp/customLibrary/simpleLibFile/simpleLibFile.kt @@ -1,5 +1,5 @@ package customLib.simpleLibFile public fun foo() { - val a = 1 + 1 + 1 } diff --git a/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out b/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out index 5cf128319d7..bd9f545a74a 100644 --- a/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out +++ b/idea/testData/debugger/tinyApp/outs/frameSharedVarLocalVar.out @@ -21,8 +21,8 @@ inline fun foo(f: () -> Unit) { // EXPRESSION: var1 // RESULT: 1: I - frame = main():7, FrameSharedVarLocalVarPackage-@packagePartHASH {frameSharedVarLocalVar} - static = static = frameSharedVarLocalVar.FrameSharedVarLocalVarPackage-@packagePartHASH + frame = main():7, FrameSharedVarLocalVarPackage$@packagePartHASH {frameSharedVarLocalVar} + static = static = frameSharedVarLocalVar.FrameSharedVarLocalVarPackage$@packagePartHASH local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} local = var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1 field = element: int = 1 diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractJetPositionManagerTest.java b/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractJetPositionManagerTest.java index cfa87856232..c4f611073d0 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractJetPositionManagerTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/AbstractJetPositionManagerTest.java @@ -23,6 +23,7 @@ import com.intellij.debugger.PositionManager; import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.DebugProcessEvents; +import com.intellij.debugger.engine.DebugProcessImpl; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; @@ -62,6 +63,8 @@ public abstract class AbstractJetPositionManagerTest extends MultiFileTestCase { return PluginTestCaseBase.getTestDataPathBase(); } + private DebugProcessImpl debugProcess; + @NotNull @Override protected String getTestRoot() { @@ -111,7 +114,7 @@ public abstract class AbstractJetPositionManagerTest extends MultiFileTestCase { Map referencesByName = getReferenceMap(state.getFactory()); - DebugProcess debugProcess = createDebugProcess(referencesByName); + debugProcess = createDebugProcess(referencesByName); final PositionManager positionManager = createPositionManager(debugProcess, files, state); @@ -128,6 +131,15 @@ public abstract class AbstractJetPositionManagerTest extends MultiFileTestCase { } } }); + + } + + @Override + public void tearDown() throws Exception { + if (debugProcess != null) { + debugProcess.dispose(); + } + super.tearDown(); } private static Collection extractBreakpointsInfo(JetFile file, String fileContent) { @@ -175,7 +187,7 @@ public abstract class AbstractJetPositionManagerTest extends MultiFileTestCase { assertNotNull(classes); assertEquals(1, classes.size()); ReferenceType type = classes.get(0); - assertTrue("Type name " + type.name() + " doesn't match " + breakpoint.classNameRegexp, + assertTrue("Type name " + type.name() + " doesn't match " + breakpoint.classNameRegexp + " for line " + (breakpoint.lineNumber + 1), type.name().matches(breakpoint.classNameRegexp)); // JDI names are of form "package.Class$InnerClass"