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.



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

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).



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

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.



28
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
# File 'lib/rubyn_code/ide/protocol.rb', line 28

def parse(line) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity -- JSON-RPC validation checks
  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.



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

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.



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

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