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.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +510 -0
  3. data/CODEOWNERS +2 -0
  4. data/CODE_OF_CONDUCT.md +46 -0
  5. data/CONTRIBUTING.md +54 -0
  6. data/Gemfile +53 -0
  7. data/LICENSE +201 -0
  8. data/README.md +308 -0
  9. data/Rakefile +185 -0
  10. data/bin/puppet-debugserver +8 -0
  11. data/bin/puppet-languageserver +7 -0
  12. data/bin/puppet-languageserver-sidecar +7 -0
  13. data/lib/dsp/dsp.rb +7 -0
  14. data/lib/dsp/dsp_base.rb +62 -0
  15. data/lib/dsp/dsp_protocol.rb +4619 -0
  16. data/lib/lsp/lsp.rb +10 -0
  17. data/lib/lsp/lsp_base.rb +63 -0
  18. data/lib/lsp/lsp_custom.rb +170 -0
  19. data/lib/lsp/lsp_enums.rb +143 -0
  20. data/lib/lsp/lsp_protocol.rb +2785 -0
  21. data/lib/lsp/lsp_protocol_callhierarchy.proposed.rb +239 -0
  22. data/lib/lsp/lsp_protocol_colorprovider.rb +100 -0
  23. data/lib/lsp/lsp_protocol_configuration.rb +82 -0
  24. data/lib/lsp/lsp_protocol_declaration.rb +73 -0
  25. data/lib/lsp/lsp_protocol_foldingrange.rb +129 -0
  26. data/lib/lsp/lsp_protocol_implementation.rb +75 -0
  27. data/lib/lsp/lsp_protocol_progress.rb +200 -0
  28. data/lib/lsp/lsp_protocol_selectionrange.rb +79 -0
  29. data/lib/lsp/lsp_protocol_sematictokens.proposed.rb +340 -0
  30. data/lib/lsp/lsp_protocol_typedefinition.rb +75 -0
  31. data/lib/lsp/lsp_protocol_workspacefolders.rb +174 -0
  32. data/lib/lsp/lsp_types.rb +1534 -0
  33. data/lib/puppet-debugserver/debug_session/break_points.rb +137 -0
  34. data/lib/puppet-debugserver/debug_session/flow_control.rb +161 -0
  35. data/lib/puppet-debugserver/debug_session/hook_handlers.rb +295 -0
  36. data/lib/puppet-debugserver/debug_session/puppet_session_run_mode.rb +66 -0
  37. data/lib/puppet-debugserver/debug_session/puppet_session_state.rb +122 -0
  38. data/lib/puppet-debugserver/hooks.rb +132 -0
  39. data/lib/puppet-debugserver/message_handler.rb +277 -0
  40. data/lib/puppet-debugserver/puppet_debug_session.rb +541 -0
  41. data/lib/puppet-debugserver/puppet_monkey_patches.rb +118 -0
  42. data/lib/puppet-languageserver/client_session_state.rb +119 -0
  43. data/lib/puppet-languageserver/crash_dump.rb +50 -0
  44. data/lib/puppet-languageserver/epp/validation_provider.rb +34 -0
  45. data/lib/puppet-languageserver/facter_helper.rb +25 -0
  46. data/lib/puppet-languageserver/global_queues/sidecar_queue.rb +205 -0
  47. data/lib/puppet-languageserver/global_queues/single_instance_queue.rb +126 -0
  48. data/lib/puppet-languageserver/global_queues/validation_queue.rb +102 -0
  49. data/lib/puppet-languageserver/global_queues.rb +16 -0
  50. data/lib/puppet-languageserver/manifest/completion_provider.rb +331 -0
  51. data/lib/puppet-languageserver/manifest/definition_provider.rb +99 -0
  52. data/lib/puppet-languageserver/manifest/document_symbol_provider.rb +228 -0
  53. data/lib/puppet-languageserver/manifest/folding_provider.rb +226 -0
  54. data/lib/puppet-languageserver/manifest/format_on_type_provider.rb +143 -0
  55. data/lib/puppet-languageserver/manifest/hover_provider.rb +221 -0
  56. data/lib/puppet-languageserver/manifest/signature_provider.rb +169 -0
  57. data/lib/puppet-languageserver/manifest/validation_provider.rb +127 -0
  58. data/lib/puppet-languageserver/message_handler.rb +462 -0
  59. data/lib/puppet-languageserver/providers.rb +18 -0
  60. data/lib/puppet-languageserver/puppet_helper.rb +108 -0
  61. data/lib/puppet-languageserver/puppet_lexer_helper.rb +55 -0
  62. data/lib/puppet-languageserver/puppet_monkey_patches.rb +39 -0
  63. data/lib/puppet-languageserver/puppet_parser_helper.rb +212 -0
  64. data/lib/puppet-languageserver/puppetfile/validation_provider.rb +185 -0
  65. data/lib/puppet-languageserver/server_capabilities.rb +48 -0
  66. data/lib/puppet-languageserver/session_state/document_store.rb +272 -0
  67. data/lib/puppet-languageserver/session_state/language_client.rb +239 -0
  68. data/lib/puppet-languageserver/session_state/object_cache.rb +162 -0
  69. data/lib/puppet-languageserver/sidecar_protocol.rb +532 -0
  70. data/lib/puppet-languageserver/uri_helper.rb +46 -0
  71. data/lib/puppet-languageserver-sidecar/cache/base.rb +36 -0
  72. data/lib/puppet-languageserver-sidecar/cache/filesystem.rb +111 -0
  73. data/lib/puppet-languageserver-sidecar/cache/null.rb +27 -0
  74. data/lib/puppet-languageserver-sidecar/facter_helper.rb +41 -0
  75. data/lib/puppet-languageserver-sidecar/puppet_environment_monkey_patches.rb +52 -0
  76. data/lib/puppet-languageserver-sidecar/puppet_helper.rb +281 -0
  77. data/lib/puppet-languageserver-sidecar/puppet_modulepath_monkey_patches.rb +146 -0
  78. data/lib/puppet-languageserver-sidecar/puppet_monkey_patches.rb +9 -0
  79. data/lib/puppet-languageserver-sidecar/puppet_parser_helper.rb +77 -0
  80. data/lib/puppet-languageserver-sidecar/puppet_strings_helper.rb +399 -0
  81. data/lib/puppet-languageserver-sidecar/puppet_strings_monkey_patches.rb +16 -0
  82. data/lib/puppet-languageserver-sidecar/sidecar_protocol_extensions.rb +16 -0
  83. data/lib/puppet-languageserver-sidecar/workspace.rb +89 -0
  84. data/lib/puppet_debugserver.rb +164 -0
  85. data/lib/puppet_editor_services/connection/base.rb +62 -0
  86. data/lib/puppet_editor_services/connection/stdio.rb +25 -0
  87. data/lib/puppet_editor_services/connection/tcp.rb +34 -0
  88. data/lib/puppet_editor_services/handler/base.rb +16 -0
  89. data/lib/puppet_editor_services/handler/debug_adapter.rb +63 -0
  90. data/lib/puppet_editor_services/handler/json_rpc.rb +133 -0
  91. data/lib/puppet_editor_services/logging.rb +45 -0
  92. data/lib/puppet_editor_services/protocol/base.rb +27 -0
  93. data/lib/puppet_editor_services/protocol/debug_adapter.rb +135 -0
  94. data/lib/puppet_editor_services/protocol/debug_adapter_messages.rb +171 -0
  95. data/lib/puppet_editor_services/protocol/json_rpc.rb +241 -0
  96. data/lib/puppet_editor_services/protocol/json_rpc_messages.rb +200 -0
  97. data/lib/puppet_editor_services/server/base.rb +42 -0
  98. data/lib/puppet_editor_services/server/stdio.rb +85 -0
  99. data/lib/puppet_editor_services/server/tcp.rb +349 -0
  100. data/lib/puppet_editor_services/server.rb +15 -0
  101. data/lib/puppet_editor_services/version.rb +36 -0
  102. data/lib/puppet_editor_services.rb +8 -0
  103. data/lib/puppet_languageserver.rb +263 -0
  104. data/lib/puppet_languageserver_sidecar.rb +361 -0
  105. data/puppet-debugserver +11 -0
  106. data/puppet-editor-services.gemspec +29 -0
  107. data/puppet-languageserver +15 -0
  108. data/puppet-languageserver-sidecar +14 -0
  109. 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