Module: RubynCode::IDE::Protocol

Defined in:
lib/rubyn_code/ide/protocol.rb

Overview

JSON-RPC 2.0 protocol layer for the IDE server. Pure data — no side effects, no I/O beyond JSON serialisation.

Constant Summary collapse

JSONRPC_VERSION =
'2.0'
PARSE_ERROR =

── Standard JSON-RPC 2.0 error codes ──────────────────────────────

-32_700
INVALID_REQUEST =
-32_600
METHOD_NOT_FOUND =
-32_601
INVALID_PARAMS =
-32_602
INTERNAL_ERROR =
-32_603
AGENT_BUSY =

── Custom error codes ─────────────────────────────────────────────

-1
SESSION_NOT_FOUND =
-2
BUDGET_EXCEEDED =
-3

Class Method Summary collapse

Class Method Details

.error(id, code, message) ⇒ Object

Build an error response hash.



67
68
69
70
71
72
73
74
75
76
# File 'lib/rubyn_code/ide/protocol.rb', line 67

def error(id, code, message)
  {
    'jsonrpc' => JSONRPC_VERSION,
    'id' => id,
    'error' => {
      'code' => code,
      'message' => message
    }
  }
end

.notification(method, params) ⇒ Object

Build a notification hash (no id).



79
80
81
82
83
84
85
# File 'lib/rubyn_code/ide/protocol.rb', line 79

def notification(method, params)
  {
    'jsonrpc' => JSONRPC_VERSION,
    'method' => method,
    'params' => stringify_keys_deep(params)
  }
end

.parse(line) ⇒ Object

Parse a JSON string into a request hash. Returns either a valid request hash or an error response hash. – JSON-RPC validation checks



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rubyn_code/ide/protocol.rb', line 29

def parse(line)
  begin
    data = JSON.parse(line)
  rescue JSON::ParserError
    return error(nil, PARSE_ERROR, 'Parse error: invalid JSON')
  end

  return error(nil, INVALID_REQUEST, 'Invalid request: expected JSON object') unless data.is_a?(Hash)

  unless data['jsonrpc'] == JSONRPC_VERSION
    return error(data['id'], INVALID_REQUEST, 'Invalid request: missing or wrong "jsonrpc" version')
  end

  # Response objects (containing "result" or "error") are valid
  # JSON-RPC 2.0 messages that don't carry a "method".
  is_response = data.key?('result') || data.key?('error')

  unless is_response || data['method'].is_a?(String)
    return error(data['id'], INVALID_REQUEST, 'Invalid request: "method" must be a string')
  end

  if data.key?('params') && !data['params'].is_a?(Hash) && !data['params'].is_a?(Array)
    return error(data['id'], INVALID_PARAMS, 'Invalid params: "params" must be an object or array')
  end

  data
end

.response(id, result) ⇒ Object

Build a success response hash.



58
59
60
61
62
63
64
# File 'lib/rubyn_code/ide/protocol.rb', line 58

def response(id, result)
  {
    'jsonrpc' => JSONRPC_VERSION,
    'id' => id,
    'result' => stringify_keys_deep(result)
  }
end

.serialize(hash) ⇒ Object

Serialise a hash to a JSON string terminated by a newline.



88
89
90
# File 'lib/rubyn_code/ide/protocol.rb', line 88

def serialize(hash)
  "#{JSON.generate(hash)}\n"
end