Пример #1
0
def select_configuration(
        window: sublime.Window,
        index: int) -> core.awaitable[Optional[Configuration]]:
    try:
        configs = all_configurations(window)
    except Exception as e:
        core.display(e)
        show_settings(window)

    done = core.main_loop.create_future()
    names = list(map(lambda x: x.name, configs)) + ["-"
                                                    ] + ["Add configuration"]

    index = yield from core.sublime_show_quick_panel_async(
        window, names, index)
    if index < 0:
        return None
    if index >= len(configs):
        project = window.project_file_name()
        if project:
            sublime.run_command("new_window")
            window = sublime.active_window()
            window.open_file(project)
        else:
            window.run_command(
                'edit_settings',
                {"base_file": "${packages}/sublime_db/debug.sublime-settings"})
        return None
    return configs[index]
Пример #2
0
    def LaunchDebugger(self) -> core.awaitable[None]:
        self.console_panel.clear()
        self.console_panel.Add('Console cleared...')
        try:
            if not self.configuration:
                yield from self.SelectConfiguration()

            if not self.configuration:
                return

            configuration = self.configuration

            adapter_configuration = self.adapters.get(configuration.type)
            if not adapter_configuration:
                raise Exception(
                    'Unable to find debug adapter with the type name "{}"'.
                    format(configuration.type))

        except Exception as e:
            core.log_exception()
            core.display(e)
            return

        yield from self.debugger.launch(adapter_configuration, configuration,
                                        self.breakpoints)
Пример #3
0
	def _set_value(self, value: str) -> core.awaitable[None]:
		try:
			variable = yield from self.variable.client.setVariable(self.variable, value)
			self.variable = variable
			if self.fetched:
				self._fetch_if_needed(True)
			self.on_updated()
		except Exception as e:
			core.log_exception()
			core.display(e)
Пример #4
0
def insert_snippet(window: sublime.Window, snippet: dict) -> core.awaitable[None]:
	content = json.dumps(snippet, indent="\t")
	content = content.replace('\\\\', '\\') # remove json encoded \ ...
	project = window.project_file_name()
	if project:
		view = yield from core.sublime_open_file_async(window, project)
		region = view.find('''"\s*debug.configurations\s*"\s*:\s*\[''', 0)
		view.sel().clear()
		view.sel().add(sublime.Region(region.b, region.b))
		view.run_command('insert', {
			'characters': '\n'
		})
		view.run_command('insert_snippet', {
			'contents': content + ','
		})
	else:
		sublime.set_clipboard(content)
		core.display('Unable to insert configuration into sublime-project file: Copied to clipboard instead')
Пример #5
0
    def load_configurations(self) -> None:
        adapters = {}
        for adapter_name, adapter_json in get_setting(
                self.window.active_view(), 'adapters', {}).items():
            try:
                adapter = AdapterConfiguration.from_json(
                    adapter_name, adapter_json, self.window)
                adapters[adapter.type] = adapter
            except Exception as e:
                core.display(
                    'There was an error creating a AdapterConfiguration {}'.
                    format(e))

        configurations = []
        configurations_json = []  #type: list
        data = self.window.project_data()
        if data:
            configurations_json = data.setdefault('settings', {}).setdefault(
                'debug.configurations', [])

        for index, configuration_json in enumerate(configurations_json):
            configuration = Configuration.from_json(configuration_json)
            configuration.all = sublime.expand_variables(
                configuration.all, extract_variables(self.window))
            configuration.index = index
            configurations.append(configuration)

        self.adapters = adapters
        self.configurations = configurations
        self.configuration = self.persistance.load_configuration_option(
            configurations)

        if self.configuration:
            self.debugger_panel.set_name(self.configuration.name)
        else:
            self.debugger_panel.set_name('select config')

        assert self.view
        self.view.settings().set('font_size',
                                 get_setting(self.view, 'ui_scale', 12))
