mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[debugger] Refactoring: Prepare to support java instrumentation
Prepare for IDEA-370744 GitOrigin-RevId: d28b2941347a480037b92b917035b4b503083c09
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d21be53db5
commit
b446b776e9
@@ -41,6 +41,7 @@ import com.intellij.util.messages.MessageBusConnection;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import com.intellij.util.ui.EDT;
|
||||
import kotlin.Unit;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
@@ -540,12 +541,13 @@ public class CompilerManagerImpl extends CompilerManager {
|
||||
return projectBuildDir;
|
||||
}
|
||||
|
||||
private static final class CompiledClass implements ClassObject {
|
||||
@ApiStatus.Internal
|
||||
public static final class CompiledClass implements ClassObject {
|
||||
private final String myPath;
|
||||
private final String myClassName;
|
||||
private final byte[] myBytes;
|
||||
|
||||
CompiledClass(String path, String className, byte[] bytes) {
|
||||
public CompiledClass(String path, String className, byte[] bytes) {
|
||||
myPath = path;
|
||||
myClassName = className;
|
||||
myBytes = bytes;
|
||||
|
||||
@@ -15,10 +15,13 @@ import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.compiler.ClassObject;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.psi.JavaRecursiveElementVisitor;
|
||||
import com.intellij.psi.PsiCodeFragment;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.extractMethodObject.LightMethodObjectExtractedData;
|
||||
import com.sun.jdi.ClassLoaderReference;
|
||||
import com.sun.jdi.Value;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader;
|
||||
@@ -39,12 +42,18 @@ public abstract class CompilingEvaluator implements ExpressionEvaluator {
|
||||
myData = data;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public @NotNull LightMethodObjectExtractedData getLightMethodObjectExtractedData() {
|
||||
return myData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Modifier getModifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private TextWithImports getCallCode() {
|
||||
@ApiStatus.Internal
|
||||
public @NotNull TextWithImports getCallCode() {
|
||||
return new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, myData.getGeneratedCallText());
|
||||
}
|
||||
|
||||
@@ -88,18 +97,28 @@ public abstract class CompilingEvaluator implements ExpressionEvaluator {
|
||||
ClassLoaderReference classLoader) throws EvaluateException {
|
||||
boolean useMagicAccessorImpl = myData.useMagicAccessor();
|
||||
|
||||
defineClassesForEvaluation(classes, context, process, classLoader, GEN_CLASS_NAME, useMagicAccessorImpl);
|
||||
process.findClass(context, getGenClassQName(), classLoader);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void defineClassesForEvaluation(@NotNull Collection<ClassObject> classes,
|
||||
EvaluationContextImpl context,
|
||||
DebugProcess process,
|
||||
ClassLoaderReference classLoader,
|
||||
@NotNull String generatedClassName,
|
||||
boolean useMagicAccessor) throws EvaluateException {
|
||||
for (ClassObject cls : classes) {
|
||||
if (cls.getPath().contains(GEN_CLASS_NAME)) {
|
||||
if (cls.getPath().contains(generatedClassName)) {
|
||||
byte[] bytes = cls.getContent();
|
||||
if (bytes != null) {
|
||||
if (useMagicAccessorImpl) {
|
||||
if (useMagicAccessor) {
|
||||
bytes = changeSuperToMagicAccessor(bytes);
|
||||
}
|
||||
ClassLoadingUtils.defineClass(cls.getClassName(), bytes, context, classLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
process.findClass(context, getGenClassQName(), classLoader);
|
||||
}
|
||||
|
||||
private static byte[] changeSuperToMagicAccessor(byte[] bytes) {
|
||||
@@ -133,5 +152,5 @@ public abstract class CompilingEvaluator implements ExpressionEvaluator {
|
||||
|
||||
///////////////// Compiler stuff
|
||||
|
||||
protected abstract @NotNull Collection<ClassObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException;
|
||||
public abstract @NotNull Collection<ClassObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException;
|
||||
}
|
||||
|
||||
+17
-7
@@ -6,7 +6,6 @@ import com.intellij.compiler.server.BuildManager;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException;
|
||||
import com.intellij.debugger.engine.evaluation.IncorrectCodeFragmentException;
|
||||
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
|
||||
import com.intellij.execution.configurations.JavaParameters;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.compiler.ClassObject;
|
||||
@@ -33,6 +32,7 @@ import com.intellij.refactoring.extractMethodObject.LightMethodObjectExtractedDa
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import com.intellij.xdebugger.frame.XSuspendContext;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.incremental.java.JavaBuilder;
|
||||
@@ -60,7 +60,7 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Collection<ClassObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException {
|
||||
public @NotNull Collection<ClassObject> compile(@Nullable JavaSdkVersion debuggeeVersion) throws EvaluateException {
|
||||
if (myCompiledClasses == null) {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("-encoding");
|
||||
@@ -146,9 +146,18 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
return file;
|
||||
}
|
||||
|
||||
public static @Nullable ExpressionEvaluator create(@NotNull Project project,
|
||||
@Nullable PsiElement psiContext,
|
||||
@NotNull Function<? super PsiElement, ? extends PsiCodeFragment> fragmentFactory)
|
||||
public static @Nullable CompilingEvaluator create(@NotNull Project project,
|
||||
@Nullable PsiElement psiContext,
|
||||
@NotNull Function<? super PsiElement, ? extends PsiCodeFragment> fragmentFactory)
|
||||
throws EvaluateException {
|
||||
return create(project, psiContext, null, fragmentFactory);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static @Nullable CompilingEvaluator create(@NotNull Project project,
|
||||
@Nullable PsiElement psiContext,
|
||||
@Nullable String generatedClassName,
|
||||
@NotNull Function<? super PsiElement, ? extends PsiCodeFragment> fragmentFactory)
|
||||
throws EvaluateException {
|
||||
if (Registry.is("debugger.compiling.evaluator") && psiContext != null) {
|
||||
return ReadAction.compute(() -> {
|
||||
@@ -160,8 +169,9 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
|
||||
project,
|
||||
physicalContext != null ? physicalContext : psiContext,
|
||||
fragmentFactory.apply(psiContext),
|
||||
getGeneratedClassName(),
|
||||
javaVersion);
|
||||
generatedClassName != null ? generatedClassName : getGeneratedClassName(),
|
||||
javaVersion,
|
||||
generatedClassName);
|
||||
if (data != null) {
|
||||
return new CompilingEvaluatorImpl(project, psiContext, data);
|
||||
}
|
||||
|
||||
+15
-6
@@ -14,15 +14,25 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
final class ExtractGeneratedClassUtil {
|
||||
private static final String GENERATED_CLASS_PACKAGE = "idea.debugger.rt";
|
||||
private static final Logger LOG = Logger.getInstance(ExtractGeneratedClassUtil.class);
|
||||
|
||||
static PsiClass extractGeneratedClass(@NotNull PsiClass generatedInnerClass,
|
||||
@NotNull PsiElementFactory elementFactory,
|
||||
@NotNull PsiElement anchor) {
|
||||
@NotNull PsiElement anchor,
|
||||
@Nullable String explicitGeneratedEvaluationClassFullName) {
|
||||
Project project = generatedInnerClass.getProject();
|
||||
|
||||
PsiClass extractedClass = elementFactory.createClass("GeneratedEvaluationClass");
|
||||
if (explicitGeneratedEvaluationClassFullName == null) {
|
||||
explicitGeneratedEvaluationClassFullName = "idea.debugger.rt.GeneratedEvaluationClass";
|
||||
}
|
||||
|
||||
int dotIndex = explicitGeneratedEvaluationClassFullName.lastIndexOf('.');
|
||||
|
||||
|
||||
String generatedEvaluationClass = dotIndex == -1 ? explicitGeneratedEvaluationClassFullName : explicitGeneratedEvaluationClassFullName.substring(dotIndex + 1);
|
||||
String packageName = dotIndex == -1 ? "" : explicitGeneratedEvaluationClassFullName.substring(0, dotIndex);
|
||||
|
||||
PsiClass extractedClass = elementFactory.createClass(generatedEvaluationClass);
|
||||
|
||||
for (PsiField field : generatedInnerClass.getAllFields()) {
|
||||
extractedClass.add(elementFactory.createFieldFromText(field.getText(), anchor)); // TODO: check if null is OK
|
||||
@@ -34,9 +44,8 @@ final class ExtractGeneratedClassUtil {
|
||||
|
||||
PsiJavaFile generatedFile = (PsiJavaFile)PsiFileFactory.getInstance(project)
|
||||
.createFileFromText(extractedClass.getName() + ".java", JavaFileType.INSTANCE, extractedClass.getContainingFile().getText());
|
||||
// copy.getModificationStamp(),
|
||||
//false, false);
|
||||
generatedFile.setPackageName(GENERATED_CLASS_PACKAGE);
|
||||
|
||||
generatedFile.setPackageName(packageName);
|
||||
extractedClass = PsiTreeUtil.findChildOfType(generatedFile, PsiClass.class);
|
||||
copyStaticImports(generatedInnerClass, generatedFile, elementFactory);
|
||||
assert extractedClass != null;
|
||||
|
||||
+12
-1
@@ -26,6 +26,7 @@ import com.intellij.util.CommonJavaRefactoringUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -41,6 +42,16 @@ public final class ExtractLightMethodObjectHandler {
|
||||
final @NotNull PsiCodeFragment fragment,
|
||||
@NotNull String methodName,
|
||||
@Nullable JavaSdkVersion javaVersion) throws PrepareFailedException {
|
||||
return extractLightMethodObject(project, originalContext, fragment, methodName, javaVersion, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static @Nullable LightMethodObjectExtractedData extractLightMethodObject(final Project project,
|
||||
@Nullable PsiElement originalContext,
|
||||
final @NotNull PsiCodeFragment fragment,
|
||||
@NotNull String methodName,
|
||||
@Nullable JavaSdkVersion javaVersion,
|
||||
@Nullable String explicitGeneratedEvaluationClassName) throws PrepareFailedException {
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
PsiElement[] elements = completeToStatementArray(fragment, elementFactory);
|
||||
if (elements == null) {
|
||||
@@ -262,7 +273,7 @@ public final class ExtractLightMethodObjectHandler {
|
||||
new ReflectionAccessorToEverything(generatedClass, elementFactory).grantAccessThroughReflection(callExpression);
|
||||
boolean isJdkAtLeast11 = javaVersion == null || javaVersion.isAtLeast(JavaSdkVersion.JDK_11);
|
||||
if (isJdkAtLeast11 || Registry.is("debugger.compiling.evaluator.extract.generated.class")) {
|
||||
generatedClass = ExtractGeneratedClassUtil.extractGeneratedClass(generatedClass, elementFactory, anchor);
|
||||
generatedClass = ExtractGeneratedClassUtil.extractGeneratedClass(generatedClass, elementFactory, anchor, explicitGeneratedEvaluationClassName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user