mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
IDEA-371371 Stream trace debugging doesn't work with records
(cherry picked from commit bbe83739e3db7cd0b7a4b8842b6e5c1cbb8d1f32) IJ-CR-161068 GitOrigin-RevId: a25b07b6d494e07c5bc018f5a6922b9bb4ad7978
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4b11fb634b
commit
b5f7185b0b
@@ -1,10 +1,11 @@
|
|||||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||||
package com.intellij.refactoring.extractMethodObject.reflect;
|
package com.intellij.refactoring.extractMethodObject.reflect;
|
||||||
|
|
||||||
import com.intellij.openapi.diagnostic.Logger;
|
import com.intellij.openapi.diagnostic.Logger;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.util.ClassUtil;
|
import com.intellij.psi.util.ClassUtil;
|
||||||
|
import com.intellij.psi.util.PsiTypesUtil;
|
||||||
import com.intellij.psi.util.PsiUtil;
|
import com.intellij.psi.util.PsiUtil;
|
||||||
import com.intellij.psi.util.TypeConversionUtil;
|
import com.intellij.psi.util.TypeConversionUtil;
|
||||||
import com.intellij.util.SmartList;
|
import com.intellij.util.SmartList;
|
||||||
@@ -112,27 +113,37 @@ public class ReflectionAccessMethodBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ReflectionAccessMethodBuilder addParameter(@NotNull String jvmType, @NotNull String name) {
|
public ReflectionAccessMethodBuilder addParameter(@NotNull String jvmType, @NotNull String name) {
|
||||||
myParameters.add(new ParameterInfo(jvmType.replace('$', '.'), name, jvmType));
|
myParameters.add(new ParameterInfo(jvmType.replace('$', '.'), name, new TypeInfo(jvmType, 0)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReflectionAccessMethodBuilder addParameters(@NotNull PsiParameterList parameterList) {
|
public ReflectionAccessMethodBuilder addParameters(@NotNull PsiParameterList parameterList) {
|
||||||
PsiParameter[] parameters = parameterList.getParameters();
|
PsiParameter[] parameters = parameterList.getParameters();
|
||||||
for (PsiParameter parameter : parameters) {
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
PsiType parameterType = parameter.getType();
|
PsiType parameterType = parameters[i].getType();
|
||||||
PsiType erasedType = TypeConversionUtil.erasure(parameterType);
|
PsiType erasedType = TypeConversionUtil.erasure(parameterType);
|
||||||
String typeName = typeName(parameterType, erasedType);
|
String typeName = typeName(parameterType, erasedType);
|
||||||
String jvmType = erasedType != null ? extractJvmType(erasedType) : typeName;
|
TypeInfo jvmType = erasedType != null ? extractJvmType(erasedType) : new TypeInfo(typeName, 0);
|
||||||
|
|
||||||
String name = parameter.getName();
|
String name = "p" + i; // To avoid confusion with local variables, the real parameter names are not used.
|
||||||
|
|
||||||
PsiType accessedType = PsiReflectionAccessUtil.nearestAccessibleType(parameterType);
|
if (requiresObjectType(parameterType) || jvmType.arrayDimension > 0) {
|
||||||
myParameters.add(new ParameterInfo(accessedType.getCanonicalText(), name, jvmType));
|
myParameters.add(new ParameterInfo(CommonClassNames.JAVA_LANG_OBJECT, name, jvmType));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PsiType accessedType = PsiReflectionAccessUtil.nearestAccessibleType(parameterType);
|
||||||
|
myParameters.add(new ParameterInfo(accessedType.getCanonicalText(), name, jvmType));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean requiresObjectType(PsiType type) {
|
||||||
|
PsiClass psiClass = PsiTypesUtil.getPsiClass(type);
|
||||||
|
return psiClass != null && (psiClass.isRecord() || psiClass.isEnum());
|
||||||
|
}
|
||||||
|
|
||||||
private static @NotNull String typeName(@NotNull PsiType type, @Nullable PsiType erasedType) {
|
private static @NotNull String typeName(@NotNull PsiType type, @Nullable PsiType erasedType) {
|
||||||
if (erasedType == null) {
|
if (erasedType == null) {
|
||||||
String typeName = type.getCanonicalText();
|
String typeName = type.getCanonicalText();
|
||||||
@@ -148,18 +159,46 @@ public class ReflectionAccessMethodBuilder {
|
|||||||
return erasedType.getCanonicalText();
|
return erasedType.getCanonicalText();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NotNull String extractJvmType(@NotNull PsiType type) {
|
private static class TypeInfo {
|
||||||
|
final int arrayDimension;
|
||||||
|
final String typeName;
|
||||||
|
|
||||||
|
private TypeInfo(String name, int dimension) {
|
||||||
|
arrayDimension = dimension;
|
||||||
|
typeName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
String lookupClass() {
|
||||||
|
if (TypeConversionUtil.isPrimitive(typeName)) {
|
||||||
|
return typeName + StringUtil.repeat("[]", arrayDimension) + ".class";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String className = typeName;
|
||||||
|
if (arrayDimension > 0) {
|
||||||
|
className = StringUtil.repeat("[", arrayDimension) + "L" + typeName + ";";
|
||||||
|
}
|
||||||
|
return "java.lang.Class.forName(\"" + className + "\")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull TypeInfo extractJvmType(@NotNull PsiType type) {
|
||||||
|
int arrayDimension = 0;
|
||||||
|
while (type instanceof PsiArrayType arrayType) {
|
||||||
|
arrayDimension++;
|
||||||
|
type = arrayType.getComponentType();
|
||||||
|
}
|
||||||
PsiClass psiClass = PsiUtil.resolveClassInType(type);
|
PsiClass psiClass = PsiUtil.resolveClassInType(type);
|
||||||
String canonicalText = type.getCanonicalText();
|
String canonicalText = type.getCanonicalText();
|
||||||
String jvmName = psiClass == null ? canonicalText : ClassUtil.getJVMClassName(psiClass);
|
String jvmName = psiClass == null ? canonicalText : ClassUtil.getJVMClassName(psiClass);
|
||||||
return jvmName == null ? canonicalText : jvmName;
|
return new TypeInfo(jvmName == null ? canonicalText : jvmName, arrayDimension);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String createCatchBlocks(@NotNull List<String> exceptions) {
|
private static String createCatchBlocks(@NotNull List<String> exceptions) {
|
||||||
return StreamEx.of(exceptions).map(x -> "catch(" + x + " e) { throw new java.lang.RuntimeException(e); }").joining("\n");
|
return StreamEx.of(exceptions).map(x -> "catch(" + x + " e) { throw new java.lang.RuntimeException(e); }").joining("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private record ParameterInfo(@NotNull String accessibleType, @NotNull String name, @NotNull String jvmTypeName) {
|
private record ParameterInfo(@NotNull String accessibleType, @NotNull String name, @NotNull TypeInfo jvmType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface MyMemberAccessor {
|
private interface MyMemberAccessor {
|
||||||
@@ -227,7 +266,7 @@ public class ReflectionAccessMethodBuilder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMemberLookupExpression() {
|
public String getMemberLookupExpression() {
|
||||||
String args = StreamEx.of(myParameters).skip(1).map(x -> PsiReflectionAccessUtil.classForName(x.jvmTypeName))
|
String args = StreamEx.of(myParameters).skip(1).map(x -> x.jvmType.lookupClass())
|
||||||
.prepend(StringUtil.wrapWithDoubleQuote(myMethodName))
|
.prepend(StringUtil.wrapWithDoubleQuote(myMethodName))
|
||||||
.joining(", ", "(", ")");
|
.joining(", ", "(", ")");
|
||||||
return "getDeclaredMethod" + args;
|
return "getDeclaredMethod" + args;
|
||||||
@@ -251,11 +290,10 @@ public class ReflectionAccessMethodBuilder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAccessExpression() {
|
public String getAccessExpression() {
|
||||||
return StreamEx.of(myParameters).map(x -> x.name).joining(", ", "invoke(", ")");
|
return "invoke" + parametersStringForInvoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class MyConstructorAccessor implements MyMemberAccessor {
|
private class MyConstructorAccessor implements MyMemberAccessor {
|
||||||
private final String myClassName;
|
private final String myClassName;
|
||||||
|
|
||||||
@@ -265,7 +303,7 @@ public class ReflectionAccessMethodBuilder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMemberLookupExpression() {
|
public String getMemberLookupExpression() {
|
||||||
String args = StreamEx.of(myParameters).map(x -> x.jvmTypeName).map(PsiReflectionAccessUtil::classForName).joining(", ", "(", ")");
|
String args = StreamEx.of(myParameters).map(x -> x.jvmType.lookupClass()).joining(", ", "(", ")");
|
||||||
return "getDeclaredConstructor" + args;
|
return "getDeclaredConstructor" + args;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,8 +314,7 @@ public class ReflectionAccessMethodBuilder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAccessExpression() {
|
public String getAccessExpression() {
|
||||||
String args = StreamEx.of(myParameters).map(x -> x.name).joining(", ", "(", ")");
|
return "newInstance" + parametersStringForInvoke();
|
||||||
return "newInstance" + args;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -290,4 +327,15 @@ public class ReflectionAccessMethodBuilder {
|
|||||||
return Collections.singletonList("java.lang.ReflectiveOperationException");
|
return Collections.singletonList("java.lang.ReflectiveOperationException");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String parametersStringForInvoke() {
|
||||||
|
return StreamEx.of(myParameters).map(x -> {
|
||||||
|
if (x.jvmType.arrayDimension > 0) {
|
||||||
|
return "(java.lang.Object)" + x.name; // cast arrays to Object to avoid confusion with varargs method invocation
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return x.name;
|
||||||
|
}
|
||||||
|
}).joining(", ", "(", ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ public class GeneratedEvaluationClass {
|
|||||||
return newWithReflectionAccess1(50);
|
return newWithReflectionAccess1(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object newWithReflectionAccess1(int value) {
|
public static Object newWithReflectionAccess1(int p0) {
|
||||||
try {
|
try {
|
||||||
Class<?> klass = Class.forName("WithReflectionAccess");
|
Class<?> klass = Class.forName("WithReflectionAccess");
|
||||||
java.lang.reflect.Constructor<?> member = null;
|
java.lang.reflect.Constructor<?> member = null;
|
||||||
@@ -30,7 +30,7 @@ public class GeneratedEvaluationClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
member.setAccessible(true);
|
member.setAccessible(true);
|
||||||
return (Object) member.newInstance(value);
|
return (Object) member.newInstance(p0);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class GeneratedEvaluationClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void callApply1(Object object, Runnable runnable) {
|
public static void callApply1(Object object, Runnable p0) {
|
||||||
try {
|
try {
|
||||||
Class<?> klass = Class.forName("WithReflectionAccess");
|
Class<?> klass = Class.forName("WithReflectionAccess");
|
||||||
java.lang.reflect.Method member = null;
|
java.lang.reflect.Method member = null;
|
||||||
@@ -61,7 +61,7 @@ public class GeneratedEvaluationClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
member.setAccessible(true);
|
member.setAccessible(true);
|
||||||
member.invoke(object, runnable);
|
member.invoke(object, p0);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public class GeneratedEvaluationClass {
|
|||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object callMethod1(Object object, Object arg) {
|
public static Object callMethod1(Object object, Object p0) {
|
||||||
try {
|
try {
|
||||||
Class<?> klass = Class.forName("WithReflectionAccess");
|
Class<?> klass = Class.forName("WithReflectionAccess");
|
||||||
java.lang.reflect.Method member = null;
|
java.lang.reflect.Method member = null;
|
||||||
@@ -32,7 +32,7 @@ public class GeneratedEvaluationClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
member.setAccessible(true);
|
member.setAccessible(true);
|
||||||
return (Object) member.invoke(object, arg);
|
return (Object) member.invoke(object, p0);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public class GeneratedEvaluationClass {
|
|||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int callMethod1(Object object, int arg) {
|
public static int callMethod1(Object object, int p0) {
|
||||||
try {
|
try {
|
||||||
Class<?> klass = Class.forName("WithReflectionAccess");
|
Class<?> klass = Class.forName("WithReflectionAccess");
|
||||||
java.lang.reflect.Method member = null;
|
java.lang.reflect.Method member = null;
|
||||||
@@ -32,7 +32,7 @@ public class GeneratedEvaluationClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
member.setAccessible(true);
|
member.setAccessible(true);
|
||||||
return (int) member.invoke(object, arg);
|
return (int) member.invoke(object, p0);
|
||||||
} catch (ReflectiveOperationException e) {
|
} catch (ReflectiveOperationException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user