Class: Yoda::Server

Inherits:
Object
  • Object
show all
Includes:
TextDocument
Defined in:
lib/yoda/server.rb,
lib/yoda/server/session.rb,
lib/yoda/server/notifier.rb,
lib/yoda/server/deserializer.rb,
lib/yoda/server/hover_provider.rb,
lib/yoda/server/signature_provider.rb,
lib/yoda/server/completion_provider.rb,
lib/yoda/server/definition_provider.rb,
lib/yoda/server/initialization_provider.rb

Defined Under Namespace

Modules: TextDocument Classes: CompletionProvider, DefinitionProvider, Deserializer, HoverProvider, InitializationProvider, Notifier, Session, SignatureProvider

Constant Summary collapse

LSP =
::LanguageServer::Protocol

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TextDocument

#handle_text_document_completion, #handle_text_document_definition, #handle_text_document_did_change, #handle_text_document_did_open, #handle_text_document_did_save, #handle_text_document_hover, #handle_text_document_signature_help

Constructor Details

#initializeServer

Returns a new instance of Server.



45
46
47
48
49
# File 'lib/yoda/server.rb', line 45

def initialize
  @reader = LSP::Transport::Stdio::Reader.new
  @writer = LSP::Transport::Stdio::Writer.new
  @after_notifications = []
end

Instance Attribute Details

#after_notificationsArray<Hash> (readonly)

Returns:

  • (Array<Hash>)


43
44
45
# File 'lib/yoda/server.rb', line 43

def after_notifications
  @after_notifications
end

#completion_providerObject (readonly)

Returns the value of attribute completion_provider.



31
32
33
# File 'lib/yoda/server.rb', line 31

def completion_provider
  @completion_provider
end

#definition_providerObject (readonly)

Returns the value of attribute definition_provider.



40
41
42
# File 'lib/yoda/server.rb', line 40

def definition_provider
  @definition_provider
end

#hover_providerObject (readonly)

Returns the value of attribute hover_provider.



34
35
36
# File 'lib/yoda/server.rb', line 34

def hover_provider
  @hover_provider
end

#readerObject (readonly)

Returns the value of attribute reader.



22
23
24
# File 'lib/yoda/server.rb', line 22

def reader
  @reader
end

#sessionResponser (readonly)

Returns:

  • (Responser)


28
29
30
# File 'lib/yoda/server.rb', line 28

def session
  @session
end

#signature_providerObject (readonly)

Returns the value of attribute signature_provider.



37
38
39
# File 'lib/yoda/server.rb', line 37

def signature_provider
  @signature_provider
end

#writerObject (readonly)

Returns the value of attribute writer.



25
26
27
# File 'lib/yoda/server.rb', line 25

def writer
  @writer
end

Class Method Details

.deserialize(hash) ⇒ Object



17
18
19
# File 'lib/yoda/server.rb', line 17

def self.deserialize(hash)
  Deserializer.new.deserialize(hash || {})
end

Instance Method Details

#callback(request) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/yoda/server.rb', line 98

def callback(request)
  if method_name = resolve(request_registrations, request[:method])
    send(method_name, self.class.deserialize(request[:params] || {}))
  elsif method_name = resolve(notification_registrations, request[:method])
    send(method_name, self.class.deserialize(request[:params] || {}))
    nil
  end
end

#handle_exit(_params) ⇒ Object



185
186
# File 'lib/yoda/server.rb', line 185

def handle_exit(_params)
end

#handle_initialize(params) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/yoda/server.rb', line 142

