Class: Rigor::LanguageServer::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/language_server/server.rb

Overview

LSP server lifecycle state machine + JSON-RPC method dispatcher. State machine: :uninitialized:initialized:shutdown:exited. #dispatch routes (method, params) to the matching handler and returns the response payload (nil for notifications); out-of-state requests return InvalidRequest (-32002) / MethodNotFound (-32601). Full v1 capability surface (document sync, publishDiagnostics, hover, completion, sig-help, folding, selection, and watched-file invalidation) is implemented.

Constant Summary collapse

ERROR_PARSE_ERROR =

JSON-RPC error codes per LSP spec § "Response Message".

-32_700
ERROR_INVALID_REQUEST =
-32_600
ERROR_METHOD_NOT_FOUND =
-32_601
ERROR_INVALID_PARAMS =
-32_602
ERROR_INTERNAL_ERROR =
-32_603
# LSP-specific reserved codes.
ERROR_SERVER_NOT_INITIALIZED =

LSP-specific reserved codes.

-32_002
ERROR_INVALID_REQUEST_AFTER_SHUTDOWN =
-32_600
TEXT_DOCUMENT_SYNC_FULL =

TextDocumentSyncKind::Full = 1. Slice 10 (deferred) promotes to Incremental = 2.

1
PRE_INITIALIZE_METHODS =

Methods callable BEFORE initialize. Per LSP spec § 3 only initialize and exit are allowed pre-initialization; every other request returns ServerNotInitialized. We also accept shutdown so a sequence like initialize → shutdown → exit (the conformance harness) round-trips even when the client skips real work.

%w[initialize shutdown exit].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(buffer_table: BufferTable.new, publisher: nil, hover_provider: nil, document_symbol_provider: nil, completion_provider: nil, signature_help_provider: nil, folding_range_provider: nil, selection_range_provider: nil, project_context: nil) ⇒ Server

Returns a new instance of Server.

Parameters:

  • completion_provider (Rigor::LanguageServer::CompletionProvider, nil) (defaults to: nil)

    resolves textDocument/completion. Nil → MethodNotFound.

  • signature_help_provider (Rigor::LanguageServer::SignatureHelpProvider, nil) (defaults to: nil)

    resolves textDocument/signatureHelp. Nil → MethodNotFound.

  • project_context (Rigor::LanguageServer::ProjectContext, nil) (defaults to: nil)

    the per-session cache of Environment + Cache::Store the providers read on every request. When present, workspace/didChangeWatchedFiles and workspace/didChangeConfiguration invalidate the cache; nil means "no project context": each request rebuilds env from scratch (mainly for specs and backward compatibility).



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rigor/language_server/server.rb', line 47

def initialize(buffer_table: BufferTable.new, publisher: nil, # rubocop:disable Metrics/ParameterLists
               hover_provider: nil, document_symbol_provider: nil,
               completion_provider: nil, signature_help_provider: nil,
               folding_range_provider: nil, selection_range_provider: nil,
               project_context: nil)
  @state = :uninitialized
  @exit_code = nil
  @buffer_table = buffer_table
  @publisher = publisher
  @hover_provider = hover_provider
  @document_symbol_provider = document_symbol_provider
  @completion_provider = completion_provider
  @signature_help_provider = signature_help_provider
  @folding_range_provider = folding_range_provider
  @selection_range_provider = selection_range_provider
  @project_context = project_context
end

Instance Attribute Details

#buffer_tableObject (readonly)

Returns the value of attribute buffer_table.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def buffer_table
  @buffer_table
end

#completion_providerObject (readonly)

Returns the value of attribute completion_provider.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def completion_provider
  @completion_provider
end

#document_symbol_providerObject (readonly)

Returns the value of attribute document_symbol_provider.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def document_symbol_provider
  @document_symbol_provider
end

#exit_codeObject (readonly)

Returns the value of attribute exit_code.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def exit_code
  @exit_code
end

#folding_range_providerObject (readonly)

Returns the value of attribute folding_range_provider.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def folding_range_provider
  @folding_range_provider
end

#hover_providerObject (readonly)

Returns the value of attribute hover_provider.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def hover_provider
  @hover_provider
end

#project_contextObject (readonly)

Returns the value of attribute project_context.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def project_context
  @project_context
end

#publisherObject (readonly)

Returns the value of attribute publisher.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def publisher
  @publisher
end

#selection_range_providerObject (readonly)

Returns the value of attribute selection_range_provider.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def selection_range_provider
  @selection_range_provider
end

#signature_help_providerObject (readonly)

Returns the value of attribute signature_help_provider.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def signature_help_provider
  @signature_help_provider
end

#stateObject (readonly)

Returns the value of attribute state.



33
34
35
# File 'lib/rigor/language_server/server.rb', line 33

def state
  @state
end

Instance Method Details

#dispatch(method, params = nil) ⇒ Hash?

Routes one LSP method call.

Parameters:

  • method (String)

    the LSP method name (e.g. "initialize").

  • params (Hash, nil) (defaults to: nil)

    the LSP params payload (Hash for request / notification methods; nil for the empty case).

Returns:

  • (Hash, nil)

    one of:

    • the response result Hash for request methods,
    • nil for notification methods,
    • { error: { code:, message: } } for state / shape errors.


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rigor/language_server/server.rb', line 81

def dispatch(method, params = nil) # rubocop:disable Metrics/CyclomaticComplexity
  return state_violation_response(method) unless method_allowed_in_state?(method)

  case method
  when "initialize"             then handle_initialize(params)
  when "initialized"            then handle_initialized
  when "shutdown"               then handle_shutdown
  when "exit"                   then handle_exit
  when "textDocument/didOpen"   then handle_did_open(params)
  when "textDocument/didChange" then handle_did_change(params)
  when "textDocument/didClose"  then handle_did_close(params)
  when "textDocument/hover"               then handle_hover(params)
  when "textDocument/documentSymbol"      then handle_document_symbol(params)
  when "textDocument/completion"          then handle_completion(params)
  when "textDocument/signatureHelp"       then handle_signature_help(params)
  when "textDocument/foldingRange"        then handle_folding_range(params)
  when "textDocument/selectionRange"      then handle_selection_range(params)
  when "workspace/didChangeWatchedFiles"  then handle_did_change_watched_files(params)
  when "workspace/didChangeConfiguration" then handle_did_change_configuration(params)
  else
    method_not_found(method)
  end
end

#exited?Boolean

Returns true once the client has called exit and the server has set its terminal exit code. The CLI loop reads this between dispatches to know when to stop.

Returns:

  • (Boolean)

    true once the client has called exit and the server has set its terminal exit code. The CLI loop reads this between dispatches to know when to stop.



68
69
70
# File 'lib/rigor/language_server/server.rb', line 68

def exited?
  @state == :exited
end