def _Launch(self): self._logger.debug("LAUNCH!") adapter_config = self._adapter launch_config = {} launch_config.update(self._adapter.get('configuration', {})) launch_config.update(self._configuration['configuration']) request = self._configuration.get( 'remote-request', launch_config.get('request', 'launch')) if request == "attach": self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Attaching to debugee...") self._PrepareAttach(adapter_config, launch_config) elif request == "launch": self._splash_screen = utils.DisplaySplash(self._api_prefix, self._splash_screen, "Launching debugee...") # FIXME: This cmdLine hack is not fun. self._PrepareLaunch(self._configuration.get('remote-cmdLine', []), adapter_config, launch_config) # FIXME: name is mandatory. Forcefully add it (we should really use the # _actual_ name, but that isn't actually remembered at this point) if 'name' not in launch_config: launch_config['name'] = 'test' self._connection.DoRequest(lambda msg: self._OnLaunchComplete(), { 'command': launch_config['request'], 'arguments': launch_config })
def _Prepare(self): self._on_init_complete_handlers = [] self._logger.debug("LAUNCH!") self._launch_config = {} self._launch_config.update(self._adapter.get('configuration', {})) self._launch_config.update(self._configuration['configuration']) request = self._configuration.get( 'remote-request', self._launch_config.get('request', 'launch')) if request == "attach": self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Attaching to debugee...") self._PrepareAttach(self._adapter, self._launch_config) elif request == "launch": self._splash_screen = utils.DisplaySplash(self._api_prefix, self._splash_screen, "Launching debugee...") # FIXME: This cmdLine hack is not fun. self._PrepareLaunch(self._configuration.get('remote-cmdLine', []), self._adapter, self._launch_config) # FIXME: name is mandatory. Forcefully add it (we should really use the # _actual_ name, but that isn't actually remembered at this point) if 'name' not in self._launch_config: self._launch_config['name'] = 'test'
def _StartDebugAdapter( self ): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Starting debug adapter..." ) if self._connection: utils.UserMessage( 'The connection is already created. Please try again', persist = True ) return self._logger.info( 'Starting debug adapter with: %s', json.dumps( self._adapter ) ) self._init_complete = False self._on_init_complete_handlers = [] self._launch_complete = False self._run_on_server_exit = None self._connection_type = 'job' if 'port' in self._adapter: self._connection_type = 'channel' if self._adapter[ 'port' ] == 'ask': port = utils.AskForInput( 'Enter port to connect to: ' ) if port is None: self._Reset() return self._adapter[ 'port' ] = port self._connection_type = self._api_prefix + self._connection_type # TODO: Do we actually need to copy and update or does Vim do that? env = os.environ.copy() if os.name == "nt": env = {} if 'env' in self._adapter: env.update( self._adapter[ 'env' ] ) self._adapter[ 'env' ] = env if 'cwd' not in self._adapter: self._adapter[ 'cwd' ] = os.getcwd() vim.vars[ '_vimspector_adapter_spec' ] = self._adapter if not vim.eval( "vimspector#internal#{}#StartDebugSession( " " g:_vimspector_adapter_spec " ")".format( self._connection_type ) ): self._logger.error( "Unable to start debug server" ) self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Unable to start adapter" ) else: self._connection = debug_adapter_connection.DebugAdapterConnection( self, lambda msg: utils.Call( "vimspector#internal#{}#Send".format( self._connection_type ), msg ) ) self._logger.info( 'Debug Adapter Started' )
def _StopDebugAdapter(self, callback=None): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Shutting down debug adapter...") def handler(*args): self._splash_screen = utils.HideSplash(self._api_prefix, self._splash_screen) if callback: self._logger.debug( "Setting server exit handler before disconnect") assert not self._run_on_server_exit self._run_on_server_exit = callback vim.eval('vimspector#internal#{}#StopDebugSession()'.format( self._connection_type)) arguments = {} if self._server_capabilities.get('supportTerminateDebuggee'): # If we attached, we should _not_ terminate the debuggee arguments['terminateDebuggee'] = False self._connection.DoRequest(handler, { 'command': 'disconnect', 'arguments': arguments, }, failure_handler=handler, timeout=5000)
def _StopDebugAdapter(self, interactive=False, callback=None): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Shutting down debug adapter...") def handler(*args): self._splash_screen = utils.HideSplash(self._api_prefix, self._splash_screen) if callback: self._logger.debug( "Setting server exit handler before disconnect") assert not self._run_on_server_exit self._run_on_server_exit = callback vim.eval('vimspector#internal#{}#StopDebugSession()'.format( self._connection_type)) arguments = {} if (interactive and self._server_capabilities.get('supportTerminateDebuggee')): if self._stackTraceView.AnyThreadsRunning(): choice = utils.AskForInput( "Terminate debuggee [Y/N/default]? ", "") if choice == "Y" or choice == "y": arguments['terminateDebuggee'] = True elif choice == "N" or choice == 'n': arguments['terminateDebuggee'] = False self._connection.DoRequest(handler, { 'command': 'disconnect', 'arguments': arguments, }, failure_handler=handler, timeout=5000)
def failure_handler(reason, msg): text = [ 'Launch Failed', '', reason, '', 'Use :VimspectorReset to close' ] self._splash_screen = utils.DisplaySplash(self._api_prefix, self._splash_screen, text)
def _Initialise(self): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Initializing debug adapter...") # For a good explaination as to why this sequence is the way it is, see # https://github.com/microsoft/vscode/issues/4902#issuecomment-368583522 # # In short, we do what VSCode does: # 1. Send the initialize request and wait for the reply # 2a. When we recieve the initialize reply, send the launch/attach request # 2b. When we receive the initialized notification, send the breakpoints # - if supportsConfigurationDoneRequest, send it # - else, send the empty exception breakpoints request # 3. When we have recieved both the receive the launch/attach reply *and* # the connfiguration done reply (or, if we didn't send one, a response to # the empty exception breakpoints request), we request threads # 4. The threads response triggers things like scopes and triggers setting # the current frame. # def handle_initialize_response(msg): self._server_capabilities = msg.get('body') or {} self._breakpoints.SetServerCapabilities(self._server_capabilities) self._variablesView.SetServerCapabilities( self._server_capabilities) self._Launch() self._connection.DoRequest( handle_initialize_response, { 'command': 'initialize', 'arguments': { 'adapterID': self._adapter.get('name', 'adapter'), 'clientID': 'vimspector', 'clientName': 'vimspector', 'linesStartAt1': True, 'columnsStartAt1': True, 'locale': 'en_GB', 'pathFormat': 'path', 'supportsVariableType': True, 'supportsVariablePaging': False, 'supportsRunInTerminalRequest': True }, })
def disconnect(): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Shutting down debug adapter..." ) def handler( *args ): self._splash_screen = utils.HideSplash( self._api_prefix, self._splash_screen ) if callback: self._logger.debug( "Setting server exit handler before disconnect" ) assert not self._run_on_server_exit self._run_on_server_exit = callback vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format( self._connection_type ) ) self._connection.DoRequest( handler, { 'command': 'disconnect', 'arguments': arguments, }, failure_handler = handler, timeout = 5000 )
def _StartDebugAdapter(self): self._splash_screen = utils.DisplaySplash(self._api_prefix, self._splash_screen, "Starting debug adapter...") if self._connection: utils.UserMessage( 'The connection is already created. Please try again', persist=True) return # There is the problem with the current flow when we try to use a debugger # which is located fully on the remote server e.g container or SSH Server. # The problem is in the order: it tries to connect to debugger before it is even started # To solve that problem, I offer adding an optional boolean key "bootstrap" to a configuration. # If we have that key, we should perform launch or attach commands to first bootstrap a remote debugger. # Then we can skip that step in the _Launch() function if self._adapter.get('bootstrap'): self._BootstrapRemoteDebugger() self._logger.info('Starting debug adapter with: %s', json.dumps(self._adapter)) self._init_complete = False self._on_init_complete_handlers = [] self._launch_complete = False self._run_on_server_exit = None self._connection_type = 'job' if 'port' in self._adapter: self._connection_type = 'channel' if self._adapter['port'] == 'ask': port = utils.AskForInput('Enter port to connect to: ') if port is None: self._Reset() return self._adapter['port'] = port self._connection_type = self._api_prefix + self._connection_type # TODO: Do we actually need to copy and update or does Vim do that? env = os.environ.copy() if 'env' in self._adapter: env.update(self._adapter['env']) self._adapter['env'] = env if 'cwd' not in self._adapter: self._adapter['cwd'] = os.getcwd() vim.vars['_vimspector_adapter_spec'] = self._adapter if not vim.eval("vimspector#internal#{}#StartDebugSession( " " g:_vimspector_adapter_spec " ")".format(self._connection_type)): self._logger.error("Unable to start debug server") self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Unable to start adapter") else: self._connection = debug_adapter_connection.DebugAdapterConnection( self, lambda msg: utils.Call( "vimspector#internal#{}#Send".format(self._connection_type ), msg)) self._logger.info('Debug Adapter Started')
def _StartDebugAdapter( self ): self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Starting debug adapter..." ) if self._connection: utils.UserMessage( 'The connection is already created. Please try again', persist = True ) return self._logger.info( 'Starting debug adapter with: %s', json.dumps( self._adapter ) ) self._init_complete = False self._launch_complete = False self._run_on_server_exit = None self._connection_type = 'job' if 'port' in self._adapter: self._connection_type = 'channel' if self._adapter[ 'port' ] == 'ask': port = utils.AskForInput( 'Enter port to connect to: ' ) if port is None: self._Reset() return self._adapter[ 'port' ] = port self._connection_type = self._api_prefix + self._connection_type self._logger.debug( f"Connection Type: { self._connection_type }" ) self._adapter[ 'env' ] = self._adapter.get( 'env', {} ) if 'cwd' not in self._adapter: self._adapter[ 'cwd' ] = os.getcwd() vim.vars[ '_vimspector_adapter_spec' ] = self._adapter if not vim.eval( "vimspector#internal#{}#StartDebugSession( " " g:_vimspector_adapter_spec " ")".format( self._connection_type ) ): self._logger.error( "Unable to start debug server" ) self._splash_screen = utils.DisplaySplash( self._api_prefix, self._splash_screen, "Unable to start adapter" ) else: if 'custom_handler' in self._adapter: spec = self._adapter[ 'custom_handler' ] if isinstance( spec, dict ): module = spec[ 'module' ] cls = spec[ 'class' ] else: module, cls = spec.rsplit( '.', 1 ) CustomHandler = getattr( importlib.import_module( module ), cls ) handlers = [ CustomHandler( self ), self ] else: handlers = [ self ] self._connection = debug_adapter_connection.DebugAdapterConnection( handlers, lambda msg: utils.Call( "vimspector#internal#{}#Send".format( self._connection_type ), msg ) ) self._logger.info( 'Debug Adapter Started' )