def handle_initialize(params)
  @session = Session.new(params[:root_uri])
  @completion_provider = CompletionProvider.new(@session)
  @hover_provider = HoverProvider.new(@session)
  @signature_provider = SignatureProvider.new(@session)
  @definition_provider = DefinitionProvider.new(@session)

  (InitializationProvider.new(session: session, notifier: notifier).provide || []).each { |notification| after_notifications.push(notification) }

  LSP::Interface::InitializeResult.new(
    capabilities: LSP::Interface::ServerCapabilities.new(
      text_document_sync: LSP::Interface::TextDocumentSyncOptions.new(
        change: LSP::Constant::TextDocumentSyncKind::FULL,
        save: LSP::Interface::SaveOptions.new(
          include_text: true,
        ),
      ),
      completion_provider: LSP::Interface::CompletionOptions.new(
        resolve_provider: false,
        trigger_characters: ['.', '@', '[', ':', '!', '<'],
      ),
      hover_provider: true,
      definition_provider: true,
      signature_help_provider: LSP::Interface::SignatureHelpOptions.new(
        trigger_characters: ['(', ','],
      ),
    ),
  )
rescue => e
  LanguageServer::Protocol::Interface::ResponseError.new(
    message: "Failed to initialize yoda: #{e.class} #{e.message}",
    code: LanguageServer::Protocol::Constant::InitializeError::UNKNOWN_PROTOCOL_VERSION,
    data: LanguageServer::Protocol::Interface::InitializeError.new(retry: false),
  )
end

#handle_initialized(_params) ⇒ Object



178
179
180
# File 'lib/yoda/server.rb', line 178

def handle_initialized(_params)
  session.client_initialized = true
end

#handle_shutdown(_params) ⇒ Object



182
183
# File 'lib/yoda/server.rb', line 182

def handle_shutdown(_params)
end

#notification_registrationsObject



130
131
132
133
134
135
136
137
138
139
140
# File 'lib/yoda/server.rb', line 130

def notification_registrations
  {
    initialized: :handle_initialized,
    exit: :handle_exit,
    textDocument: {
      didChange: :handle_text_document_did_change,
      didOpen: :handle_text_document_did_open,
      didSave: :handle_text_document_did_save,
    },
  }
end

#notifierNotifier

Returns:



52
53
54
# File 'lib/yoda/server.rb', line 52

def notifier
  @notifier ||= Notifier.new(self)
end

#process_after_notificationsObject



74
75
76
77
78
# File 'lib/yoda/server.rb', line 74

def process_after_notifications
  while notification = after_notifications.pop
    send_notification(**notification)
  end
end

#request_registrationsObject



117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/yoda/server.rb', line 117

def request_registrations
  {
    initialize: :handle_initialize,
    shutdown: :handle_shutdown,
    textDocument: {
      completion: :handle_text_document_completion,
      hover: :handle_text_document_hover,
      signatureHelp: :handle_text_document_signature_help,
      definition: :handle_text_document_definition,
    },
  }
end

#resolve(hash, key) ⇒ Symbol?

Parameters:

  • hash (Hash)
  • key (String, Symbol)

Returns:

  • (Symbol, nil)


110
111
112
113
114
115
# File 'lib/yoda/server.rb', line 110

def resolve(hash, key)
  resolved = key.to_s.split('/').reduce(hash) do |scope, key|
    (scope || {})[key.to_sym]
  end
  resolved.is_a?(Symbol) && resolved
end

#runObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/yoda/server.rb', line 56

def run
  reader.read do |request|
    begin
      if result = callback(request)
        if result.is_a?(LanguageServer::Protocol::Interface::ResponseError)
          send_error(id: request[:id], error: result)
        else
          send_response(id: request[:id], result: result)
        end
      end
      process_after_notifications if session&.client_initialized
    rescue StandardError => ex
      Logger.warn ex
      Logger.warn ex.backtrace
    end
  end
end

#send_error(id:, error:) ⇒ Object

Parameters:

  • method (String)
  • error (Object)


94
95
96
# File 'lib/yoda/server.rb', line 94

def send_error(id:, error:)
  writer.write(id: id, error: error)
end

#send_notification(method:, params:) ⇒ Object

Parameters:

  • method (String)
  • params (Object)


82
83
84
# File 'lib/yoda/server.rb', line 82

def send_notification(method:, params:)
  writer.write(method: method, params: params)
end

#send_response(id:, result:) ⇒ Object

Parameters:

  • id (String)
  • result (Object)


88
89
90
# File 'lib/yoda/server.rb', line 88

def send_response(id:, result:)
  writer.write(id: id, result: result)
end