sequenceDiagram
participant C as browser workbench
participant S as host server
C->>S: ClientPacket { version: protocol_version() }
alt version matches
S-->>C: ServerPacket { version, payload }
else version differs
S-->>C: RemoteError (negotiation failed)
end///|
test "only the exact protocol version negotiates" {
debug_inspect(
(
@remote_protocol.protocol_version(),
@remote_protocol.negotiate_protocol_version(
@remote_protocol.protocol_version(),
),
@remote_protocol.negotiate_protocol_version(
@remote_protocol.protocol_version() - 1,
),
@remote_protocol.negotiate_protocol_version(999),
),
content=(
#|(
#| 6,
#| ProtocolAccepted(6),
#| ProtocolRejected(
#| {
#| code: ProtocolUnsupportedVersion,
#| message: "Unsupported remote protocol version 5",
#| request_id: "",
#| provider_code: "",
#| },
#| ),
#| ProtocolRejected(
#| {
#| code: ProtocolUnsupportedVersion,
#| message: "Unsupported remote protocol version 999",
#| request_id: "",
#| provider_code: "",
#| },
#| ),
#|)
),
)
}///|
test "malformed input decodes to a structured error, never a raise" {
debug_inspect(
["", "not json at all", "{}", "{\"version\":1,\"kind\":\"hover\"}"].map(raw => {
match @remote_protocol.decode_client_packet(raw) {
DecodedClientPacket(_) => "decoded"
ClientPacketDecodeError(error) => "error:" + error.code.to_string()
}
}),
content=(
#|[
#| "error:InvalidJson",
#| "error:InvalidJson",
#| "error:UnsupportedVersion",
#| "error:UnsupportedVersion",
#|]
),
)
}///|
test "error codes round-trip, and unknown input falls back" {
let codes : Array[@remote_protocol.ProtocolErrorCode] = [
ProtocolInvalidJson,
ProtocolUnsupportedVersion,
ProtocolUnknownPacket,
ProtocolInvalidPacket,
ProtocolInvalidUri,
ProtocolProviderError,
]
debug_inspect(
(
codes.map(code => {
(
code.to_string(),
@remote_protocol.ProtocolErrorCode::from_string(code.to_string()) ==
code,
)
}),
@remote_protocol.ProtocolErrorCode::from_string("SomethingNewer"),
),
content=(
#|(
#| [
#| ("InvalidJson", true),
#| ("UnsupportedVersion", true),
#| ("UnknownPacket", true),
#| ("InvalidPacket", true),
#| ("InvalidUri", true),
#| ("ProviderError", true),
#| ],
#| ProtocolInvalidPacket,
#|)
),
)
}pub(all) enum ClientPacket {
ResolveDirectory(DocumentRequest)
OpenDocument(DocumentRequest)
WatchDocument(DocumentRequest)
CloseDocument(DocumentRequest)
Hover(DocumentPositionRequest)
Definition(DocumentPositionRequest)
References(DocumentPositionRequest)
DocumentSymbols(DocumentRevisionRequest)
ListHostDirectory(HostPathRequest)
SwitchWorkspace(HostPathRequest)
} derive(Debug)impl ToJson for ClientPacketpub enum ClientPacketDecodeResult {
DecodedClientPacket(ClientPacket)
ClientPacketDecodeError(ProtocolError)
} derive(Debug)pub(all) struct DiagnosticsPayload {
uri : Uri
revision : String
diagnostics : Array[Diagnostic]
} derive(Debug)pub(all) struct DocumentSymbolsResultPayload {
id : String
uri : Uri
revision : String
symbols : Array[DocumentSymbol]
} derive(Debug)pub(all) struct HostDirectoryListedPayload {
id : String
listing : HostDirectoryListing
} derive(Debug)pub(all) struct HostDirectoryListing {
path : String
parent : String?
entries : Array[HostDirectoryEntry]
} derive(Eq, Debug)pub struct ProtocolError {
code : ProtocolErrorCode
message : String
request_id : String
provider_code : String
} derive(Debug)impl ToJson for ProtocolErrorfn ProtocolError::ProtocolError(code : ProtocolErrorCode, message : String, request_id? : String, provider_code? : String) -> ProtocolErrorfn ProtocolError::from_file_system_error(error : FileSystemProviderError, request_id? : String) -> ProtocolErrorpub(all) struct ReferencesResultPayload {
id : String
uri : Uri
revision : String
references : Array[ReferenceItem]
} derive(Debug)pub(all) enum ServerPacket {
DirectoryResolved(DirectoryResolvedPayload)
DocumentLoaded(DocumentPayload)
DocumentChanged(DocumentPayload)
Diagnostics(DiagnosticsPayload)
HoverResult(HoverResultPayload)
DefinitionResult(DefinitionResultPayload)
ReferencesResult(ReferencesResultPayload)
DocumentSymbolsResult(DocumentSymbolsResultPayload)
HostDirectoryListed(HostDirectoryListedPayload)
WorkspaceSwitched(WorkspaceSwitchedPayload)
RemoteError(ProtocolError)
} derive(Debug)impl ToJson for ServerPacketpub enum ServerPacketDecodeResult {
DecodedServerPacket(ServerPacket)
ServerPacketDecodeError(ProtocolError)
} derive(Debug)Install
Download zipReadonly MoonBit code viewer harness inspired by Monaco and CodeMirror.