def __init__(self, window: sublime.Window): super().__init__() # ensure we are being run inside a sublime project # if not prompt the user to create one project_name = window.project_file_name() while not project_name: r = sublime.ok_cancel_dialog("Debugger requires a sublime project. Would you like to create a new sublime project?", "Save Project As...") if r: window.run_command('save_project_and_workspace_as') else: raise core.Error("Debugger must be run inside a sublime project") project_name = window.project_file_name() self.name = project_name self.window = window self.on_updated: core.Event[None] = core.Event() self.tasks: List[Task] = [] self.compounds: List[ConfigurationCompound] = [] self.configurations: List[Configuration] = [] self.configuration_or_compound: Optional[Union[Configuration, ConfigurationCompound]] = None self.external_terminal_kind = 'platform' self.ui_scale = 12 self.bring_window_to_front_on_pause = False # add the empty debugger configurations settings if needed data = window.project_data() or {} data.setdefault('debugger_configurations', []) window.set_project_data(data) self.disposables += Settings.updated.add(self.reload) self.reload()
def disable_in_project(window: sublime.Window, config_name: str) -> None: project_data = window.project_data() if isinstance(project_data, dict): project_settings = project_data.setdefault('settings', dict()) project_lsp_settings = project_settings.setdefault('LSP', dict()) project_client_settings = project_lsp_settings.setdefault( config_name, dict()) project_client_settings['enabled'] = False window.set_project_data(project_data) else: sublime.message_dialog( "Can't disable {} in the current workspace. Ensure that the project is saved first." .format(config_name))
def _handle_deactivate_rule(self, window: sublime.Window, args: List[str], done: Callable[[], None]) -> bool: data = window.project_data() root = data rule = args[0] data = _deeper_dict(data, "settings") data = _deeper_dict(data, "LSP") data = _deeper_dict(data, self.name()) data = _deeper_dict(data, "settings") data = _deeper_dict(data, "sonarlint") data = _deeper_dict(data, "rules") data[rule] = {"level": "off"} window.set_project_data(root) def report_to_user() -> None: fmt = 'The rule "{}" was added to the excluded list for SonarLint in your window project data. '\ 'If your window is maintained by a sublime project, the server should be restarted automatically. '\ 'Otherwise, you need to restart the server manually.' sublime.message_dialog(fmt.format(rule)) done() sublime.set_timeout(report_to_user) return True
def __init__(self, window: sublime.Window) -> None: # ensure we are being run inside a sublime project # if not prompt the user to create one while True: data = window.project_data() project_name = window.project_file_name() while not data or not project_name: r = sublime.ok_cancel_dialog("Debugger requires a sublime project. Would you like to create a new sublime project?", "Save Project As...") if r: window.run_command('save_project_and_workspace_as') else: raise core.Error("Debugger must be run inside a sublime project") # ensure we have debug configurations added to the project file data.setdefault('settings', {}).setdefault('debug.configurations', []) window.set_project_data(data) break self.project = DebuggerProject(window) autocomplete = Autocomplete.create_for_window(window) self.window = window self.disposeables = [] #type: List[Any] self.breakpoints = Breakpoints(); self.callstack_panel = CallStackPanel() self.breakpoints_panel = BreakpointsPanel(self.breakpoints) self.debugger_panel = DebuggerPanel(self, self.breakpoints_panel) def on_state_changed(state: int) -> None: if state == DebuggerStateful.stopped: self.debugger_panel.setState(STOPPED) self.show_console_panel() elif state == DebuggerStateful.running: self.debugger_panel.setState(RUNNING) elif state == DebuggerStateful.paused: self.debugger_panel.setState(PAUSED) if get_setting(self.view, 'bring_window_to_front_on_pause', False): # is there a better way to bring sublime to the front?? # this probably doesn't work for most people. subl needs to be in PATH file = self.window.active_view().file_name() if file: # ignore any errors try: subprocess.call(["subl", file]) except Exception: pass self.show_call_stack_panel() elif state == DebuggerStateful.stopping or state == DebuggerStateful.starting: self.debugger_panel.setState(LOADING) def on_scopes(scopes: List[dap.Scope]) -> None: self.variables_panel.set_scopes(scopes) def on_selected_frame(thread: Optional[dap.Thread], frame: Optional[dap.StackFrame]) -> None: if frame and thread and frame.source: self.source_provider.select(frame.source, frame.line, thread.stopped_text) else: self.source_provider.clear() def on_output(event: dap.OutputEvent) -> None: self.terminal.program_output(self.debugger.adapter, event) def on_threads_stateful(threads: Any): self.callstack_panel.update(self.debugger, threads) from .diff import DiffCollection from .terminal import Terminal def on_terminal_added(terminal: Terminal): component = TerminalComponent(terminal) panel = TabbedPanelItem(id(terminal), component, terminal.name(), 0, component.action_buttons()) def on_modified(): self.panels.modified(panel) terminal.on_updated.add(on_modified) self.panels.add([panel]) def on_terminal_removed(terminal: Terminal): self.panels.remove(id(terminal)) terminals = DiffCollection(on_terminal_added, on_terminal_removed) def on_terminals(list: Any): terminals.update(list) self.debugger = DebuggerStateful( self.breakpoints, on_state_changed=on_state_changed, on_scopes=on_scopes, on_output=on_output, on_selected_frame=on_selected_frame, on_threads_stateful=on_threads_stateful, on_terminals=on_terminals) self.variables_panel = VariablesPanel(self.breakpoints, self.debugger.watch) self.panel = OutputPhantomsPanel(window, 'Debugger') self.panel.show() self.view = self.panel.view #type: sublime.View self.persistance = PersistedData(project_name) self.load_data() self.load_settings_and_configurations() self.disposeables.extend([ self.panel, ]) self.disposeables.append(WindowSettingsCallback(self.window, self.on_settings_updated)) phantom_location = self.panel.phantom_location() phantom_view = self.panel.phantom_view() self.disposeables.extend([ ui.Phantom(self.debugger_panel, phantom_view, sublime.Region(phantom_location, phantom_location + 0), sublime.LAYOUT_INLINE), ]) callstack_panel_item = TabbedPanelItem(id(self.callstack_panel), self.callstack_panel, "Call Stack", 0) variables_panel_item = TabbedPanelItem(id(self.variables_panel), self.variables_panel, "Variables", 1) self.terminal = DebuggerTerminal( on_run_command=self.on_run_command, on_clicked_source=self.on_navigate_to_source ) terminal_component = TerminalComponent(self.terminal) terminal_panel_item = TabbedPanelItem(id(self.terminal), terminal_component, self.terminal.name(), 0) modules_panel = TabbedPanelItem(id(self.debugger.modules), ModulesView(self.debugger.modules), "Modules", 1) sources_panel = TabbedPanelItem(id(self.debugger.sources), SourcesView(self.debugger.sources), "Sources", 1) self.terminal.log_info('Opened In Workspace: {}'.format(os.path.dirname(project_name))) self.panels = Panels(phantom_view, phantom_location + 1, 3) self.panels.add([ callstack_panel_item, variables_panel_item, terminal_panel_item, modules_panel, sources_panel ]) view_hover = ViewHoverProvider(self.project, self.debugger) self.disposeables.append(view_hover) self.source_provider = ViewSelectedSourceProvider(self.project, self.debugger) self.disposeables.append(self.source_provider) self.breakpoints_provider = BreakpointCommandsProvider(self.project, self.debugger, self.breakpoints) self.disposeables.append(self.breakpoints_provider)
def __init__(self, window: sublime.Window) -> None: data = window.project_data() project_name = window.project_file_name() if not data or not project_name: sublime.error_message( "Debugger must be run inside a sublime project") return # ensure we have debug configurations added to the project file data.setdefault('settings', {}).setdefault('debug.configurations', []) window.set_project_data(data) ui.set_create_input_handler(window, self.create_input_handler) self.input_open = False self.window = window self.disposeables = [] #type: List[Any] self.breakpoints = Breakpoints() self.console_panel = ConsolePanel(self.open_repl_console) self.variables_panel = VariablesPanel() self.callstack_panel = CallStackPanel() self.breakpoints_panel = BreakpointsComponent( self.breakpoints, self.onSelectedBreakpoint) self.pages_panel = TabbedPanel([ ("Breakpoints", self.breakpoints_panel, None), ("Call Stack", self.callstack_panel, None), ("Console", self.console_panel, self.console_panel.change_filter), ], 0) self.debugger_panel = DebuggerPanel(self.breakpoints, self) self.selected_frame_line = None #type: Optional[SelectedLine] self.selected_frame_generated_view = None #type: Optional[sublime.View] self.breakpointInformation = None #type: Optional[Any] def on_state_changed(state: int) -> None: if state == DebuggerState.stopped: self.breakpoints.clear_breakpoint_results() self.debugger_panel.setState(STOPPED) self.show_console_panel() elif state == DebuggerState.running: self.debugger_panel.setState(RUNNING) elif state == DebuggerState.paused: self.debugger_panel.setState(PAUSED) if get_setting(self.view, 'bring_window_to_front_on_pause', False): # is there a better way to bring sublime to the front?? # this probably doesn't work for most people. subl needs to be in PATH file = self.window.active_view().file_name() if file: # ignore any errors try: subprocess.call(["subl", file]) except Exception: pass self.show_call_stack_panel() elif state == DebuggerState.stopping or state == DebuggerState.starting: self.debugger_panel.setState(LOADING) def on_threads(threads: List[Thread]) -> None: self.callstack_panel.update(self.debugger, threads) def on_scopes(scopes: List[Scope]) -> None: self.variables_panel.set_scopes(scopes) def on_selected_frame(thread: Optional[Thread], frame: Optional[StackFrame]) -> None: if frame and thread: self.run_async(self.navigate_to_frame(thread, frame)) else: self.dispose_selected_frame() def on_output(event: OutputEvent) -> None: category = event.category msg = event.text variablesReference = event.variablesReference if variablesReference and self.debugger.adapter: # this seems to be what vscode does it ignores the actual message here. # Some of the messages are junk like "output" that we probably don't want to display @core. async def appendVariabble() -> core.awaitable[None]: variables = yield from self.debugger.adapter.GetVariables( variablesReference) for variable in variables: variable.name = "" # this is what vs code does? self.console_panel.AddVariable(variable) self.pages_panel.modified(2) # this could make variable messages appear out of order. Do we care?? self.run_async(appendVariabble()) elif category == "stdout": self.console_panel.AddStdout(msg) self.pages_panel.modified(2) elif category == "stderr": self.console_panel.AddStderr(msg) self.pages_panel.modified(2) elif category == "telemetry": pass elif category == "output": self.console_panel.AddStdout(msg) self.pages_panel.modified(2) elif category == "error": self.console_panel.AddStderr(msg) self.pages_panel.modified(2) elif category == "info": self.console_panel.Add(msg) self.pages_panel.modified(2) else: self.console_panel.AddOutputOther(msg) self.pages_panel.modified(2) self.debugger = DebuggerState(on_state_changed=on_state_changed, on_threads=on_threads, on_scopes=on_scopes, on_output=on_output, on_selected_frame=on_selected_frame) self.panel = OutputPhantomsPanel(window, 'Debugger') self.panel.show() self.view = self.panel.view #type: sublime.View self.persistance = PersistedData(project_name) for breakpoint in self.persistance.load_breakpoints(): self.breakpoints.add(breakpoint) self.load_configurations() self.stopped_reason = '' self.path = window.project_file_name() if self.path: self.path = os.path.dirname(self.path) self.console_panel.Add('Opened In Workspace: {}'.format(self.path)) else: self.console_panel.AddStderr( 'warning: debugger opened in a window that is not part of a project' ) print('Creating a window: h') self.disposeables.extend([ self.panel, ui.view_gutter_hovered.add(self.on_gutter_hovered), ui.view_text_hovered.add(self.on_text_hovered), ui.view_drag_select.add(self.on_drag_select), ]) offset = self.panel.phantom_location() self.disposeables.extend([ ui.Phantom(self.debugger_panel, self.view, sublime.Region(offset, offset + 0), sublime.LAYOUT_INLINE), ui.Phantom(self.pages_panel, self.view, sublime.Region(offset, offset + 1), sublime.LAYOUT_INLINE), ui.Phantom(self.variables_panel, self.view, sublime.Region(offset, offset + 2), sublime.LAYOUT_INLINE), ]) self.breakpoints.onRemovedBreakpoint.add( lambda b: self.clearBreakpointInformation()) self.breakpoints.onChangedBreakpoint.add(self.onChangedBreakpoint) self.breakpoints.onChangedFilter.add(self.onChangedFilter) self.breakpoints.onSelectedBreakpoint.add(self.onSelectedBreakpoint) active_view = self.window.active_view() if active_view: self.disposeables.append( register_on_changed_setting(active_view, self.on_settings_updated)) else: print('Failed to find active view to listen for settings changes')
def __init__(self, window: sublime.Window): super().__init__() # ensure we are being run inside a sublime project # if not prompt the user to create one while True: data = window.project_data() project_name = window.project_file_name() while not project_name: r = sublime.ok_cancel_dialog( "Debugger requires a sublime project. Would you like to create a new sublime project?", "Save Project As...") if r: window.run_command('save_project_and_workspace_as') else: raise core.Error( "Debugger must be run inside a sublime project") # ensure we have debug configurations added to the project file data.setdefault('settings', {}).setdefault('debug.configurations', []) window.set_project_data(data) break self.name = project_name self.window = window self.on_updated: core.Event[None] = core.Event() self.compounds: List[ConfigurationCompound] = [] self.configurations: List[Configuration] = [] self.external_terminal_kind = 'platform' self.ui_scale = 12 self.bring_window_to_front_on_pause = False self.panel = self.window.create_output_panel("Debugger") self.panel_show() # we need enough space to place our phantoms in increasing regions (1, 1), (1, 2)... etc # otherwise they will get reordered when one of them gets redrawn # we use new lines so we don't have extra space on the rhs self.panel.run_command('insert', {'characters': _phantom_text}) settings = self.panel.settings() settings.set("margin", 0) settings.set('line_padding_top', 1) settings.set('gutter', False) settings.set('word_wrap', False) settings.set('line_spacing', 0) settings.set('context_menu', 'Widget Debug.sublime-menu') self.panel.sel().clear() # hack to get view to not freak out when clicking the edge of the window self.panel.set_viewport_position((_panel_position, 0), animate=False) async def later(): await core.sleep(0) self.panel.set_viewport_position((_panel_position, 0), animate=False) core.run(later()) self.reload()