Пример #6
0
	def __init__(self, window: sublime.Window) -> None:
		print('new Main for window', window.id())
		self.window = window
		self.disposeables = [] #type: List[Any]
		self.breakpoints = Breakpoints()
		self.view = None #type: Optional[sublime.View]
		self.eventLog = EventLogComponent()
		self.variablesComponent = VariablesComponent()
		self.callstackComponent = CallStackComponent()
		self.debuggerComponent = DebuggerComponent(self.breakpoints, self)

		self.debugAdapterClient = None #type: Optional[DebugAdapterClient]
		
		self.selectedFrameComponent = None #type: Optional[ui.Phantom]
		self.breakpointInformation = None #type: Optional[ui.Phantom]
		self.pausedWithError = False
		self.process = None #type: Optional[Process]
		self.disconnecting = False

		self.project_name = window.project_file_name() or "user"
		data = config.persisted_for_project(self.project_name)
		config_name = data.get('config_name')
		config_maybe_at_index = data.get('config_maybe_at_index')

		for bp in data.get('breakpoints', []):
			self.breakpoints.add(Breakpoint.from_json(bp))

		if config_name:
			self.configuration = get_configuration_for_name(window, config_name, config_maybe_at_index)
		else:
			self.configuration = None
			
		if self.configuration:
			self.debuggerComponent.set_name(self.configuration.name)
		else:
			self.debuggerComponent.set_name('select config')

		self.stopped_reason = ''
		self.path = window.project_file_name()
		if self.path:
			self.path = os.path.dirname(self.path)
			self.eventLog.Add('Opened In Workspace: {}'.format(self.path))
		else:
			self.eventLog.AddStderr('warning: debugger opened in a window that is not part of a project')
			
		print('Creating a window: h')
		
		self.disposeables.extend([
			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),
		])
		
		mode = get_setting(window.active_view(), 'display')

		if mode == 'window':
			sublime.run_command("new_window")
			new_window = sublime.active_window()
			output = new_window.new_file()
			new_window.set_minimap_visible(False)
			new_window.set_sidebar_visible(False)
			new_window.set_tabs_visible(False)
			new_window.set_menu_visible(False)
			new_window.set_status_bar_visible(False)
		elif mode == 'view':
			output = self.window.new_file()
		elif mode == 'output':
			output = self.window.create_output_panel('debugger')
			self.window.run_command('show_panel', {
				'panel': 'output.debugger'
			})
		else:
			core.display('expected setting "mode" to be one of "window", "view" or "output", found "{}"'.format(mode))
			return
		
		output.run_command('insert', {
			'characters': "      "
		})
		output.set_scratch(True)
		output.set_read_only(True)
		output.set_name('Debugger')
		view_settings = output.settings()
		view_settings.set("is_widget", True)
		view_settings.set("gutter", False)
		view_settings.set("margin", 0)
		view_settings.set("always_show_minimap_viewport", False)		
		self.view = output

		self.disposeables.extend([
			ui.Phantom(self.debuggerComponent, output, sublime.Region(1, 1), sublime.LAYOUT_INLINE),
			ui.Phantom(self.callstackComponent, output, sublime.Region(1, 2), sublime.LAYOUT_INLINE),
			ui.Phantom(self.variablesComponent, output, sublime.Region(1, 3), sublime.LAYOUT_INLINE),
			ui.Phantom(self.eventLog, output, sublime.Region(1, 4), 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)
Пример #7
0
	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)
Пример #8
0
	def _launch(self, adapter_configuration: AdapterConfiguration, configuration: Configuration, breakpoints: Breakpoints) -> core.awaitable[None]:
		if self.state != DebuggerState.stopped:
			print('stopping debug adapter')
			yield from self.stop()

		assert(self.state == DebuggerState.stopped, "debugger not in stopped state?")
		self.state = DebuggerState.starting
		self.adapter_configuration = adapter_configuration
		self.configuration = configuration

		if not adapter_configuration.installed:
			raise Exception('Debug adapter with type name "{}" is not installed. You can install it by running Debugger: Install Adapters'.format(adapter_configuration.type))


		# If there is a command to run for this debugger run it now
		if adapter_configuration.tcp_port:
			self.log_info('starting debug adapter...')
			try:
				self.process = Process(adapter_configuration.command, on_stdout=self.log_info, on_stderr=self.log_info)
			except Exception as e:
				self.log_error('Failed to start debug adapter process: {}'.format(e))
				self.log_error('Command in question: {}'.format(adapter_configuration.command))
				core.display('Failed to start debug adapter process: Check the Event Log for more details')
				raise Exception("failed to start debug adapter process")
			tcp_address = adapter_configuration.tcp_address or 'localhost'
			try:
				transport = yield from start_tcp_transport(tcp_address, adapter_configuration.tcp_port)
			except Exception as e:
				self.log_error('Failed to connect to debug adapter: {}'.format(e))
				self.log_error('address: {} port: {}'.format(tcp_address, adapter_configuration.tcp_port))
				core.display('Failed to connect to debug adapter: Check the Event Log for more details and messages from the debug adapter process?')
				raise Exception("failed to start debug adapter process")

			self.log_info('... debug adapter started')
		else:
			# dont monitor stdout the StdioTransport users it
			self.process = Process(adapter_configuration.command, on_stdout=None, on_stderr=self.log_info)
			transport = StdioTransport(self.process)

		adapter = DebugAdapterClient(transport)
		adapter.onThreads.add(self._on_threads_event)
		adapter.onOutput.add(self._on_output_event)
		adapter.onStopped.add(self._on_stopped_event)
		adapter.onContinued.add(self._on_continued_event)
		adapter.onExited.add(self._on_exited_event)

		self.log_info("starting debugger... ")

		# 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() -> core.awaitable[None]:
			yield from adapter.Initialized()
			yield from adapter.AddBreakpoints(breakpoints)
			yield from adapter.ConfigurationDone()
		core.run(Initialized())

		capabilities = yield from adapter.Initialize()
		for filter in capabilities.exceptionBreakpointFilters:
			breakpoints.add_filter(filter.id, filter.label, filter.default)

		if configuration.request == 'launch':
			self.launch_request = True
			yield from adapter.Launch(configuration.all)
		elif configuration.request == 'attach':
			self.launch_request = False
			yield from adapter.Attach(configuration.all)
		else:
			raise Exception('expected configuration to have request of either "launch" or "attach" found {}'.format(configuration.request))

		self.adapter = adapter
		# At this point we are running?
		self.state = DebuggerState.running