Skip to content

Commit

Permalink
Updated protocol logs to include more details and syntax highlight be…
Browse files Browse the repository at this point in the history
…tter
  • Loading branch information
daveleroy committed Oct 15, 2022
1 parent 3988fc3 commit 0e63caf
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 126 deletions.
37 changes: 19 additions & 18 deletions Commands/DebuggerProtocol.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,26 @@ name: Debugger Protocol

contexts:
main:
- match: '(⟽|⟸) '
- match: '((<-)|(->)) ([a-zA-Z]*) (..)'
captures:
1: storage.modifier
push: request

- match: '(⟾|⟹) '
captures:
1: storage.type
push: request
2: comment
3: comment
4: comment
5: punctuation.separator
embed: scope:source.js
escape: '\n'
pop: true

request:
- match: '(::)'
- match: '((<-)|(->)) ([a-zA-Z]*)(\((.*)\))? (::|!!)'
captures:
1: punctuation.separator
# 2: comment
2: region.bluish debugger.background
3: region.redish debugger.background
4: entity.name.function
6: constant.numeric
7: punctuation.separator
embed: scope:source.js
escape: '\n'
pop: true
- match: '([0-9]*)'
captures:
1: constant.numeric
- match: '([a-zA-Z/]*)'
captures:
1: entity.name.function



2 changes: 1 addition & 1 deletion modules/adapters/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ async def on_custom_event(self, session: dap.Session, event: str, body: Any):
configuration_expanded = dap.ConfigurationExpanded(configuration, session.configuration.variables)
await session.debugger.launch(session.breakpoints, self, configuration_expanded, parent=session)
else:
core.error(f'event ignored not implemented {event}')
core.info(f'event not handled `{event}`')

# TODO: patch in env since python seems to not inherit it from the adapter process.
async def configuration_resolve(self, configuration: dap.ConfigurationExpanded):
Expand Down
3 changes: 2 additions & 1 deletion modules/dap/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def did_stop_debugging(self, session: Session):
...

async def on_custom_event(self, session: Session, event: str, body: Any):
core.error(f'event ignored not implemented {event}')
core.info(f'event not handled `{event}`')

