def schedule_render() -> None: global _render_scheduled if _render_scheduled: return _render_scheduled = True core.run(render_scheduled())
def getStackTrace(self, thread: Thread, response: Callable[[List[StackFrame]], None]) -> None: selection_in_other_thread = False selected_frame_id = -1 if self.selected_thread: assert self.selected_frame if self.selected_thread.id == thread.id: selected_frame_id = self.selected_frame.id else: selection_in_other_thread = True def cb(body: dict) -> None: frames = [] default_selected_index = -1 found_selected_frame = False for index, frame in enumerate(body['stackFrames']): source = frame.get('source') hint = frame.get('presentationHint', 'normal') if hint == 'label': presentation = StackFramePresentation.label elif hint == 'subtle': presentation = StackFramePresentation.subtle else: if default_selected_index < 0: default_selected_index = index presentation = StackFramePresentation.normal internal = False file = None if source: file = source.get('path') if not file: file = '??' internal = True frame = StackFrame(frame['id'], file, frame['name'], frame.get('line', 0), internal, presentation) frames.append(frame) if frame.id == selected_frame_id: found_selected_frame = True # we auto select a frame if we don't already have a frame selected in another thread # if the frame selected is in our thread but we didn't find the same frame then we select a new one # ensure this thread is still stopped before we select the frame # it is possible this thread started running again so we don't want to auto select its frame if thread.stopped and not selection_in_other_thread and not found_selected_frame: self.set_selected_thread_and_frame( thread, frames[default_selected_index]) response(frames) core.run(self.send_request_asyc('stackTrace', {"threadId": thread.id}), cb)
def OnExpandBreakpoint(self, breakpoint: Breakpoint) -> None: @core.async def a() -> core.awaitable[None]: view = yield from core.sublime_open_file_async(sublime.active_window(), breakpoint.file, breakpoint.line) at = view.text_point(breakpoint.line - 1, 0) view.sel().clear() self.clearBreakpointInformation() self.breakpointInformation = ui.Phantom(BreakpointInlineComponent(breakpoints = self.breakpoints, breakpoint = breakpoint), view, sublime.Region(at, at), sublime.LAYOUT_BELOW) core.run(a())
def set_selected_frame(self, frame: Optional[StackFrame]) -> None: new_frame = self.frame != frame self.frame = frame if new_frame: self.on_selected_frame(self.thread, frame) self._refresh_state() if self.adapter and frame: core.run(self.adapter.GetScopes(frame), self.on_scopes) else: self.on_scopes([])
def scopes(self, frameId: int) -> None: def response(response: dict) -> None: self.variables.clear() for scope in response['scopes']: var = Variable(self, scope['name'], '', scope['variablesReference']) self.variables.append(var) self.onVariables.post(None) core.run(self.send_request_asyc('scopes', {"frameId": frameId}), response)
def onSelectedStackFrame(self, frame: Optional[StackFrame]) -> None: if not frame: if self.selectedFrameComponent: self.selectedFrameComponent.dispose() self.selectedFrameComponent = None return if not frame.internal: line = frame.line - 1 def complete(view: sublime.View) -> None: self.add_selected_stack_frame_component(view, line) core.run(core.sublime_open_file_async(self.window, frame.file, line), complete)
def __init__(self, variable: Variable) -> None: super().__init__() self.variables = [] #type: List[Variable] # We exand this variabble right away. # It seems that console messages that have a variable reference are an array of variables to display # the names of those variables are their index... @core. async def onVariables() -> core.awaitable[None]: self.variables = yield from variable.adapter.GetVariables( variable.reference) self.dirty() core.run(onVariables())
def toggle(self) -> None: self.expanded = not self.expanded if self.expanded: @core. async def onVariables() -> core.awaitable[None]: self.variables = yield from self.variable.adapter.GetVariables( self.variable.reference) self.dirty() core.run(onVariables()) self.fetched = True self.dirty()
def on_modified(self, view: sublime.View) -> None: if self.ignore_next_modification: self.ignore_next_modification = False return panel = OutputPhantomsPanel.for_view(view) if not panel: return text = self.editable_text(panel) core.main_loop.call_soon_threadsafe(panel.on_updated_input, text) if text and text != self.getting_completions_text: self.getting_completions_text = text core.run(self.get_completions(view, text))
def _start_render() -> None: _rendering = True @core.async def _run_render() -> core.awaitable[None]: last_time = core.main_loop.time() while _rendering: time = core.main_loop.time() delta = time - last_time last_time = time update(delta) render() yield from asyncio.sleep(0.05) core.run(_run_render())
def on_query_completions(self, view, prefix, locations) -> Any: panel = OutputPhantomsPanel.for_view(view) if not panel: return text = self.editable_text(panel) if text != self.getting_completions_text: self.getting_completions_text = text core.run(self.get_completions(view, text)) items = [] for completion in self.completions: items.append([completion.label, completion.text or completion.label]) return items
def on_text_hovered(self, event: ui.HoverEvent) -> None: if self.debugAdapterClient: word = event.view.word(event.point) expr = event.view.substr(word) def complete(response: Optional[EvaluateResponse]) -> None: if not response: return if self.debugAdapterClient: variable = Variable(self.debugAdapterClient, response.result, '', response.variablesReference) event.view.add_regions('selected_hover', [word], scope = "comment", flags = sublime.DRAW_NO_OUTLINE) def on_close() -> None: event.view.erase_regions('selected_hover') ui.Popup(VariableComponent(variable), event.view, word.a, on_close = on_close) core.run(self.debugAdapterClient.Evaluate(expr, 'hover'), complete)
def threadsCommandBase(self) -> None: def response(response: dict) -> None: def get_or_create_thread(id: int, name: str) -> Optional[Thread]: thread = self._thread_for_id(id) thread.name = name return thread threads = [] for thread in response['threads']: thread = get_or_create_thread(thread['id'], thread['name']) threads.append(thread) self.threads = threads self.onThreads.post(None) core.run(self.send_request_asyc('threads', {}), response)
def fetch_frames_if_needed(self) -> None: if self.thread.stopped and self.thread.expanded and not self.fetched: self.fetched = True print('fetching thread frames') def response(frames: List[StackFrame]) -> None: if not frames: self.frames = frames self.dirty() return if self.panel.selected_thread == self.thread and not self.panel.has_selection_frame( ): for i, frame in enumerate(frames): if frame.presentation != StackFrame.subtle: self.panel.set_selected(self.thread, frame, i) break else: self.panel.set_selected(self.thread, frames[0], 0) self.frames = frames self.dirty() core.run(self.thread.client.GetStackTrace(self.thread), response)
def launch(self, adapter_configuration: AdapterConfiguration, configuration: Configuration, breakpoints: Breakpoints) -> core.awaitable[None]: if self.launching_async: self.launching_async.cancel() self.launching_async = core.run(self._launch(adapter_configuration, configuration, breakpoints)) try: yield from self.launching_async except Exception as e: self.launching_async = None core.log_exception(e) if isinstance(e, core.CancelledError): self.log_info("... canceled") else: self.log_error("... an error occured, " + str(e)) self.force_stop_adapter() self.launching_async = None
def OnPlay(self) -> None: core.run(self.LaunchDebugger())
def shutdown() -> None: event = threading.Event() core.run(shutdown_main_thread(event)) event.wait() core.shutdown()
def startup() -> None: core.startup() core.run(startup_main_thread())
def on_text_hovered(self, event: ui.HoverEvent) -> None: core.run(self.async_on_text_hovered(event))
def OnStepOut(self) -> None: assert self.debugAdapterClient core.run(self.debugAdapterClient.StepOut())
def OnPause(self) -> None: assert self.debugAdapterClient core.run(self.debugAdapterClient.Pause())
def OnResume(self) -> None: assert self.debugAdapterClient core.run(self.debugAdapterClient.Resume())
def OnStop(self) -> None: if self.disconnecting: self.KillDebugger() else: core.run(self.Disconnect())
def OnSettings(self) -> None: core.run(self.EditSettings())
def onChangedBreakpoint(self, breakpoint: Breakpoint) -> None: if self.debugAdapterClient: file = breakpoint.file breakpoints = self.breakpoints.breakpoints_for_file(file) core.run(self.debugAdapterClient.SetBreakpointsFile(file, breakpoints))
def run_async(self, awaitable: core.awaitable[None]): def on_error(e: Exception) -> None: self.console_panel.AddStderr(str(e)) self.pages_panel.modified(2) core.run(awaitable, on_error=on_error)
def on_main(self, main: DebuggerInterface) -> None: core.run(main.SelectConfiguration())
def LaunchDebugger (self) -> Generator[Any, None, None]: self.KillDebugger() self.eventLog.clear() self.eventLog.Add('Starting debugger...') self.debuggerComponent.setState(LOADING) try: if not self.configuration: yield from self.EditSettings() if not self.configuration: return config = self.configuration debuggers = get_setting(self.window.active_view(), 'adapters', {}) debugger = debuggers.get(config.type) assert debugger, 'no debugger named {}'.format(config.type) adapter_type_config = sublime.expand_variables(debugger, self.window.extract_variables()) command = adapter_type_config.get('command') assert command, 'expected "command" in debugger settings' port = adapter_type_config.get('tcp_port') #If there is a command to run for this debugger run it now if port: print('Starting Process: {}'.format(command)) try: self.process = Process(command, on_stdout = lambda msg: self.eventLog.Add(msg), on_stderr = lambda msg: self.eventLog.Add(msg)) except Exception as e: self.eventLog.AddStderr('Failed to start debug adapter process: {}'.format(e)) self.eventLog.AddStderr('Command in question: {}'.format(command)) core.display('Failed to start debug adapter process: Check the Event Log for more details') address = adapter_type_config.get('tcp_address', 'localhost') try: transport = yield from start_tcp_transport(address, port) except Exception as e: self.eventLog.AddStderr('Failed to connect to debug adapter: {}'.format(e)) self.eventLog.AddStderr('address: {} port: {}'.format(address, port)) core.display('Failed to connect to debug adapter: Check the Event Log for more details and messages from the debug adapter process?') return else: # dont monitor stdout the StdioTransport users it self.process = Process(command, on_stdout = None, on_stderr = lambda msg: self.eventLog.Add(msg)) transport = StdioTransport(self.process) except Exception as e: core.display(e) return debugAdapterClient = DebugAdapterClient(transport) self.debugAdapterClient = debugAdapterClient def onOutput(event: OutputEvent) -> None: category = event.category msg = event.text variablesReference = event.variablesReference if variablesReference and self.debugAdapterClient: variable = Variable(self.debugAdapterClient, msg, '', variablesReference) self.eventLog.AddVariable(variable) elif category == "stdout": self.eventLog.AddStdout(msg) elif category == "stderr": self.eventLog.AddStderr(msg) elif category == "console": self.eventLog.Add(msg) def onStopped(event: StoppedEvent) -> None: self.pausedWithError = debugAdapterClient.stoppedOnError self.debuggerComponent.setState(PAUSED) self.eventLog.Add(event.reason) self.stopped_reason = event.reason if event.text: self.eventLog.Add(event.text) def onContinued(event: Any) -> None: self.debuggerComponent.setState(RUNNING) def onExited(event: Any) -> None: self.KillDebugger() def onThreads(event: Any) -> None: self.callstackComponent.setThreads(debugAdapterClient, debugAdapterClient.threads, self.pausedWithError) def onVariables(event: Any) -> None: self.variablesComponent.set_variables(debugAdapterClient.variables) def onSelectedStackFrame(frame: Optional[StackFrame]) -> None: self.onSelectedStackFrame(frame) self.callstackComponent.dirty_threads() def on_error(error: str) -> None: self.eventLog.AddStderr(error) debugAdapterClient.onSelectedStackFrame.add(onSelectedStackFrame) debugAdapterClient.onExited.add(onExited) debugAdapterClient.onOutput.add(onOutput) debugAdapterClient.onStopped.add(onStopped) debugAdapterClient.onContinued.add(onContinued) debugAdapterClient.onThreads.add(onThreads) debugAdapterClient.onVariables.add(onVariables) debugAdapterClient.on_error_event.add(on_error) # this is a bit of a weird case. Initialized will happen at some point in time # it depends on when the debug adapter chooses it is ready for configuration information # when it does happen we can then add all the breakpoints and complete the configuration @core.async def Initialized() -> Generator[Any, None, None]: yield from debugAdapterClient.Initialized() yield from debugAdapterClient.AddBreakpoints(self.breakpoints) yield from debugAdapterClient.ConfigurationDone() core.run(Initialized()) adapter_config = sublime.expand_variables(config.all, self.window.extract_variables()) print ('Adapter initialize') body = yield from debugAdapterClient.Initialize() for filter in body.get('exceptionBreakpointFilters', []): id = filter['filter'] name = filter['label'] default = filter.get('default', False) self.breakpoints.add_filter(id, name, default) print ('Adapter initialized: success!') if config.request == 'launch': yield from debugAdapterClient.Launch(adapter_config) elif config.request == 'attach': yield from debugAdapterClient.Attach(adapter_config) else: raise Exception('expected configuration to have request of either "launch" or "attach" found {}'.format(config.request)) print ('Adapter has been launched/attached') # At this point we are running? self.debuggerComponent.setState(RUNNING)
def on_main(self, main: DebuggerInterface) -> None: core.run(self.install(main))
def onChangedFilter(self, filter: Filter) -> None: if self.debugAdapterClient: core.run(self.debugAdapterClient.setExceptionBreakpoints(self. breakpoints.filters))