generated from JetBrains/intellij-platform-plugin-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
debug: get to know how IJ debugger work
- Loading branch information
Showing
6 changed files
with
178 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package org.aya.intellij.debug; | ||
|
||
import com.intellij.openapi.fileTypes.FileType; | ||
import com.intellij.openapi.project.Project; | ||
import com.intellij.psi.JavaCodeFragmentFactory; | ||
import com.intellij.psi.PsiElement; | ||
import com.intellij.psi.PsiFile; | ||
import com.intellij.xdebugger.XDebugProcess; | ||
import com.intellij.xdebugger.XDebugSession; | ||
import com.intellij.xdebugger.XSourcePosition; | ||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; | ||
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProviderBase; | ||
import com.intellij.xdebugger.frame.XSuspendContext; | ||
import org.aya.intellij.AyaFileType; | ||
import org.aya.intellij.run.AyaProgramRunner; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public class AyaDebugProcess extends XDebugProcess { | ||
public AyaDebugProcess(@NotNull XDebugSession session, @NotNull AyaProgramRunner.AyaRunState state) { | ||
super(session); | ||
} | ||
|
||
@Override public void sessionInitialized() { | ||
getSession().positionReached(new AyaSuspendState()); | ||
} | ||
|
||
@Override public void resume(@Nullable XSuspendContext context) {} | ||
|
||
@Override public void stop() {} | ||
|
||
@Override public void startStepOut(@Nullable XSuspendContext context) { | ||
getSession().positionReached(new AyaSuspendState()); | ||
} | ||
|
||
@Override public void startStepInto(@Nullable XSuspendContext context) { | ||
getSession().positionReached(new AyaSuspendState()); | ||
} | ||
|
||
@Override public void startStepOver(@Nullable XSuspendContext context) { | ||
getSession().positionReached(new AyaSuspendState()); | ||
} | ||
|
||
@Override public void runToPosition(@NotNull XSourcePosition position, @Nullable XSuspendContext context) { | ||
getSession().positionReached(new AyaSuspendState()); | ||
} | ||
|
||
@Override public @NotNull XDebuggerEditorsProvider getEditorsProvider() { | ||
return new AyaEditorsProvider(); | ||
} | ||
|
||
private static final class AyaEditorsProvider extends XDebuggerEditorsProviderBase { | ||
@Override public @NotNull FileType getFileType() { | ||
return AyaFileType.INSTANCE; | ||
} | ||
|
||
@Override | ||
protected PsiFile createExpressionCodeFragment(@NotNull Project project, @NotNull String text, @Nullable PsiElement context, boolean isPhysical) { | ||
// TODO: aya code fragment? | ||
return JavaCodeFragmentFactory.getInstance(project).createExpressionCodeFragment(text, context, null, isPhysical); | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/org/aya/intellij/debug/AyaExecutionStack.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.aya.intellij.debug; | ||
|
||
import com.intellij.ui.ColoredTextContainer; | ||
import com.intellij.ui.SimpleTextAttributes; | ||
import com.intellij.xdebugger.frame.XExecutionStack; | ||
import com.intellij.xdebugger.frame.XStackFrame; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
import javax.swing.*; | ||
import java.util.List; | ||
|
||
public class AyaExecutionStack extends XExecutionStack { | ||
protected AyaExecutionStack(@NotNull String displayName, @Nullable Icon icon) { | ||
super(displayName, icon); | ||
} | ||
|
||
@Override public @Nullable AyaStackFrame getTopFrame() { | ||
return new AyaStackFrame(); | ||
} | ||
|
||
@Override public void computeStackFrames(int firstFrameIndex, XStackFrameContainer container) { | ||
container.addStackFrames(List.of(new AyaStackFrame(), new AyaStackFrame()), false); | ||
} | ||
|
||
public static final class AyaStackFrame extends XStackFrame { | ||
@Override public void customizePresentation(@NotNull ColoredTextContainer component) { | ||
component.append("Aya stack frame", SimpleTextAttributes.REGULAR_ATTRIBUTES); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package org.aya.intellij.debug; | ||
|
||
import com.intellij.xdebugger.frame.XSuspendContext; | ||
import org.jetbrains.annotations.Nullable; | ||
|
||
public class AyaSuspendState extends XSuspendContext { | ||
@Override public @Nullable AyaExecutionStack getActiveExecutionStack() { | ||
return new AyaExecutionStack("Aya Execution Stack", null); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package org.aya.intellij.run; | ||
|
||
import com.intellij.debugger.impl.GenericDebuggerRunnerSettings; | ||
import com.intellij.execution.ExecutionException; | ||
import com.intellij.execution.ExecutionResult; | ||
import com.intellij.execution.Executor; | ||
import com.intellij.execution.configurations.RunProfile; | ||
import com.intellij.execution.configurations.RunProfileState; | ||
import com.intellij.execution.executors.DefaultDebugExecutor; | ||
import com.intellij.execution.executors.DefaultRunExecutor; | ||
import com.intellij.execution.runners.AsyncProgramRunner; | ||
import com.intellij.execution.runners.ExecutionEnvironment; | ||
import com.intellij.execution.runners.ProgramRunner; | ||
import com.intellij.execution.ui.RunContentDescriptor; | ||
import com.intellij.xdebugger.XDebugProcess; | ||
import com.intellij.xdebugger.XDebugProcessStarter; | ||
import com.intellij.xdebugger.XDebugSession; | ||
import com.intellij.xdebugger.XDebuggerManager; | ||
import org.aya.intellij.debug.AyaDebugProcess; | ||
import org.jetbrains.annotations.NonNls; | ||
import org.jetbrains.annotations.NotNull; | ||
import org.jetbrains.annotations.Nullable; | ||
import org.jetbrains.concurrency.Promise; | ||
import org.jetbrains.concurrency.Promises; | ||
|
||
/** | ||
* highly inspired from {@link com.intellij.javascript.debugger.execution.DebuggableProgramRunner} | ||
*/ | ||
public class AyaProgramRunner extends AsyncProgramRunner<GenericDebuggerRunnerSettings> { | ||
@Override public @NotNull @NonNls String getRunnerId() { | ||
return AyaProgramRunner.class.getSimpleName(); | ||
} | ||
|
||
@Override public boolean canRun(@NotNull String executorId, @NotNull RunProfile profile) { | ||
return (executorId.equals(DefaultDebugExecutor.EXECUTOR_ID) // make "Debug" button clickable | ||
|| executorId.equals(DefaultRunExecutor.EXECUTOR_ID) // make "Run" button clickable | ||
) && profile instanceof TyckRunConfig; | ||
} | ||
|
||
public static @Nullable AyaRunState prepare(@NotNull Executor executor, @NotNull TyckRunConfig config) { | ||
// TODO: what if user just want normal typechecking (rather than traced/debugger)? | ||
if (executor.getId().equals(DefaultRunExecutor.EXECUTOR_ID)) return null; | ||
// Now user want to trace the typechecking process. | ||
return new AyaRunState(config, true); | ||
} | ||
|
||
@Override | ||
protected @NotNull Promise<RunContentDescriptor> execute(@NotNull ExecutionEnvironment env, @NotNull RunProfileState state) throws ExecutionException { | ||
if (!(state instanceof AyaRunState aya)) | ||
return Promises.rejectedPromise("Trying to run non-aya program with AyaProgramRunner"); | ||
var session = startDebug(env, aya); | ||
return Promises.resolvedPromise(session.getRunContentDescriptor()); | ||
} | ||
|
||
private static @NotNull XDebugSession startDebug(@NotNull ExecutionEnvironment env, @NotNull AyaRunState state) throws ExecutionException { | ||
return XDebuggerManager.getInstance(env.getProject()) | ||
.startSession(env, new XDebugProcessStarter() { | ||
@Override public @NotNull XDebugProcess start(@NotNull XDebugSession session) { | ||
return new AyaDebugProcess(session, state); | ||
} | ||
}); | ||
} | ||
|
||
/** @implNote put aya compiler cmdline arguments here */ | ||
public record AyaRunState(@NotNull TyckRunConfig config, boolean debug) implements RunProfileState { | ||
@Override public @Nullable ExecutionResult execute(Executor executor, @NotNull ProgramRunner<?> runner) { | ||
// We do not need to execute here. AyaProgramRunner handles everything. | ||
throw new IllegalStateException("unreachable"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters