lsp: Add compile an decompile commands

This commit is contained in:
Sonny Piers 2023-03-19 22:14:42 +00:00 committed by James Westman
parent 8c3c43a34a
commit 6f4806bfb3
5 changed files with 74 additions and 3 deletions

View file

@ -8,6 +8,10 @@ If you learn something useful, please add it to this file.
python -m unittest python -m unittest
``` ```
# Formatting
Blueprint uses [Black](https://github.com/psf/black) for code formatting.
# Build the docs # Build the docs
```sh ```sh

View file

@ -22,7 +22,7 @@ from enum import Enum
import typing as T import typing as T
from dataclasses import dataclass from dataclasses import dataclass
from .xml_reader import Element, parse from .xml_reader import Element, parse, parse_string
from .gir import * from .gir import *
from .utils import Colors from .utils import Colors
@ -211,6 +211,15 @@ def decompile(data: str) -> str:
return ctx.result return ctx.result
def decompile_string(data):
ctx = DecompileCtx()
xml = parse_string(data)
_decompile_element(ctx, None, xml)
return ctx.result
def canon(string: str) -> str: def canon(string: str) -> str:
if string == "class": if string == "class":
return "klass" return "klass"

View file

@ -24,7 +24,8 @@ import json, sys, traceback
from .completions import complete from .completions import complete
from .errors import PrintableError, CompileError, MultipleErrors from .errors import PrintableError, CompileError, MultipleErrors
from .lsp_utils import * from .lsp_utils import *
from . import tokenizer, parser, utils, xml_reader from .outputs.xml import XmlOutput
from . import tokenizer, parser, utils, xml_reader, decompiler
def printerr(*args, **kwargs): def printerr(*args, **kwargs):
@ -149,6 +150,18 @@ class LanguageServer:
) )
sys.stdout.flush() sys.stdout.flush()
def _send_error(self, id, code, message, data=None):
self._send(
{
"id": id,
"error": {
"code": code,
"message": message,
"data": data,
},
}
)
def _send_response(self, id, result): def _send_response(self, id, result):
self._send( self._send(
{ {
@ -169,7 +182,7 @@ class LanguageServer:
def initialize(self, id, params): def initialize(self, id, params):
from . import main from . import main
self.client_capabilities = params.get("capabilities") self.client_capabilities = params.get("capabilities", {})
self._send_response( self._send_response(
id, id,
{ {
@ -256,6 +269,41 @@ class LanguageServer:
id, [completion.to_json(True) for completion in completions] id, [completion.to_json(True) for completion in completions]
) )
@command("textDocument/x-blueprint-compile")
def compile(self, id, params):
open_file = self._open_files[params["textDocument"]["uri"]]
if open_file.ast is None:
self._send_error(id, ErrorCode.RequestFailed, "Document is not open")
return
xml = None
try:
output = XmlOutput()
xml = output.emit(open_file.ast)
except:
printerr(traceback.format_exc())
self._send_error(id, ErrorCode.RequestFailed, "Could not compile document")
return
self._send_response(id, {"xml": xml})
@command("x-blueprint/decompile")
def decompile(self, id, params):
text = params.get("text")
blp = None
try:
blp = decompiler.decompile_string(text)
except decompiler.UnsupportedError as e:
self._send_error(id, ErrorCode.RequestFailed, e.message)
return
except:
printerr(traceback.format_exc())
self._send_error(id, ErrorCode.RequestFailed, "Invalid input")
return
self._send_response(id, {"blp": blp})
@command("textDocument/semanticTokens/full") @command("textDocument/semanticTokens/full")
def semantic_tokens(self, id, params): def semantic_tokens(self, id, params):
open_file = self._open_files[params["textDocument"]["uri"]] open_file = self._open_files[params["textDocument"]["uri"]]

View file

@ -69,6 +69,10 @@ class CompletionItemKind(enum.IntEnum):
TypeParameter = 25 TypeParameter = 25
class ErrorCode(enum.IntEnum):
RequestFailed = -32803
@dataclass @dataclass
class Completion: class Completion:
label: str label: str

View file

@ -92,3 +92,9 @@ def parse(filename):
parser.setContentHandler(handler) parser.setContentHandler(handler)
parser.parse(filename) parser.parse(filename)
return handler.root return handler.root
def parse_string(xml):
handler = Handler()
parser = sax.parseString(xml, handler)
return handler.root