puppet-editor-services 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +510 -0
- data/CODEOWNERS +2 -0
- data/CODE_OF_CONDUCT.md +46 -0
- data/CONTRIBUTING.md +54 -0
- data/Gemfile +53 -0
- data/LICENSE +201 -0
- data/README.md +308 -0
- data/Rakefile +185 -0
- data/bin/puppet-debugserver +8 -0
- data/bin/puppet-languageserver +7 -0
- data/bin/puppet-languageserver-sidecar +7 -0
- data/lib/dsp/dsp.rb +7 -0
- data/lib/dsp/dsp_base.rb +62 -0
- data/lib/dsp/dsp_protocol.rb +4619 -0
- data/lib/lsp/lsp.rb +10 -0
- data/lib/lsp/lsp_base.rb +63 -0
- data/lib/lsp/lsp_custom.rb +170 -0
- data/lib/lsp/lsp_enums.rb +143 -0
- data/lib/lsp/lsp_protocol.rb +2785 -0
- data/lib/lsp/lsp_protocol_callhierarchy.proposed.rb +239 -0
- data/lib/lsp/lsp_protocol_colorprovider.rb +100 -0
- data/lib/lsp/lsp_protocol_configuration.rb +82 -0
- data/lib/lsp/lsp_protocol_declaration.rb +73 -0
- data/lib/lsp/lsp_protocol_foldingrange.rb +129 -0
- data/lib/lsp/lsp_protocol_implementation.rb +75 -0
- data/lib/lsp/lsp_protocol_progress.rb +200 -0
- data/lib/lsp/lsp_protocol_selectionrange.rb +79 -0
- data/lib/lsp/lsp_protocol_sematictokens.proposed.rb +340 -0
- data/lib/lsp/lsp_protocol_typedefinition.rb +75 -0
- data/lib/lsp/lsp_protocol_workspacefolders.rb +174 -0
- data/lib/lsp/lsp_types.rb +1534 -0
- data/lib/puppet-debugserver/debug_session/break_points.rb +137 -0
- data/lib/puppet-debugserver/debug_session/flow_control.rb +161 -0
- data/lib/puppet-debugserver/debug_session/hook_handlers.rb +295 -0
- data/lib/puppet-debugserver/debug_session/puppet_session_run_mode.rb +66 -0
- data/lib/puppet-debugserver/debug_session/puppet_session_state.rb +122 -0
- data/lib/puppet-debugserver/hooks.rb +132 -0
- data/lib/puppet-debugserver/message_handler.rb +277 -0
- data/lib/puppet-debugserver/puppet_debug_session.rb +541 -0
- data/lib/puppet-debugserver/puppet_monkey_patches.rb +118 -0
- data/lib/puppet-languageserver/client_session_state.rb +119 -0
- data/lib/puppet-languageserver/crash_dump.rb +50 -0
- data/lib/puppet-languageserver/epp/validation_provider.rb +34 -0
- data/lib/puppet-languageserver/facter_helper.rb +25 -0
- data/lib/puppet-languageserver/global_queues/sidecar_queue.rb +205 -0
- data/lib/puppet-languageserver/global_queues/single_instance_queue.rb +126 -0
- data/lib/puppet-languageserver/global_queues/validation_queue.rb +102 -0
- data/lib/puppet-languageserver/global_queues.rb +16 -0
- data/lib/puppet-languageserver/manifest/completion_provider.rb +331 -0
- data/lib/puppet-languageserver/manifest/definition_provider.rb +99 -0
- data/lib/puppet-languageserver/manifest/document_symbol_provider.rb +228 -0
- data/lib/puppet-languageserver/manifest/folding_provider.rb +226 -0
- data/lib/puppet-languageserver/manifest/format_on_type_provider.rb +143 -0
- data/lib/puppet-languageserver/manifest/hover_provider.rb +221 -0
- data/lib/puppet-languageserver/manifest/signature_provider.rb +169 -0
- data/lib/puppet-languageserver/manifest/validation_provider.rb +127 -0
- data/lib/puppet-languageserver/message_handler.rb +462 -0
- data/lib/puppet-languageserver/providers.rb +18 -0
- data/lib/puppet-languageserver/puppet_helper.rb +108 -0
- data/lib/puppet-languageserver/puppet_lexer_helper.rb +55 -0
- data/lib/puppet-languageserver/puppet_monkey_patches.rb +39 -0
- data/lib/puppet-languageserver/puppet_parser_helper.rb +212 -0
- data/lib/puppet-languageserver/puppetfile/validation_provider.rb +185 -0
- data/lib/puppet-languageserver/server_capabilities.rb +48 -0
- data/lib/puppet-languageserver/session_state/document_store.rb +272 -0
- data/lib/puppet-languageserver/session_state/language_client.rb +239 -0
- data/lib/puppet-languageserver/session_state/object_cache.rb +162 -0
- data/lib/puppet-languageserver/sidecar_protocol.rb +532 -0
- data/lib/puppet-languageserver/uri_helper.rb +46 -0
- data/lib/puppet-languageserver-sidecar/cache/base.rb +36 -0
- data/lib/puppet-languageserver-sidecar/cache/filesystem.rb +111 -0
- data/lib/puppet-languageserver-sidecar/cache/null.rb +27 -0
- data/lib/puppet-languageserver-sidecar/facter_helper.rb +41 -0
- data/lib/puppet-languageserver-sidecar/puppet_environment_monkey_patches.rb +52 -0
- data/lib/puppet-languageserver-sidecar/puppet_helper.rb +281 -0
- data/lib/puppet-languageserver-sidecar/puppet_modulepath_monkey_patches.rb +146 -0
- data/lib/puppet-languageserver-sidecar/puppet_monkey_patches.rb +9 -0
- data/lib/puppet-languageserver-sidecar/puppet_parser_helper.rb +77 -0
- data/lib/puppet-languageserver-sidecar/puppet_strings_helper.rb +399 -0
- data/lib/puppet-languageserver-sidecar/puppet_strings_monkey_patches.rb +16 -0
- data/lib/puppet-languageserver-sidecar/sidecar_protocol_extensions.rb +16 -0
- data/lib/puppet-languageserver-sidecar/workspace.rb +89 -0
- data/lib/puppet_debugserver.rb +164 -0
- data/lib/puppet_editor_services/connection/base.rb +62 -0
- data/lib/puppet_editor_services/connection/stdio.rb +25 -0
- data/lib/puppet_editor_services/connection/tcp.rb +34 -0
- data/lib/puppet_editor_services/handler/base.rb +16 -0
- data/lib/puppet_editor_services/handler/debug_adapter.rb +63 -0
- data/lib/puppet_editor_services/handler/json_rpc.rb +133 -0
- data/lib/puppet_editor_services/logging.rb +45 -0
- data/lib/puppet_editor_services/protocol/base.rb +27 -0
- data/lib/puppet_editor_services/protocol/debug_adapter.rb +135 -0
- data/lib/puppet_editor_services/protocol/debug_adapter_messages.rb +171 -0
- data/lib/puppet_editor_services/protocol/json_rpc.rb +241 -0
- data/lib/puppet_editor_services/protocol/json_rpc_messages.rb +200 -0
- data/lib/puppet_editor_services/server/base.rb +42 -0
- data/lib/puppet_editor_services/server/stdio.rb +85 -0
- data/lib/puppet_editor_services/server/tcp.rb +349 -0
- data/lib/puppet_editor_services/server.rb +15 -0
- data/lib/puppet_editor_services/version.rb +36 -0
- data/lib/puppet_editor_services.rb +8 -0
- data/lib/puppet_languageserver.rb +263 -0
- data/lib/puppet_languageserver_sidecar.rb +361 -0
- data/puppet-debugserver +11 -0
- data/puppet-editor-services.gemspec +29 -0
- data/puppet-languageserver +15 -0
- data/puppet-languageserver-sidecar +14 -0
- metadata +240 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PuppetDebugServer
|
|
4
|
+
module DebugSession
|
|
5
|
+
# The actual and saved state of Puppet during a debug session.
|
|
6
|
+
class PuppetSessionState
|
|
7
|
+
# The actual, current state of Puppet during a debug session.
|
|
8
|
+
# @return [PuppetDebugServer::DebugSession::ActualPuppetSessionState]
|
|
9
|
+
attr_reader :actual
|
|
10
|
+
|
|
11
|
+
# The state of Puppet when a debug session was paused, typically during a breakpoint or exception.
|
|
12
|
+
# @return [PuppetDebugServer::DebugSession::SavedPuppetSessionState]
|
|
13
|
+
attr_reader :saved
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
@actual = ActualPuppetSessionState.new
|
|
17
|
+
@saved = SavedPuppetSessionState.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Clears the saved state. Typically only used when a paused debug session is about to start again.
|
|
21
|
+
def clear!
|
|
22
|
+
@saved.clear!
|
|
23
|
+
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The actual state of Puppet during a debug session
|
|
29
|
+
class ActualPuppetSessionState
|
|
30
|
+
# The depth of AST objects during a catalog compilation.
|
|
31
|
+
# @return [Integer]
|
|
32
|
+
attr_reader :pops_depth_level
|
|
33
|
+
|
|
34
|
+
# The compiler used to compile the catalog
|
|
35
|
+
# @return [Puppet::Parser::Compiler]
|
|
36
|
+
attr_reader :compiler
|
|
37
|
+
|
|
38
|
+
def initialize
|
|
39
|
+
@pops_depth_level = 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Resets back to initial state. Typically used when a debug session first starts.
|
|
43
|
+
def reset!
|
|
44
|
+
@pops_depth_level = 0
|
|
45
|
+
@compiler = nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Sets the compiler object. Typically set when a debug session begins catalog compilation.
|
|
49
|
+
def update_compiler(value)
|
|
50
|
+
@compiler = value
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Signals that an AST object is starting to be evaluated. Typically used during catalog compilation.
|
|
54
|
+
def increment_pops_depth
|
|
55
|
+
@pops_depth_level += 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Signals that an AST object has completed evaluated. Typically used during catalog compilation.
|
|
59
|
+
def decrement_pops_depth
|
|
60
|
+
@pops_depth_level -= 1
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The state of Puppet when a debug session was paused, typically during a breakpoint or exception.
|
|
65
|
+
class SavedPuppetSessionState
|
|
66
|
+
# The exception thrown when the session was paused.
|
|
67
|
+
# @return [Object]
|
|
68
|
+
attr_reader :exception
|
|
69
|
+
|
|
70
|
+
# The puppet stacktrace, not ruby stacktrace, when the session was paused.
|
|
71
|
+
# @return [Array<Object>]
|
|
72
|
+
attr_reader :puppet_stacktrace
|
|
73
|
+
|
|
74
|
+
# The Pops Object that caused the session to pause.
|
|
75
|
+
# @return [Object]
|
|
76
|
+
attr_reader :pops_target
|
|
77
|
+
|
|
78
|
+
# The Pops Scope containing the Pops Object that caused the session to pause.
|
|
79
|
+
# @return [Puppet::Parser::Scope]
|
|
80
|
+
attr_reader :scope
|
|
81
|
+
|
|
82
|
+
# The AST depth of the Pops Object that caused the session to pause.
|
|
83
|
+
# @return [Integer]
|
|
84
|
+
attr_reader :pops_depth_level
|
|
85
|
+
|
|
86
|
+
# A cache of variable references used to speed up Debug Server VariableReferences queries.
|
|
87
|
+
# @return [Hash<Integer, Object>]
|
|
88
|
+
attr_reader :variable_cache
|
|
89
|
+
|
|
90
|
+
def initialize
|
|
91
|
+
@variable_cache = {}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Updates the saved session state
|
|
95
|
+
# @see PuppetDebugServer::DebugSession::SavedPuppetSessionState
|
|
96
|
+
# @option options :exception
|
|
97
|
+
# @option options :puppet_stacktrace
|
|
98
|
+
# @option options :pops_target
|
|
99
|
+
# @option options :scope
|
|
100
|
+
# @option options :pops_depth_level
|
|
101
|
+
def update!(options = {})
|
|
102
|
+
@exception = options[:session_exception] unless options[:session_exception].nil?
|
|
103
|
+
@puppet_stacktrace = options[:puppet_stacktrace] unless options[:puppet_stacktrace].nil?
|
|
104
|
+
@pops_target = options[:pops_target] unless options[:pops_target].nil?
|
|
105
|
+
@scope = options[:scope] unless options[:scope].nil?
|
|
106
|
+
@pops_depth_level = options[:pops_depth_level] unless options[:pops_depth_level].nil?
|
|
107
|
+
self
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Clears the saved state. Typically used a debug session is un-paused.
|
|
111
|
+
def clear!
|
|
112
|
+
@exception = nil
|
|
113
|
+
@puppet_stacktrace = nil
|
|
114
|
+
@pops_target = nil
|
|
115
|
+
@scope = nil
|
|
116
|
+
@pops_depth_level = nil
|
|
117
|
+
@variable_cache = {}
|
|
118
|
+
self
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PuppetDebugServer
|
|
4
|
+
# This code was inspired from Puppet-Debugger (https://raw.githubusercontent.com/nwops/puppet-debugger/master/lib/puppet-debugger/hooks.rb) which was borrowed from Pry hooks file
|
|
5
|
+
|
|
6
|
+
# Both puppet-debugger and pry are licensed with MIT
|
|
7
|
+
# https://raw.githubusercontent.com/nwops/puppet-debugger/master/LICENSE.txt
|
|
8
|
+
# https://raw.githubusercontent.com/pry/pry/master/LICENSE
|
|
9
|
+
|
|
10
|
+
class Hooks
|
|
11
|
+
def initialize
|
|
12
|
+
@hooks = Hash.new { |h, k| h[k] = [] }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Ensure that duplicates have their @hooks object.
|
|
16
|
+
def initialize_copy
|
|
17
|
+
hooks_dup = @hooks.dup
|
|
18
|
+
@hooks.each do |k, v|
|
|
19
|
+
hooks_dup[k] = v.dup
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
@hooks = hooks_dup
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def errors
|
|
26
|
+
@errors ||= []
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Add a new hook to be executed for the `event_name` event.
|
|
30
|
+
# @param [Symbol] event_name The name of the event.
|
|
31
|
+
# @param [Symbol] hook_name The name of the hook.
|
|
32
|
+
# @param [#call] callable The callable.
|
|
33
|
+
# @yield The block to use as the callable (if no `callable` provided).
|
|
34
|
+
# @return [PuppetDebugger::Hooks] The receiver.
|
|
35
|
+
def add_hook(event_name, hook_name, callable = nil, &block)
|
|
36
|
+
event_name = event_name.to_s
|
|
37
|
+
|
|
38
|
+
# do not allow duplicates, but allow multiple `nil` hooks
|
|
39
|
+
# (anonymous hooks)
|
|
40
|
+
raise ArgumentError, "Hook with name '#{hook_name}' already defined!" if hook_exists?(event_name, hook_name) && !hook_name.nil?
|
|
41
|
+
|
|
42
|
+
raise ArgumentError, 'Must provide a block or callable.' if !block && !callable
|
|
43
|
+
|
|
44
|
+
# ensure we only have one anonymous hook
|
|
45
|
+
@hooks[event_name].delete_if { |h, _k| h.nil? } if hook_name.nil?
|
|
46
|
+
|
|
47
|
+
if block
|
|
48
|
+
@hooks[event_name] << [hook_name, block]
|
|
49
|
+
elsif callable
|
|
50
|
+
@hooks[event_name] << [hook_name, callable]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
self
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Execute the list of hooks for the `event_name` event.
|
|
57
|
+
# @param [Symbol] event_name The name of the event.
|
|
58
|
+
# @param [Array] args The arguments to pass to each hook function.
|
|
59
|
+
# @return [Object] The return value of the last executed hook.
|
|
60
|
+
def exec_hook(event_name, *args, &block)
|
|
61
|
+
PuppetDebugServer.log_message(:debug, "Starting to execute hook #{event_name}") unless event_name == :hook_log_message
|
|
62
|
+
@hooks[event_name.to_s].map do |_hook_name, callable|
|
|
63
|
+
callable.call(*args, &block)
|
|
64
|
+
rescue ::RuntimeError => e
|
|
65
|
+
errors << e
|
|
66
|
+
e
|
|
67
|
+
end.last
|
|
68
|
+
PuppetDebugServer.log_message(:debug, "Finished executing hook #{event_name}") unless event_name == :hook_log_message
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @param [Symbol] event_name The name of the event.
|
|
72
|
+
# @return [Fixnum] The number of hook functions for `event_name`.
|
|
73
|
+
def hook_count(event_name)
|
|
74
|
+
@hooks[event_name.to_s].size
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# @param [Symbol] event_name The name of the event.
|
|
78
|
+
# @param [Symbol] hook_name The name of the hook
|
|
79
|
+
# @return [#call] a specific hook for a given event.
|
|
80
|
+
def get_hook(event_name, hook_name)
|
|
81
|
+
hook = @hooks[event_name.to_s].find do |current_hook_name, _callable|
|
|
82
|
+
current_hook_name == hook_name
|
|
83
|
+
end
|
|
84
|
+
hook.last if hook
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @param [Symbol] event_name The name of the event.
|
|
88
|
+
# @return [Hash] The hash of hook names / hook functions.
|
|
89
|
+
# @note Modifying the returned hash does not alter the hooks, use
|
|
90
|
+
# `add_hook`/`delete_hook` for that.
|
|
91
|
+
def get_hooks(event_name)
|
|
92
|
+
(@hooks[event_name.to_s]).to_h
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @param [Symbol] event_name The name of the event.
|
|
96
|
+
# @param [Symbol] hook_name The name of the hook.
|
|
97
|
+
# to delete.
|
|
98
|
+
# @return [#call] The deleted hook.
|
|
99
|
+
def delete_hook(event_name, hook_name)
|
|
100
|
+
deleted_callable = nil
|
|
101
|
+
|
|
102
|
+
@hooks[event_name.to_s].delete_if do |current_hook_name, callable|
|
|
103
|
+
if current_hook_name == hook_name
|
|
104
|
+
deleted_callable = callable
|
|
105
|
+
true
|
|
106
|
+
else
|
|
107
|
+
false
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
deleted_callable
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Clear all hooks functions for a given event.
|
|
114
|
+
#
|
|
115
|
+
# @param [String] event_name The name of the event.
|
|
116
|
+
# @return [void]
|
|
117
|
+
def clear_event_hooks(event_name)
|
|
118
|
+
@hooks[event_name.to_s] = []
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @param [Symbol] event_name Name of the event.
|
|
122
|
+
# @param [Symbol] hook_name Name of the hook.
|
|
123
|
+
# @return [Boolean] Whether the hook by the name `hook_name`.
|
|
124
|
+
def hook_exists?(event_name, hook_name)
|
|
125
|
+
@hooks[event_name.to_s].map(&:first).include?(hook_name)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
protected
|
|
129
|
+
|
|
130
|
+
attr_reader :hooks
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'puppet_editor_services/handler/debug_adapter'
|
|
4
|
+
|
|
5
|
+
module PuppetDebugServer
|
|
6
|
+
class MessageHandler < PuppetEditorServices::Handler::DebugAdapter
|
|
7
|
+
# region Message Helpers
|
|
8
|
+
def send_exited_event(exitcode)
|
|
9
|
+
protocol.encode_and_send(
|
|
10
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.new_event(
|
|
11
|
+
'exited',
|
|
12
|
+
'exitCode' => exitcode
|
|
13
|
+
)
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def send_output_event(body_content)
|
|
18
|
+
protocol.encode_and_send(PuppetEditorServices::Protocol::DebugAdapterMessages.new_event('output', body_content))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def send_stopped_event(reason, options = {})
|
|
22
|
+
protocol.encode_and_send(
|
|
23
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.new_event(
|
|
24
|
+
'stopped',
|
|
25
|
+
{ 'reason' => reason }.merge(options)
|
|
26
|
+
)
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def send_termination_event
|
|
31
|
+
protocol.encode_and_send(PuppetEditorServices::Protocol::DebugAdapterMessages.new_event('terminated'))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def send_thread_event(reason, thread_id)
|
|
35
|
+
protocol.encode_and_send(
|
|
36
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.new_event(
|
|
37
|
+
'thread',
|
|
38
|
+
'reason' => reason, 'threadId' => thread_id
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
# end region
|
|
43
|
+
|
|
44
|
+
def request_configurationdone(_connection_id, request_message)
|
|
45
|
+
PuppetDebugServer.log_message(:debug, 'Received configurationDone request.')
|
|
46
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
47
|
+
|
|
48
|
+
debug_session.flow_control.assert_flag(:client_completed_configuration)
|
|
49
|
+
|
|
50
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(request_message)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def request_continue(_connection_id, request_message)
|
|
54
|
+
PuppetDebugServer.log_message(:debug, 'Received continue request.')
|
|
55
|
+
|
|
56
|
+
# Continue the debug session
|
|
57
|
+
PuppetDebugServer::PuppetDebugSession.instance.flow_control.continue!
|
|
58
|
+
|
|
59
|
+
# Send response. We only actually have one thread, but simulate the
|
|
60
|
+
# allThreadsContinued setting
|
|
61
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
62
|
+
request_message,
|
|
63
|
+
'allThreadsContinued' => true
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def request_disconnect(_connection_id, _request_message)
|
|
68
|
+
# Don't really care about the arguments - Kill everything
|
|
69
|
+
PuppetDebugServer.log_message(:info, 'Received disconnect request. Closing connection to client...')
|
|
70
|
+
protocol.close_connection
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def request_evaluate(_connection_id, request_message)
|
|
74
|
+
PuppetDebugServer.log_message(:debug, 'Received evaluate request.')
|
|
75
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
76
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) unless debug_session.flow_control.session_active?
|
|
77
|
+
|
|
78
|
+
obj = DSP::EvaluateRequest.new(request_message.to_h)
|
|
79
|
+
begin
|
|
80
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
81
|
+
request_message,
|
|
82
|
+
'result' => debug_session.evaluate_string(obj.arguments), 'variablesReference' => 0
|
|
83
|
+
)
|
|
84
|
+
rescue => e # rubocop:disable Style/RescueStandardError Anything could be thrown here. Catch 'em all
|
|
85
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(
|
|
86
|
+
request_message,
|
|
87
|
+
e.to_s
|
|
88
|
+
)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def request_initialize(_connection_id, request_message)
|
|
93
|
+
PuppetDebugServer.log_message(:debug, 'Received initialize request.')
|
|
94
|
+
# Save the client capabilities for later use
|
|
95
|
+
@client_capabilities = request_message.arguments.to_h
|
|
96
|
+
|
|
97
|
+
# Send capability response
|
|
98
|
+
capabilities = DSP::Capabilities.new
|
|
99
|
+
# We can't accept breakpoints at any time so need them upfront
|
|
100
|
+
capabilities.supportsConfigurationDoneRequest = true
|
|
101
|
+
# The different kind of breakpoints the server supports
|
|
102
|
+
capabilities.supportsFunctionBreakpoints = true
|
|
103
|
+
capabilities.supportsConditionalBreakpoints = false
|
|
104
|
+
capabilities.supportsHitConditionalBreakpoints = false
|
|
105
|
+
capabilities.supportsDataBreakpoints = false
|
|
106
|
+
capabilities.supportsLogPoints = false
|
|
107
|
+
capabilities.supportsExceptionOptions = false
|
|
108
|
+
# We don't have any filters
|
|
109
|
+
capabilities.exceptionBreakpointFilters = []
|
|
110
|
+
# We only have one thread so no need for this
|
|
111
|
+
capabilities.supportsTerminateThreadsRequest = false
|
|
112
|
+
capabilities.supportTerminateDebuggee = false
|
|
113
|
+
# But we can terminate
|
|
114
|
+
capabilities.supportsTerminateRequest = true
|
|
115
|
+
# We can't really restart or go backwards
|
|
116
|
+
capabilities.supportsRestartRequest = false
|
|
117
|
+
capabilities.supportsStepBack = false
|
|
118
|
+
capabilities.supportsRestartFrame = false
|
|
119
|
+
# While Puppet "variables" are immutable (and poorly named) when can create new ones
|
|
120
|
+
capabilities.supportsSetVariable = true
|
|
121
|
+
capabilities.supportsSetExpression = false
|
|
122
|
+
# We don't support Targets
|
|
123
|
+
capabilities.supportsGotoTargetsRequest = false
|
|
124
|
+
capabilities.supportsStepInTargetsRequest = false
|
|
125
|
+
# Puppet doesn't have those kind of modules
|
|
126
|
+
capabilities.supportsModulesRequest = false
|
|
127
|
+
# We don't have that kinda memory or disassembly
|
|
128
|
+
capabilities.supportsReadMemoryRequest = false
|
|
129
|
+
capabilities.supportsDisassembleRequest = false
|
|
130
|
+
# Other capabilites which don't make sens in a Puppet world, yet.
|
|
131
|
+
capabilities.supportsEvaluateForHovers = false
|
|
132
|
+
capabilities.supportsCompletionsRequest = false
|
|
133
|
+
capabilities.additionalModuleColumns = []
|
|
134
|
+
capabilities.supportedChecksumAlgorithms = []
|
|
135
|
+
capabilities.supportsValueFormattingOptions = false
|
|
136
|
+
capabilities.supportsExceptionInfoRequest = false
|
|
137
|
+
capabilities.supportsDelayedStackTraceLoading = false
|
|
138
|
+
capabilities.supportsLoadedSourcesRequest = false
|
|
139
|
+
|
|
140
|
+
# Do some initialization
|
|
141
|
+
# .... dum de dum ...
|
|
142
|
+
protocol.encode_and_send(PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(request_message, capabilities))
|
|
143
|
+
|
|
144
|
+
# Send a message that we are initialized
|
|
145
|
+
# This must happen _after_ the capabilites are sent. This is pretty janky but _meh_
|
|
146
|
+
sleep(0.5) # Sleep for a small amount of time to give the client time to process the capabilites response
|
|
147
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.new_event('initialized')
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def request_launch(_connection_id, request_message)
|
|
151
|
+
PuppetDebugServer.log_message(:debug, 'Received launch request.')
|
|
152
|
+
# TODO: Do we care about the noDebug?
|
|
153
|
+
|
|
154
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
155
|
+
# Setup the debug session
|
|
156
|
+
# Can't use the DSP::LaunchRequest object here because the arguments are dynamic
|
|
157
|
+
# The :session_setup flag is asserted inside the setup method so no need to for us to do that here
|
|
158
|
+
debug_session.setup(self, request_message.arguments)
|
|
159
|
+
|
|
160
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(request_message)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def request_next(_connection_id, request_message)
|
|
164
|
+
PuppetDebugServer.log_message(:debug, 'Received next request.')
|
|
165
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
166
|
+
obj = DSP::NextRequest.new(request_message.to_h)
|
|
167
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) if debug_session.puppet_thread_id.nil? || debug_session.puppet_thread_id != obj.arguments.threadId
|
|
168
|
+
|
|
169
|
+
# Stepout the debug session
|
|
170
|
+
debug_session.flow_control.next!
|
|
171
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(request_message)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def request_scopes(_connection_id, request_message)
|
|
175
|
+
PuppetDebugServer.log_message(:debug, 'Received scopes request.')
|
|
176
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
177
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) unless debug_session.flow_control.session_active?
|
|
178
|
+
|
|
179
|
+
obj = DSP::ScopesRequest.new(request_message.to_h)
|
|
180
|
+
|
|
181
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
182
|
+
request_message,
|
|
183
|
+
'scopes' => debug_session.generate_scopes_list(obj.arguments.frameId)
|
|
184
|
+
)
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def request_setbreakpoints(_connection_id, request_message)
|
|
188
|
+
PuppetDebugServer.log_message(:debug, 'Received setBreakpoints request.')
|
|
189
|
+
req = DSP::SetBreakpointsRequest.new(request_message.to_h)
|
|
190
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
191
|
+
|
|
192
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
193
|
+
request_message,
|
|
194
|
+
'breakpoints' => debug_session.breakpoints.process_set_breakpoints_request!(req.arguments)
|
|
195
|
+
)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def request_setfunctionbreakpoints(_connection_id, request_message)
|
|
199
|
+
PuppetDebugServer.log_message(:debug, 'Received setFunctionBreakpoints request.')
|
|
200
|
+
req = DSP::SetFunctionBreakpointsRequest.new(request_message.to_h)
|
|
201
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
202
|
+
|
|
203
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
204
|
+
request_message,
|
|
205
|
+
'breakpoints' => debug_session.breakpoints.process_set_function_breakpoints_request!(req.arguments)
|
|
206
|
+
)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def request_stacktrace(_connection_id, request_message)
|
|
210
|
+
PuppetDebugServer.log_message(:debug, 'Received stackTrace request.')
|
|
211
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
212
|
+
obj = DSP::StackTraceRequest.new(request_message.to_h)
|
|
213
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) if debug_session.puppet_thread_id.nil? || debug_session.puppet_thread_id != obj.arguments.threadId
|
|
214
|
+
|
|
215
|
+
frames = debug_session.generate_stackframe_list
|
|
216
|
+
|
|
217
|
+
# TODO: Should really trim the frame information for the given stack trace request
|
|
218
|
+
# /** The index of the first frame to return; if omitted frames start at 0. */
|
|
219
|
+
# startFrame?: number;
|
|
220
|
+
# /** The maximum number of frames to return. If levels is not specified or 0, all frames are returned. */
|
|
221
|
+
# levels?: number;
|
|
222
|
+
# /** Specifies details on how to format the stack frames. */
|
|
223
|
+
# format?: StackFrameFormat;
|
|
224
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
225
|
+
request_message,
|
|
226
|
+
'stackFrames' => frames, 'totalFrames' => frames.count
|
|
227
|
+
)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def request_stepin(_connection_id, request_message)
|
|
231
|
+
PuppetDebugServer.log_message(:debug, 'Received stepIn request.')
|
|
232
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
233
|
+
obj = DSP::StepInRequest.new(request_message.to_h)
|
|
234
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) if debug_session.puppet_thread_id.nil? || debug_session.puppet_thread_id != obj.arguments.threadId
|
|
235
|
+
|
|
236
|
+
# Stepin the debug session
|
|
237
|
+
debug_session.flow_control.step_in!
|
|
238
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(request_message)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def request_stepout(_connection_id, request_message)
|
|
242
|
+
PuppetDebugServer.log_message(:debug, 'Received stepOut request.')
|
|
243
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
244
|
+
obj = DSP::StepOutRequest.new(request_message.to_h)
|
|
245
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) if debug_session.puppet_thread_id.nil? || debug_session.puppet_thread_id != obj.arguments.threadId
|
|
246
|
+
|
|
247
|
+
# Stepout the debug session
|
|
248
|
+
debug_session.flow_control.step_out!
|
|
249
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(request_message)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def request_threads(_connection_id, request_message)
|
|
253
|
+
PuppetDebugServer.log_message(:debug, 'Received threads request.')
|
|
254
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
255
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) if debug_session.puppet_thread_id.nil?
|
|
256
|
+
|
|
257
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
258
|
+
request_message,
|
|
259
|
+
# There is only one thread
|
|
260
|
+
'threads' => [{ 'id' => debug_session.puppet_thread_id, 'name' => 'puppet' }]
|
|
261
|
+
)
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def request_variables(_connection_id, request_message)
|
|
265
|
+
PuppetDebugServer.log_message(:debug, 'Received variables request.')
|
|
266
|
+
debug_session = PuppetDebugServer::PuppetDebugSession.instance
|
|
267
|
+
return PuppetEditorServices::Protocol::DebugAdapterMessages.reply_error(request_message) unless debug_session.flow_control.session_active?
|
|
268
|
+
|
|
269
|
+
obj = DSP::VariablesRequest.new(request_message.to_h)
|
|
270
|
+
|
|
271
|
+
PuppetEditorServices::Protocol::DebugAdapterMessages.reply_success(
|
|
272
|
+
request_message,
|
|
273
|
+
'variables' => debug_session.generate_variables_list(obj.arguments)
|
|
274
|
+
)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|