Skip to content

Commit

Permalink
Refactor all breakpoint tracer related logic
Browse files Browse the repository at this point in the history
Add ability to load compiled classes into target VM
  • Loading branch information
Soarex16 committed Apr 12, 2022
1 parent 1aa6bd8 commit d29c75f
Show file tree
Hide file tree
Showing 27 changed files with 591 additions and 268 deletions.
1 change: 1 addition & 0 deletions plugins/stream-debugger/intellij.java.debugger.streams.iml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
<orderEntry type="module" module-name="intellij.java" />
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.platform.ide.util.io" />
<orderEntry type="module" module-name="intellij.java.compiler" />
</component>
</module>
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ tab.content.exception.thrown=There is no result (exception was thrown)
tab.content.no.result=There is no result of such stream chain
exception.tab.name=Exception
evaluation.failed.unknown.result.type=Evaluation failed: unknown type of result value
evaluation.failed.cannot.interpret.result=Cannot interpret trace result. {0}
evaluation.failed.cannot.interpret.result=Cannot interpret trace result. {0}
evaluation.failed.cannot.find.places.for.breakpoints=Cannot find places for breakpoints.
evaluation.failed.cannot.initialize.breakpoints=Cannot initialize breakpoints.
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.streams.action;

import com.intellij.debugger.engine.JavaDebugProcess;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.streams.diagnostic.ex.TraceCompilationException;
import com.intellij.debugger.streams.diagnostic.ex.TraceEvaluationException;
import com.intellij.debugger.streams.lib.LibrarySupportProvider;
import com.intellij.debugger.streams.psi.DebuggerPositionResolver;
import com.intellij.debugger.streams.psi.impl.DebuggerPositionResolverImpl;
import com.intellij.debugger.streams.trace.*;
import com.intellij.debugger.streams.trace.breakpoint.BreakpointConfigurator;
import com.intellij.debugger.streams.trace.breakpoint.BulkBreakpointConfigurator;
import com.intellij.debugger.streams.trace.breakpoint.MethodBreakpointTracer;
import com.intellij.debugger.streams.trace.breakpoint.*;
import com.intellij.debugger.streams.trace.impl.TraceResultInterpreterImpl;
import com.intellij.debugger.streams.ui.ChooserOption;
import com.intellij.debugger.streams.ui.impl.ElementChooserImpl;
import com.intellij.debugger.streams.ui.impl.EvaluationAwareTraceWindow;
import com.intellij.debugger.streams.wrapper.StreamCall;
import com.intellij.debugger.streams.wrapper.StreamChain;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
Expand All @@ -28,12 +28,15 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.stream.Stream;
Expand Down Expand Up @@ -114,8 +117,22 @@ private static void runTrace(@NotNull StreamChain chain, @NotNull LibrarySupport
final Project project = session.getProject();
final TraceExpressionBuilder expressionBuilder = provider.getExpressionBuilder(project);
final TraceResultInterpreter resultInterpreter = new TraceResultInterpreterImpl(provider.getLibrarySupport().getInterpreterFactory());
final BreakpointConfigurator breakpointConfigurator = new BulkBreakpointConfigurator();
final StreamTracer tracer = new MethodBreakpointTracer(session, breakpointConfigurator, resultInterpreter);

final PsiManager psiManager = PsiManager.getInstance(project);
final XSourcePosition currentPosition = session.getCurrentPosition();
if (currentPosition == null) {
LOG.info("Cannot find current debugger location");
return; // TODO: notify that stream cannot be traced
}
final PsiFile currentFile = psiManager.findFile(currentPosition.getFile());
if (currentFile == null) {
LOG.info("Cannot find current file PSI represenation");
return; // TODO: notify that stream cannot be traced
}
final BreakpointResolver breakpointResolver = new JavaBreakpointResolver(currentFile);

final StreamTracer tracer = new MethodBreakpointTracer(session, breakpointResolver, resultInterpreter);
//final StreamTracer tracer = new EvaluateExpressionTracer(session, expressionBuilder, resultInterpreter);
tracer.trace(chain, new TracingCallback() {
@Override
public void evaluated(@NotNull TracingResult result, @NotNull EvaluationContextImpl context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class PairMapResolver : ValuesOrderResolver {

return of(direct, reverse)
}
}

fun <K, V> MutableMap<K, MutableList<V>>.add(key: K, value: V) {
computeIfAbsent(key, { mutableListOf() }) += value
}
fun <K, V> MutableMap<K, MutableList<V>>.add(key: K, value: V) {
computeIfAbsent(key, { mutableListOf() }) += value
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.streams.trace.breakpoint

import com.intellij.debugger.streams.wrapper.StreamCall

/**
* @author Shumaf Lovpache
*/
interface BreakpointResolver {
fun tryFindBreakpointPlace(streamStep: StreamCall): MethodSignature?
}

data class StreamChainBreakpointPlaces(val intermediateStepsMethods: List<MethodSignature>, val terminationOperationMethod: MethodSignature)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.streams.trace.breakpoint

import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.engine.evaluation.EvaluateException
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.impl.ClassLoadingUtils
import com.intellij.openapi.compiler.ClassObject
import com.intellij.openapi.compiler.CompilerManager
import com.intellij.openapi.project.Project
import com.sun.jdi.ReferenceType
import com.sun.jdi.event.MethodExitEvent

/**
* @author Shumaf Lovpache
*/
fun createHelperClass(suspendContext: SuspendContextImpl, event: MethodExitEvent) {
val source = """
class MapCollector<T> implements Consumer<T> {
private final java.util.Map<java.lang.Integer, T> storage;
private final java.util.concurrent.atomic.AtomicInteger time;
MapCollector(Map<Integer, T> storage, AtomicInteger time) {
this.storage = storage;
this.time = time;
}
@Override
public void accept(T t) {
storage.put(time.incrementAndGet(), t);
}
}
""".trimIndent()

// compileClass
}

fun compileClass(project: Project, sourceCode: String): ClassObject? {
val compilerManager: CompilerManager = CompilerManager.getInstance(project)
// TODO: научиться компилировать код
// compilerManager.compileJavaCode()
return null
}

fun EvaluationContextImpl.loadClass(className: String): ReferenceType? = debugProcess.loadClass(this, className, classLoader)

fun EvaluationContextImpl.loadClassIfAbsent(className: String, bytesLoader: () -> ByteArray?): ReferenceType? {
try {
return try {
val classLoader = this.classLoader
this.debugProcess.findClass(this, className, classLoader)
} catch (e: EvaluateException) {
if (e.exceptionFromTargetVM!!.type().name() == "java.lang.ClassNotFoundException") {
val bytes = bytesLoader() ?: return null
loadAndPrepareClass(this, className, bytes)
} else {
throw e
}
}
}
catch (e: Throwable) {
return null
}
}

@Throws(EvaluateException::class)
private fun loadAndPrepareClass(evaluationContext: EvaluationContextImpl, name: String, bytes: ByteArray): ReferenceType? {
val debugProcess = evaluationContext.debugProcess
evaluationContext.isAutoLoadClasses = true
val classLoader = evaluationContext.classLoader
ClassLoadingUtils.defineClass(name, bytes, evaluationContext, debugProcess, classLoader)
return try {
debugProcess.loadClass(evaluationContext, name, classLoader)
}
catch (e: Exception) {
throw EvaluateExceptionUtil.createEvaluateException("Could not load class", e)
}
}
Loading

0 comments on commit d29c75f

Please sign in to comment.