예제 #1
0
	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()
예제 #2
0
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))
예제 #3
0
    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
예제 #4
0
	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)
예제 #5
0
    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()