Execution
The IntelliJ Platform Execution API allows running external processes from within the IDE, e.g., applications, tests, servers, scripts, etc. These processes can be run from the editor, project view, run toolbar, or custom actions. Executed processes can be stopped, restarted, and their output and logs can be viewed in the run console. It is possible to manage and persist Run Configurations from the UI.
Architecture Overview
The key Execution API classes are divided into two groups:
The following diagram shows the relations between the key classes:
Configuration Classes
RunProfile
is a base interface for things that can be executed (e.g., an application started via a main()
method, a test or test suite, a remote debug session to a specific host, etc.). It is responsible for building a process that is run and creates a RunProfileState
.
RunProfileState
holds the information about the process ready to be started, like the command line, current working directory, and environment variables. The existence of RunProfileState
allows extensions and other components to patch the run profile and modify the parameters before the process gets executed. See standard run profile state classes.
RunConfiguration
is a specific type of run profile, which can be managed and persisted by users from UI. See the Run Configurations section for more details.
Execution Classes
Executor
describes a specific way of executing run profiles. The three default executors provided by the IntelliJ Platform are:
DefaultRunExecutor
(Run)DefaultDebugExecutor
(Debug)CoverageExecutor
(Run with Coverage)
Custom implementations are rarely required (it may be necessary, e.g., when a profiler integration is implemented). Executor implementations are registered in the com.intellij.executor
extension point (EP).
ProgramRunner
is responsible for the execution workflow of a RunProfile
with a certain Executor
. ProgramRunner
implementations are registered in the com.intellij.programRunner
EP.
ExecutionEnvironment
object aggregates all the objects and settings required to execute the process. It is used by the ProgramRunner.execute()
method.
RunContentBuilder
is responsible for building the content of the Run or Debug tool window. The content is built by the ProgramRunner
executing the process.
ExecutionResult
is prepared by RunProfileState
class before execution and contains ExecutionConsole
and ProcessHandler
.
ExecutionConsole
is a component displaying the result of executing the process. It can be a console, a test results view, or another similar component.
ProcessHandler
is an object attached to the executed process and allows controlling and accessing the information about the process. See standard process handler class.
Execution Workflow
A standard execution of a process consists of the following steps:
Depending on the execution context:
For execution initiated by a user from UI: the user selects a
RunConfiguration
(e.g., by choosing one from the run configurations combo box) and anExecutor
(e.g., by pressing the Run toolbar button).For programmatic execution: a
RunProfile
instance is created, and anExecutor
is provided. Specific run executors can be accessed withExecutorRegistry.getInstance().getExecutorById()
.
The
ProgramRunner
that will execute the process is selected. The firstProgramRunner
that returns true fromProgramRunner.canRun(executorId, runProfile)
is selected from all registered program runners.The
ExecutionEnvironment
is created. It aggregates all the information required to run the process as well as the selectedProgramRunner
,Executor
, andRunProfile
.ProgramRunner.execute(executionEnvironment)
is called, and the actual process is executed.
A standard implementation of ProgramRunner.execute()
goes through the following steps to execute the process:
RunProfile.getState()
method is called to create aRunProfileState
object, which describes a process about to be started. The command line parameters, environment variables, and other information required to start the process are initialized at this stage.RunProfileState.execute(executor, programRunner)
is called. It starts the process, attaches aProcessHandler
to its input and output streams, creates a console to display the process output, and returns anExecutionResult
object aggregating theExecutionConsole
and theProcessHandler
.The
RunContentBuilder
object is created and invoked to display the execution console in a Run or Debug tool window tab.
Example: RunAnythingCommandProvider.runCommand()
, which programmatically executes a command typed by a user in the Run Anything popup
Standard Base Classes
Run Profile State
The standard base class used as an implementation of RunProfileState
is CommandLineState
. It contains the logic for putting together a running process and a console into an ExecutionResult
but doesn't know anything about how the process is actually started. For starting the process, it's recommended to use the GeneralCommandLine
class, which takes care of setting up the command line parameters and executing the process.
Alternatively, if the process is a JVM-based one, use the JavaCommandLineState
base class. It handles the JVM command line parameters and can take care of details like calculating the classpath for the JVM. Note that using this class requires dependency on the Java plugin.
Process Handler
The standard class for monitoring the execution of a process and capturing its output is OSProcessHandler
. Once an instance of OSProcessHandler
is created from either a GeneralCommandLine
or a Process
object, call the startNotify()
method to capture its output. To display the exit status of the process in the console, attach a ProcessTerminatedListener
to the OSProcessHandler
.
Displaying Process Output
When a process execution is handled with CommandLineState
, a console view will be automatically created and attached to the process's output.
Alternatively, it can be handled with the following steps:
TextConsoleBuilderFactory.createBuilder(project).getConsole()
creates aConsoleView
instance.ConsoleView.attachToProcess()
attaches it to the output of a process.
If the running process uses ANSI escape codes to color its output, use the ColoredProcessHandler
class to display the colors in the IDE console.
Console Filters
Console Filter
allows converting certain strings found in the process output to clickable hyperlinks. To attach a filter to the console, use CommandLineState.addConsoleFilters()
or TextConsoleBuilder.addFilter()
if the console is created manually. Two standard filter implementations are RegexpFilter
and UrlFilter
.
Console filters can be also provided by implementing ConsoleFilterProvider
and registering it in com.intellij.consoleFilterProvider
EP.
Listening for Execution Events
Implement ExecutionListener
and subscribe to ExecutionManager#EXECUTION_TOPIC
. The listener allows for listening to several phases of the process execution lifecycle.