async def on_custom_request(self, session: Session, command: str, arguments: dict[str, Any]) -> dict[str, Any] | None:
...
Expand Down Expand Up @@ -213,6 +213,7 @@ def _expand_variables_and_platform(json: dict[str, Any], variables: dict[str, st
# Its mostly so we can redefine $project_path when specifying a project file in debugger_configurations so $project_path refers to the correct location
if json_variables := json.get('$'):
json = sublime.expand_variables(json, json_variables)
del json['$']

if variables := variables:
json = sublime.expand_variables(json, variables)
Expand Down
76 changes: 45 additions & 31 deletions modules/dap/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@
from __future__ import annotations
from typing import Any, Awaitable, Protocol

from dataclasses import dataclass

from ..import core
from .error import Error

import threading
from dataclasses import dataclass


class Transport(Protocol):
Expand All @@ -37,46 +36,63 @@ async def on_reverse_request(self, command: str, arguments: dict[str, Any]) -> d

def on_transport_closed(self): ...


@dataclass
class TransportStdoutOutputLog:
output: str
def __str__(self) -> str:
return '-> stdout :: ' + self.output

@dataclass
class TransportStderrOutputLog:
output: str
def __str__(self) -> str:
return '-> stderr !! ' + self.output

@dataclass
class TransportLog:
out: bool
class TransportDataLog:
data: dict[str, Any]

def __str__(self) -> str:
data = self.data
out = self.out
data: dict[str, Any] = self.data
data_formatted = core.json_encode(data)

type = data.get('type')

def sigil(success: bool):
if success:
if out:
return '⟸'
else:
return '⟹'
return '::'
else:
if out:
return '⟽'
else:
return '⟾'
return '!!'

if type == 'response':
id = data.get('request_seq')
command = data.get('command')
body = data.get('body', data.get('message'))
return f'{sigil(data.get("success", False))} response/{command}({id}) :: {body}'
return f'{command}({id}) {sigil(data.get("success", False))} {data_formatted}'

if type == 'request':
id = data.get('seq')
command = data.get('command')
body = data.get('arguments')
return f'{sigil(True)} request/{command}({id}) :: {body}'
return f'{command}({id}) :: {data_formatted}'

if type == 'event':
command = data.get('event')
body = data.get('body')
return f'{sigil(True)} event/{command} :: {body}'

return f'{command} .. {data_formatted}'

return f'unknown :: {data_formatted}'

return f'{sigil(False)} {type}/unknown :: {data}'
class TransportIncomingDataLog(TransportDataLog):
data: dict[str, Any]

def __str__(self) -> str:
return '-> ' + super().__str__()

class TransportOutgoingDataLog(TransportDataLog):
data: dict[str, Any]

def __str__(self) -> str:
return '<- ' + super().__str__()


class TransportProtocol:
Expand All @@ -93,7 +109,7 @@ def __init__(
self.pending_requests: dict[int, core.Future[dict[str, Any]]] = {}
self.seq = 0

self.transport_log.log('transport', f'⟸ process/started ::')
self.transport_log.log('transport', f'-- begin transport protocol')
self.thread = threading.Thread(target=self.read)
self.thread.start()

Expand Down Expand Up @@ -138,7 +154,9 @@ def read(self):
core.call_soon_threadsafe(self.recieved_msg, core.json_decode(content))

except Exception as e:
core.call_soon_threadsafe(self.transport_log.log,'transport', f'⟸ process/stopped :: {e}')
msg = '-- end transport protocol: ' + (str(e) or 'eof')

core.call_soon_threadsafe(lambda: self.transport_log.log('transport', msg))
core.call_soon_threadsafe(self.events.on_transport_closed)

def send(self, message: dict[str, Any]):
Expand All @@ -163,9 +181,8 @@ def send_request_asyc(self, command: str, args: dict[str, Any]|None) -> Awaitabl

self.pending_requests[self.seq] = future

self.log_transport(True, request)
self.transport_log.log('transport', TransportOutgoingDataLog(request))
self.send(request)

return future

def send_response(self, request: dict[str, Any], body: dict[str, Any], error: str|None = None) -> None:
Expand All @@ -186,12 +203,9 @@ def send_response(self, request: dict[str, Any], body: dict[str, Any], error: st
'message': error,
}

self.log_transport(True, data)
self.transport_log.log('transport', TransportOutgoingDataLog(data))
self.send(data)

def log_transport(self, out: bool, data: dict[str, Any]):
self.transport_log.log('transport', TransportLog(out, data))

@core.schedule
async def handle_reverse_request(self, request: dict[str, Any]):
command = request['command']
Expand All @@ -203,9 +217,9 @@ async def handle_reverse_request(self, request: dict[str, Any]):
self.send_response(request, {}, error=str(e))

def recieved_msg(self, data: dict[str, Any]) -> None:
t = data['type']
self.log_transport(False, data)
self.transport_log.log('transport', TransportIncomingDataLog(data))

t = data['type']
if t == 'response':
try:
future = self.pending_requests.pop(data['request_seq'])
Expand Down
96 changes: 21 additions & 75 deletions modules/dap/transports.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import IO, Any, Callable

from ..import core
from .transport import Transport
from .transport import Transport, TransportStderrOutputLog, TransportStdoutOutputLog

import socket
import os
Expand Down Expand Up @@ -81,17 +81,13 @@ def on_stderr(self, callback: Callable[[str], None]):

def _read_all(self, file: Any, callback: Callable[[str], None]) -> None:
while True:
try:
line = file.read(2**15).decode('UTF-8')
if not line:
core.info('Nothing to read from process, closing')
break
core.info(line)
core.call_soon_threadsafe(callback, line)
except Exception as e:
core.exception()
line = file.read(2**15).decode('UTF-8')
if not line:
break

core.info(line)
core.call_soon_threadsafe(callback, line)

def _readline(self, pipe: IO[bytes]) -> bytes:
if l := pipe.readline():
return l
Expand All @@ -118,31 +114,15 @@ def dispose(self):

class StdioTransport(Transport):
def __init__(self, log: core.Logger, command: list[str], cwd: str|None = None, stderr: Callable[[str], None] | None = None):
log.log('transport', f'⟸ process/starting :: {command}')
self.process = Process(command, cwd)
log.log('transport', f'-- stdio transport: {command}')

def log_stderr(data: str):
log.log('transport', f'⟸ process/stderr :: {data}')
log.log('transport', TransportStderrOutputLog(data))
if stderr:
stderr(data)

thread = threading.Thread(target=self._read, args=(self.process.stderr, log_stderr))
thread.start()

def _read(self, file: Any, callback: Callable[[str], None]) -> None:
while True:
try:
line = file.read(2**15).decode('UTF-8')
if not line:
core.info('Nothing to read from process, closing')
break

core.call_soon_threadsafe(callback, line)
except Exception as e:
core.exception()
break

self.process.dispose()
self.process = Process(command, cwd)
self.process.on_stderr(log_stderr)

def write(self, message: bytes) -> None:
self.process.stdin.write(message)
Expand All @@ -164,6 +144,7 @@ def dispose(self) -> None:

class SocketTransport(Transport):
def __init__(self, log: core.Logger, host: str, port: int):
log.log('transport', f'-- socket transport: {host}:{port}')
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((host, port))
self.stdin = self.socket.makefile('wb')
Expand All @@ -184,6 +165,7 @@ async def connect_with_retry(log: core.Logger, host: str, port: int):

@staticmethod
async def connect_with_process(log: core.Logger, command: list[str], port: int, process_is_program_output: bool = False):
log.log('transport', f'-- socket transport process: {command}')
process = Process(command)

# log the data to the console here instead of sending it to the protocol panel
Expand All @@ -192,22 +174,17 @@ async def connect_with_process(log: core.Logger, command: list[str], port: int,
process.on_stdout(lambda data: log.log('stdout', data))
process.on_stderr(lambda data: log.log('stderr', data))
else:
process.on_stdout(lambda data: log.log('transport', f'⟸ process/stdout :: {data}'))
process.on_stderr(lambda data: log.log('transport', f'⟸ process/stderr :: {data}'))

exception: Exception|None = None
for _ in range(0, 8):
try:
transport = SocketTransport(log, 'localhost', port)
transport.process = process
return transport
process.on_stdout(lambda data: log.log('transport', TransportStdoutOutputLog(data)))
process.on_stderr(lambda data: log.log('transport', TransportStderrOutputLog(data)))

except Exception as e:
await core.sleep(0.25)
exception = e
try:
transport = await SocketTransport.connect_with_retry(log, 'localhost', port)
transport.process = process
return transport

process.dispose()
raise exception or core.Error('unreachable')
except Exception as e:
process.dispose()
raise e

def write(self, message: bytes) -> None:
self.stdin.write(message)
Expand All @@ -232,34 +209,3 @@ def dispose(self) -> None:
if self.process:
self.process.dispose()


# class StdioSocketTransport(Transport):
# def __init__(self, regex: Any, port: int, log: core.Logger):
# self.process = adapter_process

# super().__init__(log, 'localhost', port)

# def log_stderr(data: str):
# log.log('transport', f'⟸ process/stderr :: {data}')

# thread = threading.Thread(target=self._read, args=(self.process.stderr, log_stderr))
# thread.start()

# def connect(self):
# adapter.SocketTransport

# def _read(self, file: Any, callback: Callable[[str], None]) -> None:
# while True:
# try:
# line = file.read(2**15).decode('UTF-8')
# if not line:
# core.info('Nothing to read from process, closing')
# break
# core.info(line)
# core.call_soon_threadsafe(callback, line)
# except Exception as e:
# core.exception()
# break

# def dispose(self) -> None:
# self.process.dispose()

0 comments on commit 0e63caf

Please sign in to comment.