Add section for standard service methods and navigate to code

This is a proposal for a standardized service method for IDEs to register for navigating to code. This is intended to replace the `navigate` `ToolEvent` since there isn't a way for an IDE to respond to that notification and verify that the DevTools-IDE interaction was successful.

Change-Id: I92c0ad36b3f0557ffb80b868b466808ef3c3563d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/375080
Reviewed-by: Ben Konyi <bkonyi@google.com>
Commit-Queue: Helin Shiah <helinx@google.com>
diff --git a/pkg/dtd/lib/src/rpc_error_codes.dart b/pkg/dtd/lib/src/rpc_error_codes.dart
index 4a19e80..8bfa865 100644
--- a/pkg/dtd/lib/src/rpc_error_codes.dart
+++ b/pkg/dtd/lib/src/rpc_error_codes.dart
@@ -35,6 +35,7 @@
   static const kFileDoesNotExist = 141;
   static const kPermissionDenied = 142;
   static const kExpectsUriParamWithFileScheme = 143;
+  static const kUnknownUriScheme = 144;
 
   // Experimental (used in private rpcs).
   // static const kFileSystemAlreadyExists = 1001;
@@ -53,5 +54,6 @@
     kFileDoesNotExist: 'The file does not exist',
     kPermissionDenied: 'Permission denied',
     kExpectsUriParamWithFileScheme: 'File scheme expected on uri',
+    kUnknownUriScheme: 'URI scheme is not supported',
   };
 }
diff --git a/pkg/dtd_impl/dtd_common_services.md b/pkg/dtd_impl/dtd_common_services.md
new file mode 100644
index 0000000..caf48e1
--- /dev/null
+++ b/pkg/dtd_impl/dtd_common_services.md
@@ -0,0 +1,109 @@
+# Common service methods
+
+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.
+
+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.
+
+## 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.
+
+### Registering the method with DTD
+
+This is what the client handling navigate to code requests (i.e. IDE) should send to DTD:
+
+```json
+{
+  "jsonrpc": "2.0",
+  "method": "registerService",
+  "params": {
+    "service": "Editor",
+    "method": "navigateToCode",
+    "capabilities": {
+      "supportedSchemes": ["file", "dart-macro-file"],
+    }
+  },
+  "id": "0"
+}
+```
+
+### Request Parameters
+
+These are the parameters a client should send when requesting an editor navigate to code.
+
+- `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
+
+```json
+{
+  "jsonrpc": "2.0",
+  "method": "Editor.navigateToCode",
+  "params": {
+    "file": "file:///path/to/file.dart",
+    "line": 1,
+    "column": 2,
+  },
+  "id": "0"
+}
+```
+
+### Result
+
+These are the parameters in a result:
+
+- `String type` - one of `Success` or `Failure`.
+- optional `String errorCode` - a specific error code for a well-known failure type.
+
+    | Error code    | Description |
+    | -------- | ------- |
+    | 144  | The URI's scheme is not recognized by the editor. |
+
+- optional `String errorMessage` - a freeform message about the error.
+
+#### Examples
+
+If navigation in the editor is successful, a Success result should be returned.
+
+```json
+{
+  "jsonrpc": "2.0",
+  "result": {"type": "Success"},
+  "id": "0"
+}
+```
+
+Otherwise, the client can return an error code and/or an error message.
+
+```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,
+          }
+        }
+      }
+    }
+  },
+  "id": "0"
+}
+```
diff --git a/pkg/dtd_impl/dtd_protocol.md b/pkg/dtd_impl/dtd_protocol.md
index bd5c8e9..df867b3 100644
--- a/pkg/dtd_impl/dtd_protocol.md
+++ b/pkg/dtd_impl/dtd_protocol.md
@@ -80,19 +80,19 @@
     participant dtd as Dart Tooling Daemon
     participant c2 as Client 2
 
-    Note right of c1: Client 1 registers the foo.bar method.
-    c1->>dtd: registerService(service: "foo", method: "bar")
+    Note right of c1: Client 1 registers the Foo.bar method.
+    c1->>dtd: registerService(service: "Foo", method: "bar")
     activate dtd
-    dtd-->>c2: ServiceRegistered({"service": "foo", "method": "bar"})
+    dtd-->>c2: ServiceRegistered({"service": "Foo", "method": "bar"})
     dtd-->>c1: Success
     deactivate dtd
 
-    Note left of c2: Client 2 calls foo.bar
-    c2->>dtd: foo.bar({{"a": 1, "b": 2}})
+    Note left of c2: Client 2 calls Foo.bar
+    c2->>dtd: Foo.bar({{"a": 1, "b": 2}})
     activate dtd
 
     Note left of dtd: dtd forwards the service method call to Client 1.
-    dtd->>c1: foo.bar({{"a": 1, "b": 2}})
+    dtd->>c1: Foo.bar({{"a": 1, "b": 2}})
     activate c1
 
     Note right of c1: Client 1 handles the<br/>request and responds to the Dart Tooling Daemon.
@@ -105,7 +105,7 @@
 
     Note right of c1: Client 1 disconnects.
     activate dtd
-    dtd-->>c2: ServiceUnregistered({"service": "foo", "method": "bar"})
+    dtd-->>c2: ServiceUnregistered({"service": "Foo", "method": "bar"})
     deactivate dtd
 ```
 
@@ -118,7 +118,7 @@
   "jsonrpc": "2.0",
   "method": "registerService",
   "params": {
-    "service": "foo",
+    "service": "Foo",
     "method": "bar",
     "capabilities": {
       "supportsAdditionalFoo": true,
@@ -139,7 +139,7 @@
         "streamId": "Service",
         "eventKind": "ServiceRegistered",
         "eventData": {
-          "service": "foo",
+          "service": "Foo",
           "method": "bar",
           // Capabilities are included only if the client provided them
           "capabilities": {
@@ -157,7 +157,7 @@
         "streamId": "Service",
         "eventKind": "ServiceUnregistered",
         "eventData": {
-          "service": "foo",
+          "service": "Foo",
           "method": "bar",
           // Unregistered events do not contain capabilities
         }
@@ -348,7 +348,7 @@
   "jsonrpc": "2.0",
   "method": "registerService",
   "params": {
-    "service": "foo",
+    "service": "Foo",
     "method": "bar",
   },
   "id": "2"
@@ -392,7 +392,7 @@
 
 Assume that a client has registered a service method with:
 
-- service: `foo`
+- service: `Foo`
 - method: `bar`
 
 Then calling that service method might look like:
@@ -400,7 +400,7 @@
 ```json
 {
   "jsonrpc": "2.0",
-  "method": "foo.bar",
+  "method": "Foo.bar",
   "params": { "baz": 3 },
   "id": "2"
 }
@@ -480,7 +480,7 @@
 
 Assume that a client has registered a service method with:
 
-- service: `foo`
+- service: `Foo`
 - method: `bar`
 
 Then calling that service method might look like:
@@ -488,7 +488,7 @@
 ```json
 {
   "jsonrpc": "2.0",
-  "method": "foo.bar",
+  "method": "Foo.bar",
   "params": { "baz": 3 },
   "id": "2"
 }