Skip to content

Commit

Permalink
Merge pull request #34 from Jozott00/move-to-executor
Browse files Browse the repository at this point in the history
Remove Custom Run Tool-Window
  • Loading branch information
Jozott00 authored Mar 4, 2024
2 parents 686bdac + 4e2f0cb commit c291ccd
Show file tree
Hide file tree
Showing 43 changed files with 810 additions and 728 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ jobs:
# Run Qodana inspections
- name: Qodana - Code Inspection
uses: JetBrains/[email protected]
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
with:
cache-default-branch-only: true

Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,27 @@
# wokwi-intellij Changelog

## [Unreleased]

This update switches from the custom run toolwindow
to a headless run configuration, which is more familiar for
most Intellij users.

### Added
- Run configuration for simulator instance
- Automatic GDB port selection

### Removed
- WokwiDebugStart configuration
- Wokwi Run toolwindow

## [0.9.0] - 2024-02-23

### Added

- Embedded Wokwi simulator
- Wokwi console to control simulator
- wokwi.toml analysis support
- Wokwi simulation debugging support

[Unreleased]: https://github.com/Jozott00/wokwi-intellij/compare/v0.9.0...HEAD
[0.9.0]: https://github.com/Jozott00/wokwi-intellij/commits/v0.9.0
Binary file modified blob/imgs/sim_running.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ repositories {

// Dependencies are managed with Gradle version catalog - read more: https://docs.gradle.org/current/userguide/platforms.html#sub:version-catalog
dependencies {
implementation(files("libs/espimg-0.1.0.jar"))
implementation("org.java-websocket:Java-WebSocket:1.5.4")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
implementation("com.beust:klaxon:5.6")
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ pluginGroup=com.github.jozott00.wokwiintellij
pluginName=wokwi-intellij
pluginRepositoryUrl=https://github.com/Jozott00/wokwi-intellij
# SemVer format -> https://semver.org
pluginVersion=0.9.0
pluginVersion=0.10.0
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild=232
pluginUntilBuild=233.*
# IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension
platformType=IC
platformType=CL
platformVersion=2023.2
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
Expand Down
Binary file removed libs/espimg-0.1.0.jar
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.github.jozott00.wokwiintellij.actions

import com.github.jozott00.wokwiintellij.services.WokwiProjectService
import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.service

class WokwiRestartAction : AnAction() {
override fun actionPerformed(p0: AnActionEvent) {
p0.project?.service<WokwiProjectService>()?.startSimulator()
p0.project?.service<WokwiSimulatorService>()?.startSimulator()
}

}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package com.github.jozott00.wokwiintellij.actions


import com.github.jozott00.wokwiintellij.services.WokwiProjectService
import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.github.jozott00.wokwiintellij.utils.simulation.SimulatorRunUtils
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.service

class WokwiStartAction : AnAction() {


// TODO: Consider run configuration instead of custom run handling
override fun update(e: AnActionEvent) {
e.project?.let {
e.presentation.isEnabled = !it.service<WokwiSimulatorService>().isSimulatorRunning()
}
}
override fun actionPerformed(event: AnActionEvent) {
// event.project?.let {
// val config = RunManager.getInstance(it).createConfiguration("Wokwi Runner", WokwiConfigurationFactory(WokwiRunConfigType()))
// ProgramRunnerUtil.executeConfiguration(config, DefaultRunExecutor.getRunExecutorInstance())
// }
val s = event.project?.service<WokwiProjectService>()
s?.startSimulator()
event.project?.let { SimulatorRunUtils.startExecution(it) }
}

override fun getActionUpdateThread() = ActionUpdateThread.EDT
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.github.jozott00.wokwiintellij.actions


import com.github.jozott00.wokwiintellij.services.WokwiProjectService
import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
Expand All @@ -14,15 +14,14 @@ class WokwiStopAction : AnAction() {
}

override fun update(e: AnActionEvent) {
val s = e.project?.service<WokwiProjectService>() ?: return
val s = e.project?.service<WokwiSimulatorService>() ?: return
val p = e.presentation

p.isEnabled = s.isSimulatorRunning()

}

override fun actionPerformed(event: AnActionEvent) {
val s = event.project?.service<WokwiProjectService>()
val s = event.project?.service<WokwiSimulatorService>()
s?.stopSimulator()

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.github.jozott00.wokwiintellij.runner
package com.github.jozott00.wokwiintellij.execution

import com.github.jozott00.wokwiintellij.runner.configs.*
import com.github.jozott00.wokwiintellij.execution.configs.*
import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.execution.configurations.ConfigurationType
import com.intellij.openapi.project.Project
Expand All @@ -13,14 +13,12 @@ class WokwiConfigurationFactory(type: ConfigurationType) : ConfigurationFactory(
override fun createTemplateConfiguration(
project: Project
) = when (type) {
is WokwiStartDebugConfigType -> WokwiStartDebugConfig(project, this, type.displayName)
is WokwiRunConfigType -> WokwiRunConfig(project, this, type.displayName)
else -> error("Invalid configuration type")
}


override fun getOptionsClass() = when (type) {
is WokwiStartDebugConfigType -> WokwiStartDebugConfigOptions::class.java
is WokwiRunConfigType -> WokwiRunConfigOptions::class.java
else -> error("Invalid configuration type")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.github.jozott00.wokwiintellij.runner.configs
package com.github.jozott00.wokwiintellij.execution.configs

import com.github.jozott00.wokwiintellij.runner.WokwiConfigurationFactory
import com.github.jozott00.wokwiintellij.runner.profileStates.WokwiSimulatorRunnerState
import com.github.jozott00.wokwiintellij.execution.WokwiConfigurationFactory
import com.github.jozott00.wokwiintellij.execution.profileStates.WokwiSimulatorRunnerState
import com.github.jozott00.wokwiintellij.ui.WokwiIcons
import com.intellij.execution.Executor
import com.intellij.execution.configurations.ConfigurationFactory
Expand Down Expand Up @@ -33,7 +33,7 @@ class WokwiRunConfig(

class WokwiRunConfigType : ConfigurationTypeBase(
ID, "Wokwi Run", "Run the Wokwi simulator and let it wait for a GDB debugger.",
NotNullLazyValue.createValue { WokwiIcons.Debug }
NotNullLazyValue.createValue { WokwiIcons.SimulatorToolWindowIcon }
) {
init {
addFactory(WokwiConfigurationFactory(this))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.github.jozott00.wokwiintellij.runner.macros
package com.github.jozott00.wokwiintellij.execution.macros

import com.github.jozott00.wokwiintellij.toml.WokwiConfigProcessor
import com.intellij.ide.macro.Macro
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.github.jozott00.wokwiintellij.runner.macros
package com.github.jozott00.wokwiintellij.execution.macros

import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.github.jozott00.wokwiintellij.toml.WokwiConfigProcessor
import com.intellij.ide.macro.Macro
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.components.service
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking

Expand All @@ -15,8 +17,10 @@ class GdbServerMacro : Macro() {
override fun expand(dataContext: DataContext): String? {
val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return null
val config = runBlocking(Dispatchers.IO) { WokwiConfigProcessor.readConfig(project) } ?: return null
val wokwiService = project.service<WokwiSimulatorService>()

val port = wokwiService.getRunningGDBPort() ?: config.gdbServerPort ?: return "localhost:<unknown-port>"

val port = config.gdbServerPort ?: return null
return "localhost:$port"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.github.jozott00.wokwiintellij.runner
package com.github.jozott00.wokwiintellij.execution.processHandler

import com.github.jozott00.wokwiintellij.simulator.WokwiSimulatorListener
import com.intellij.execution.process.ProcessHandler
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.github.jozott00.wokwiintellij.execution.processHandler

import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.github.jozott00.wokwiintellij.simulator.SimExitCode
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import java.io.OutputStream

class WokwiRunProcessHandler(project: Project): WokwiProcessHandler() {

private val projectService: WokwiSimulatorService = project.service()

override fun destroyProcessImpl() {
projectService.stopSimulator()
notifyProcessTerminated(0)
}

override fun detachProcessImpl() {
notifyProcessDetached()
}

override fun detachIsDefault(): Boolean = false

override fun getProcessInput(): OutputStream? {
return null
}

override fun onTextAvailable(text: String, outputType: Key<*>) {
notifyTextAvailable(text, outputType)
}

override fun onShutdown(exitCode: SimExitCode) {
if (!isProcessTerminated) {
notifyProcessTerminated(exitCode.int)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.github.jozott00.wokwiintellij.execution.profileStates

import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.intellij.execution.Executor
import com.intellij.execution.configurations.CommandLineState
import com.intellij.execution.process.ProcessHandler
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.execution.ui.ConsoleView
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.Separator
import com.intellij.openapi.components.service

class WokwiSimulatorRunnerState(myEnvironment: ExecutionEnvironment) : CommandLineState(myEnvironment) {
private val projectService = myEnvironment.project.service<WokwiSimulatorService>()
private val am = ActionManager.getInstance()
override fun startProcess() = projectService.startSimulator(false)

override fun createActions(console: ConsoleView?, processHandler: ProcessHandler?, executor: Executor?) = arrayOf(
Separator(),
am.getAction("com.github.jozott00.wokwiintellij.actions.WokwiWatchAction")
)

override fun createConsole(executor: Executor): ConsoleView? {
val builder = consoleBuilder ?: return null
builder.setViewer(true) // make it readonly
return builder.console
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package com.github.jozott00.wokwiintellij.execution.runBefore

import com.github.jozott00.wokwiintellij.services.WokwiSimulatorService
import com.github.jozott00.wokwiintellij.simulator.WokwiSimulatorListener
import com.github.jozott00.wokwiintellij.ui.WokwiIcons
import com.github.jozott00.wokwiintellij.utils.simulation.SimulatorRunUtils
import com.intellij.execution.BeforeRunTask
import com.intellij.execution.BeforeRunTaskProvider
import com.intellij.execution.configurations.RunConfiguration
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.components.service
import com.intellij.openapi.util.Key
import kotlinx.coroutines.*
import javax.swing.Icon

/**
* A [BeforeRunTaskProvider] implementation that initiates a debug session by starting the Wokwi
* simulator in debug mode before executing the main run configuration.
*
* This is required when debugging with CLion's `Remote Debug` configuration.
*/
class WokwiStartDebugBeforeRunTaskProvider : BeforeRunTaskProvider<WokwiStartDebugBeforeRunTask>() {

override fun getId(): Key<WokwiStartDebugBeforeRunTask> = ID

override fun getName() = "Start Wokwi Debug"

override fun getIcon(): Icon = WokwiIcons.Debug

override fun createTask(runConfiguration: RunConfiguration): WokwiStartDebugBeforeRunTask =
WokwiStartDebugBeforeRunTask()


/**
* Executes the task to start the Wokwi simulator in debug mode before the main run configuration.
* It ensures the simulator is running and ready for debugging. The additional execution of the
* run configuration is required to provide simulation output in a Run-window.
*
* @param context The data context in which the task is executed.
* @param configuration The run configuration associated with the task.
* @param environment The execution environment for the task.
* @param task The [WokwiStartDebugBeforeRunTask] to be executed.
* @return `true` if the task was successfully executed, `false` otherwise.
*/
override fun executeTask(
context: DataContext,
configuration: RunConfiguration,
environment: ExecutionEnvironment,
task: WokwiStartDebugBeforeRunTask
): Boolean {
val projectService = environment.project.service<WokwiSimulatorService>()
return runBlocking(Dispatchers.IO) {
// start child scope to make cancellation on dispose possible.
val job = projectService.childScope().async {
val result = projectService.startSimulatorAsync(task, true)
task.waitForSimulatorToBeRunning()
result
}
try {
val result = job.await()

// start run execution for additional log output
SimulatorRunUtils.startExecutionIfNotRunning(environment.project)

result
} catch (e: CancellationException) {
false
}
}
}

}

/**
* A [BeforeRunTask] implementation that waits for the Wokwi simulator to start and reach a running state
* before allowing the debug session to proceed. It implements the [WokwiSimulatorListener] interface
* to receive notifications about the simulator's state.
*/
class WokwiStartDebugBeforeRunTask :
BeforeRunTask<WokwiStartDebugBeforeRunTask>(ID), WokwiSimulatorListener {

private val simulatorRunning = CompletableDeferred<Unit>()

/**
* Suspends the current coroutine until the Wokwi simulator has been reported as running.
* This method waits for the [onRunning] event to be called, indicating that the simulator
* is ready.
*/
suspend fun waitForSimulatorToBeRunning() {
simulatorRunning.await()
}

/**
* Callback method from the [WokwiSimulatorListener] interface. It is called when the simulator
* changes its state to running.
*
* This method completes the [simulatorRunning] deferred, allowing any suspended coroutines
* waiting for the simulator to start to resume execution.
*/
override fun onRunning() {
simulatorRunning.complete(Unit)
}
}

val ID: Key<WokwiStartDebugBeforeRunTask> = Key.create("WokwiStartDebug.Before.Run")
Loading

0 comments on commit c291ccd

Please sign in to comment.