diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d817250..20a865d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,10 @@ If you learn something useful, please add it to this file. python -m unittest ``` +# Formatting + +Blueprint uses [Black](https://github.com/psf/black) for code formatting. + # Build the docs ```sh diff --git a/blueprintcompiler/decompiler.py b/blueprintcompiler/decompiler.py index 036c86f..1d9f4dd 100644 --- a/blueprintcompiler/decompiler.py +++ b/blueprintcompiler/decompiler.py @@ -22,7 +22,7 @@ from enum import Enum import typing as T from dataclasses import dataclass -from .xml_reader import Element, parse +from .xml_reader import Element, parse, parse_string from .gir import * from .utils import Colors @@ -211,6 +211,15 @@ def decompile(data: str) -> str: 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: if string == "class": return "klass" diff --git a/blueprintcompiler/lsp.py b/blueprintcompiler/lsp.py index dd12905..b44d631 100644 --- a/blueprintcompiler/lsp.py +++ b/blueprintcompiler/lsp.py @@ -24,7 +24,8 @@ import json, sys, traceback from .completions import complete from .errors import PrintableError, CompileError, MultipleErrors 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): @@ -149,6 +150,18 @@ class LanguageServer: ) 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): self._send( { @@ -169,7 +182,7 @@ class LanguageServer: def initialize(self, id, params): from . import main - self.client_capabilities = params.get("capabilities") + self.client_capabilities = params.get("capabilities", {}) self._send_response( id, { @@ -256,6 +269,41 @@ class LanguageServer: 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") def semantic_tokens(self, id, params): open_file = self._open_files[params["textDocument"]["uri"]] diff --git a/blueprintcompiler/lsp_utils.py b/blueprintcompiler/lsp_utils.py index 5e4ef89..219cade 100644 --- a/blueprintcompiler/lsp_utils.py +++ b/blueprintcompiler/lsp_utils.py @@ -69,6 +69,10 @@ class CompletionItemKind(enum.IntEnum): TypeParameter = 25 +class ErrorCode(enum.IntEnum): + RequestFailed = -32803 + + @dataclass class Completion: label: str diff --git a/blueprintcompiler/xml_reader.py b/blueprintcompiler/xml_reader.py index 5e31773..b2d579b 100644 --- a/blueprintcompiler/xml_reader.py +++ b/blueprintcompiler/xml_reader.py @@ -92,3 +92,9 @@ def parse(filename): parser.setContentHandler(handler) parser.parse(filename) return handler.root + + +def parse_string(xml): + handler = Handler() + parser = sax.parseString(xml, handler) + return handler.root