Debugger: fix className for properties in class objects

This commit is contained in:
Natalia Ukhorskaya
2014-09-25 14:37:02 +04:00
parent 4994e771d0
commit 6179b4889b
5 changed files with 100 additions and 12 deletions
@@ -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
@@ -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
}
}
@@ -1,5 +1,5 @@
package customLib.simpleLibFile
public fun foo() {
val a = 1
1 + 1
}
@@ -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
@@ -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<String, ReferenceType> 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<Breakpoint> 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"