Debugger: fix className for properties in class objects
This commit is contained in:
@@ -39,11 +39,11 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.TestOnly;
|
import org.jetbrains.annotations.TestOnly;
|
||||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||||
|
import org.jetbrains.jet.codegen.AsmUtil;
|
||||||
import org.jetbrains.jet.codegen.ClassBuilderFactories;
|
import org.jetbrains.jet.codegen.ClassBuilderFactories;
|
||||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
|
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
|
||||||
@@ -208,6 +208,29 @@ public class JetPositionManager implements PositionManager {
|
|||||||
return asmType.getInternalName();
|
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) {
|
else if (element instanceof JetNamedFunction) {
|
||||||
PsiElement parent = getElementToCalculateClassName(element);
|
PsiElement parent = getElementToCalculateClassName(element);
|
||||||
if (parent instanceof JetClassOrObject) {
|
if (parent instanceof JetClassOrObject) {
|
||||||
@@ -230,14 +253,31 @@ public class JetPositionManager implements PositionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static JetNamedDeclaration getElementToCalculateClassName(@Nullable PsiElement notPositionedElement) {
|
private static JetDeclaration getElementToCalculateClassName(@Nullable PsiElement notPositionedElement) {
|
||||||
//noinspection unchecked
|
//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
|
@Nullable
|
||||||
private static JetElement getElementToCreateTypeMapperForLibraryFile(@Nullable PsiElement notPositionedElement) {
|
private static JetElement getElementToCreateTypeMapperForLibraryFile(@Nullable PsiElement element) {
|
||||||
return PsiTreeUtil.getParentOfType(notPositionedElement, JetElement.class);
|
return element instanceof JetElement ? (JetElement) element : PsiTreeUtil.getParentOfType(element, JetElement.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -1,7 +1,43 @@
|
|||||||
class A {
|
class A {
|
||||||
class object {
|
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
|
"" // 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
|
package customLib.simpleLibFile
|
||||||
|
|
||||||
public fun foo() {
|
public fun foo() {
|
||||||
val a = 1
|
1 + 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ inline fun foo(f: () -> Unit) {
|
|||||||
|
|
||||||
// EXPRESSION: var1
|
// EXPRESSION: var1
|
||||||
// RESULT: 1: I
|
// RESULT: 1: I
|
||||||
frame = main():7, FrameSharedVarLocalVarPackage-@packagePartHASH {frameSharedVarLocalVar}
|
frame = main():7, FrameSharedVarLocalVarPackage$@packagePartHASH {frameSharedVarLocalVar}
|
||||||
static = static = frameSharedVarLocalVar.FrameSharedVarLocalVarPackage-@packagePartHASH
|
static = static = frameSharedVarLocalVar.FrameSharedVarLocalVarPackage$@packagePartHASH
|
||||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID}
|
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID}
|
||||||
local = var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
local = var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
||||||
field = element: int = 1
|
field = element: int = 1
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.intellij.debugger.PositionManager;
|
|||||||
import com.intellij.debugger.SourcePosition;
|
import com.intellij.debugger.SourcePosition;
|
||||||
import com.intellij.debugger.engine.DebugProcess;
|
import com.intellij.debugger.engine.DebugProcess;
|
||||||
import com.intellij.debugger.engine.DebugProcessEvents;
|
import com.intellij.debugger.engine.DebugProcessEvents;
|
||||||
|
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||||
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
|
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
@@ -62,6 +63,8 @@ public abstract class AbstractJetPositionManagerTest extends MultiFileTestCase {
|
|||||||
return PluginTestCaseBase.getTestDataPathBase();
|
return PluginTestCaseBase.getTestDataPathBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DebugProcessImpl debugProcess;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected String getTestRoot() {
|
protected String getTestRoot() {
|
||||||
@@ -111,7 +114,7 @@ public abstract class AbstractJetPositionManagerTest extends MultiFileTestCase {
|
|||||||
|
|
||||||
Map<String, ReferenceType> referencesByName = getReferenceMap(state.getFactory());
|
Map<String, ReferenceType> referencesByName = getReferenceMap(state.getFactory());
|
||||||
|
|
||||||
DebugProcess debugProcess = createDebugProcess(referencesByName);
|
debugProcess = createDebugProcess(referencesByName);
|
||||||
|
|
||||||
final PositionManager positionManager = createPositionManager(debugProcess, files, state);
|
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) {
|
private static Collection<Breakpoint> extractBreakpointsInfo(JetFile file, String fileContent) {
|
||||||
@@ -175,7 +187,7 @@ public abstract class AbstractJetPositionManagerTest extends MultiFileTestCase {
|
|||||||
assertNotNull(classes);
|
assertNotNull(classes);
|
||||||
assertEquals(1, classes.size());
|
assertEquals(1, classes.size());
|
||||||
ReferenceType type = classes.get(0);
|
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));
|
type.name().matches(breakpoint.classNameRegexp));
|
||||||
|
|
||||||
// JDI names are of form "package.Class$InnerClass"
|
// JDI names are of form "package.Class$InnerClass"
|
||||||
|
|||||||
Reference in New Issue
Block a user