[dtd] Add editor service definitions as used by sidebar
This adds additional "Editor" service method definitions as used by the new DTD sidebar. I moved the Editor service definitions into a new file (because they're now quite large and dtd_common_services seems better as an intro and list of the common specified services).
I also split the existing info about `navigateToCode` into a more terse definition (in the new file) and a general example. I also updated the error example as I believe it was incorrectly wrapped in `result`.
Change-Id: I6136eb550cce0dab86d535db02f9f06ee42892e0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/378141
Reviewed-by: Kenzie Davisson <kenzieschmoll@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
Reviewed-by: Helin Shiah <helinx@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
diff --git a/pkg/dtd_impl/dtd_common_services.md b/pkg/dtd_impl/dtd_common_services.md
index caf48e1..0bcee8a 100644
--- a/pkg/dtd_impl/dtd_common_services.md
+++ b/pkg/dtd_impl/dtd_common_services.md
@@ -1,20 +1,25 @@
-# Common service methods
+# Common Services
-These are service methods that may be registered to DTD by multiple client types (e.g. multiple IDEs support navigating to a location in code). Other clients can then rely on service methods having a common interface despite being implemented by different client types. For example, DevTools should be able to request navigation to code using the same service method regardless of whether VS Code or IntelliJ registered it.
+These are service methods and events that may be registered to DTD by multiple client types (e.g. multiple IDEs support navigating to a location in code). Other clients can then rely on service methods having a common interface despite being implemented by different client types. For example, DevTools should be able to request navigation to code using the same service method regardless of whether VS Code or IntelliJ registered it.
Notes:
- Though multiple client types may register these methods, a single instance of DTD will accept only one client registering as a particular service. (DTD will throw an error if a second client tries to register as the same service.)
- These methods are not implemented in DTD. Rather, we want any new clients registering methods for a common purpose to follow a shared interface.
-- These methods may not be registered at all to DTD, depending on what other tools are connected. Clients hoping to use these methods should use the [`Service` stream](dtd_protocol.md#service-methods) to monitor whether these services are available.
+- These methods may not be registered at all to DTD, depending on what other tools are connected. Clients hoping to use these methods should use the [`Service` stream](./dtd_protocol.md#service-methods) to monitor whether these services are available.
-## Navigate to code location
-This is a service method that should be registered by a client that displays code (likely an IDE), so that other clients can request showing a specific location in code.
+## Service Definitions
-### Registering the method with DTD
+- [Editor Service](./dtd_common_services_editor.md)
+ Services provided by an editor or IDE for tools to interact with code, devices and debug sessions.
-This is what the client handling navigate to code requests (i.e. IDE) should send to DTD:
+
+## Registering a service method with DTD
+
+DTD uses JSON-RPC for communication. Methods can be registered by calling the `registerService` method documented in the [DTD Protocol](./dtd_protocol.md).
+
+### Example
```json
{
@@ -24,22 +29,19 @@
"service": "Editor",
"method": "navigateToCode",
"capabilities": {
- "supportedSchemes": ["file", "dart-macro-file"],
+ "supportedSchemes": ["file", "dart-macro+file"],
}
},
"id": "0"
}
```
-### Request Parameters
+## Calling a service method over DTD
-These are the parameters a client should send when requesting an editor navigate to code.
+Calling a service method involves a JSON-RPC request to a method name that
+combines the service and method name, for example `"Editor.navigateToCode"`.
-- `String uri` - The URI of the location to navigate to. Only `file://` URIs are supported unless the service registration's `capabilities` indicate other schemes are supported (specifics to be defined here in future). Editors should return error code 144 if a caller passes a URI with an unsupported scheme.
-- optional `int line` - 1-based line number.
-- optional `int column` - 1-based column number.
-
-#### Example
+### Example
```json
{
@@ -54,22 +56,18 @@
}
```
-### Result
+## Responses
-These are the parameters in a result:
+The response will contain a `result` that has a `type` indicating the type of
+returned data or `Success` if a successful request has no return value. Errors
+will be indicated as JSON-RPC errors with a `code` and `message`.
-- `String type` - one of `Success` or `Failure`.
-- optional `String errorCode` - a specific error code for a well-known failure type.
+### Examples
- | Error code | Description |
- | -------- | ------- |
- | 144 | The URI's scheme is not recognized by the editor. |
+#### Success
-- optional `String errorMessage` - a freeform message about the error.
-
-#### Examples
-
-If navigation in the editor is successful, a Success result should be returned.
+If a request is successful but has no specific return value, a `Success` result
+is returned.
```json
{
@@ -79,31 +77,39 @@
}
```
-Otherwise, the client can return an error code and/or an error message.
+#### Error
+
+If an error occurs, there will be no `result` but instead an `error`.
```json
{
"jsonrpc": "2.0",
- "result": {
- "type": "Failure",
- "error": {
- "code": 144,
- "message": "File scheme is not supported",
- "data": {
- "details": "File URI `malformed-file:///file.dart` is not valid.",
- "request": {
- "id": "0",
- "jsonrpc": "2.0",
- "method": "Editor.navigateToCode",
- "params": {
- "file": "malformed-file:///file.dart",
- "line": 1,
- "column": 2,
- }
+ "error": {
+ "code": 144,
+ "message": "File scheme is not supported",
+ "data": {
+ "details": "File URI `malformed-file:///file.dart` is not valid.",
+ "request": {
+ "id": "0",
+ "jsonrpc": "2.0",
+ "method": "Editor.navigateToCode",
+ "params": {
+ "file": "malformed-file:///file.dart",
+ "line": 1,
+ "column": 2,
}
}
}
- },
+ }
"id": "0"
}
```
+
+## Common Error Codes
+
+Below are some common error codes that may be used by all common services.
+Individual services may document their own error codes.
+
+| Error code | Description |
+| -------- | ------- |
+| 144 | The URI's scheme is not recognized. |
diff --git a/pkg/dtd_impl/dtd_common_services_editor.md b/pkg/dtd_impl/dtd_common_services_editor.md
new file mode 100644
index 0000000..f413c38
--- /dev/null
+++ b/pkg/dtd_impl/dtd_common_services_editor.md
@@ -0,0 +1,304 @@
+# Editor Services
+
+This document describes a common interface for service methods that editors/IDEs
+may provide over DTD.
+
+For a full list of common services, see [common_services](./dtd_common_services.md).
+
+# Methods
+
+Callers of these methods should monitor the
+[`Service` stream](./dtd_protocol.md#service-methods) to ensure they are
+available before calling them (it is not guaranteed that all editors provide
+all methods).
+
+
+## navigateToCode
+`Success navigateToCode(NavigateToCodeParams)`
+
+Instructs the editor to open and navigate to a file (and optional line/column).
+
+
+## getDevices
+`GetDevicesResult getDevices()`
+
+Requests the list of available devices from the editor. Devices can include
+connected mobile devices, web browsers and the desktop device. The `supported`
+flag can be used to tell whether a particular device is enabled in the current
+workspace.
+
+Callers of this method should first subscribe to the [`deviceXXX`](#deviceAdded)
+events to be notified when devices are added/removed/updated.
+
+
+## getDebugSessions
+`GetDebugSessionsResult getDebugSessions()`
+
+Requests a list of active debug sessions from the editor.
+
+Callers of this method should first subscribe to the
+[`debugSessionXXX`](#debugSessionStarted) events to be notified when debug
+sessions are started/stopped/updated.
+
+
+## selectDevice
+`Success selectDevice(SelectDeviceParams)`
+
+Instructs the editor to select a specific device (or no device). Callers should
+not assume the active device has changed until they receive a `deviceSelected`
+event.
+
+
+## enablePlatformType
+`Success enablePlatformType(EnablePlatformTypeParams)`
+
+Instructs the editor to enable a `platformType` for the current workspace. This
+may trigger a prompt to the user followed by executing commands (such as
+`flutter create`). Callers should not assume the platform is enabled until they
+receive a `deviceUpdated` event that shows `supported=true` for the devices of
+that type.
+
+
+## hotReload
+`Success hotReload(HotReloadParams)`
+
+Instructs the editor to trigger a hot reload for the provided debug session.
+
+
+## hotRestart
+`Success hotRestart(HotRestartParams)`
+
+Instructs the editor to trigger a hot restart for the provided debug session.
+
+
+## openDevToolsPage
+`Success openDevToolsPage(OpenDevToolsPageParams)`
+
+Instructs the editor to open DevTools at the given page for the provided debug
+session.
+
+
+# Events
+
+The following events are sent over the `Editor` stream. See `streamListen` in
+[dtd_protocol](./dtd_protocol.md) for information on subscribing to streams.
+
+
+## deviceAdded
+`DeviceAddedEvent`
+
+An event sent by an editor when a new device becomes available.
+
+
+## deviceRemoved
+`DeviceRemovedEvent`
+
+An event sent by an editor when a device is no longer available.
+
+
+## deviceChanged
+`DeviceChangedEvent`
+
+An event sent by an editor when an existing device is updated.
+
+The ID in this event always matches an existing device (that is, the ID never
+changes, or it would be considered a removal/add).
+
+
+## deviceSelected
+`DeviceSelectedEvent`
+
+An event sent by an editor when the current selected device was changed.
+
+This could be as a result of the client itself calling the `selectDevice`
+method or because the device changed for another reason (such as the user
+selecting a device in the editor directly, or the previously selected device
+is being removed).
+
+
+## debugSessionStarted
+`DebugSessionStartedEvent`
+
+An event sent by an editor when a new debug session is started.
+
+
+## debugSessionStopped
+`DebugSessionStoppedEvent`
+
+An event sent by an editor when a debug session ends.
+
+
+## debugSessionChanged
+`DebugSessionChangedEvent`
+
+An event sent by an editor when a debug session is changed.
+
+This could be happen when a VM Service URI becomes available for a session
+launched in debug mode, for example.
+
+
+# Type Definitions
+
+```dart
+/// An event sent by an editor when a debug session is changed.
+///
+/// This could be happen when a VM Service URI becomes available for a session
+/// launched in debug mode, for example.
+class DebugSessionChangedEvent {
+ EditorDebugSession debugSession;
+}
+
+/// An event sent by an editor when a new debug session is started.
+class DebugSessionStartedEvent {
+ EditorDebugSession debugSession;
+}
+
+/// An event sent by an editor when a debug session ends.
+class DebugSessionStoppedEvent {
+ String debugSessionId;
+}
+
+/// An event sent by an editor when a new device becomes available.
+class DeviceAddedEvent {
+ EditorDevice device;
+}
+
+/// An event sent by an editor when an existing device is updated.
+///
+/// The ID in this event always matches an existing device (that is, the ID
+/// never changes, or it would be considered a removal/add).
+interface class DeviceChangedEvent {
+ EditorDevice device;
+}
+
+/// An event sent by an editor when a device is no longer available.
+class DeviceRemovedEvent {
+ String deviceId;
+}
+
+/// An event sent by an editor when the current selected device was changed.
+///
+/// This could be as a result of the client itself calling the `selectDevice`
+/// method or because the device changed for another reason (such as the user
+/// selecting a device in the editor directly, or the previously selected device
+/// is being removed).
+class DeviceSelectedEvent {
+ /// The ID of the device being selected, or `null` if the current device is
+ /// being unselected without a new device being selected.
+ String? deviceId;
+}
+
+/// A debug session running in the editor.
+class EditorDebugSession {
+ String id;
+ String name;
+ String? vmServiceUri;
+ String? flutterMode;
+ String? flutterDeviceId;
+ String? debuggerType;
+ String? projectRootPath;
+}
+
+/// A device that is available in the editor.
+class EditorDevice {
+ String id;
+ String name;
+ String? category;
+ bool emulator;
+ String? emulatorId;
+ bool ephemeral;
+ String platform;
+ String? platformType;
+
+ /// Whether this device is supported for projects in the current workspace.
+ ///
+ /// If `false`, the `enablePlatformType` method can be used to ask the editor
+ /// to enable it (which will trigger a `deviceChanged` event after the changes
+ /// are made).
+ bool supported;
+}
+
+/// Parameters for the `enablePlatformTypeParams` request.
+class EnablePlatformTypeParams {
+ /// The `platformType` to enable.
+ ///
+ /// This should be taken from an [EditorDevice] that has `supported=false`.
+ String platformType;
+}
+
+/// The result of a `getDebugSessions` request.
+class GetDebugSessionsResult {
+ /// The current active debug sessions.
+ final List<EditorDebugSession> debugSessions;
+}
+
+/// The result of a `getDevices` request.
+class GetDevicesResult {
+ /// The current available devices.
+ List<EditorDevice> devices;
+
+ /// The ID of the device that is currently selected, if any.
+ String? selectedDeviceId;
+}
+
+/// Parameters for the `hotReload` request.
+class HotReloadParams {
+ /// The ID of the debug session to hot reload.
+ String debugSessionId;
+}
+
+/// Parameters for the `hotRestart` request.
+class HotRestartParams {
+ /// The ID of the debug session to hot restart.
+ String debugSessionId;
+}
+
+/// Parameters for the `navigateToCode` request.
+class NavigateToCodeParams {
+ /// The URI of the location to navigate to. Only `file://` URIs are supported
+ /// unless the service registration's `capabilities` indicate other schemes
+ /// are supported.
+ ///
+ /// Editors should return error code 144 if a caller passes a URI with an
+ /// unsupported scheme.
+ String uri;
+
+ /// Optional 1-based line number to navigate to.
+ int? line;
+
+ /// Optional 1-based column number to navigate to.
+ int? column;
+}
+
+/// Parameters for the `openDevToolsPage` request.
+class OpenDevToolsPageParams {
+ /// The debug session to to provide to DevTools.
+ String? debugSessionId;
+
+ /// The DevTools page to open.
+ String? page;
+
+ /// Whether to force opening in an external browser even if user preferences
+ /// are usually to be embedded.
+ bool? forceExternal;
+
+ /// Whether the target page requires a debug session.
+ ///
+ /// If so and [debugSessionId] is not supplied, the editor must provide a
+ /// debug session (which it may prompt the user to select).
+ bool? requiresDebugSession;
+
+ /// Whether the target page prefers (but does not require) a debug session.
+ ///
+ /// Unlike [requiresDebugSession], editors may skip prompting for/providing a
+ /// debug session unless there is already a single session that is the obvious
+ /// target.
+ bool? prefersDebugSession;
+}
+
+/// Parameters for the `selectDevice` request.
+class SelectDeviceParams {
+ /// The ID of the device to select (or `null` to unselect the current device).
+ String? deviceId;
+}
+```
diff --git a/pkg/dtd_impl/dtd_protocol.md b/pkg/dtd_impl/dtd_protocol.md
index df867b3..34e10eb 100644
--- a/pkg/dtd_impl/dtd_protocol.md
+++ b/pkg/dtd_impl/dtd_protocol.md
@@ -8,12 +8,18 @@
If you have access to `Dart` then you can use the [package:dtd](#packagedtd)
package.
-Otherwise, if you are creating your own client that will communicate with DTD using RPC,
-make sure to follow the entire
+Otherwise, if you are creating your own client that will communicate with DTD
+using RPC, make sure to follow the entire
[Dart Tooling Daemon RPC protocol](#dart-tooling-daemon-rpc-protocol) section.
The Dart Tooling Daemon Protocol uses JSON-RPC 2.0.
+## Common Services Definitions
+
+Some common services are defined to ensure that different tools can provide the
+same functionality consistently to DTD clients. Details of these can be found in
+[dtd_common_services](./dtd_common_services.md).
+
## Visualizing DTD interactions
The following diagrams visualize how the Dart Tooling Daemon interacts with