mirror of
https://gitlab.gnome.org/jwestman/blueprint-compiler.git
synced 2025-05-04 15:59:08 -04:00
reorganization: Move decompilers
This commit is contained in:
parent
ee5f32622f
commit
1150ae1a09
11 changed files with 138 additions and 140 deletions
|
@ -22,7 +22,6 @@ from enum import Enum
|
|||
import typing as T
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .language import gtk_a11y
|
||||
from .xml_reader import Element, parse
|
||||
from .gir import *
|
||||
from .utils import Colors
|
||||
|
@ -126,11 +125,11 @@ class DecompileCtx:
|
|||
|
||||
def print_attribute(self, name, value, type):
|
||||
if type is None:
|
||||
self.print(f"{name}: \"{_escape_quote(value)}\";")
|
||||
self.print(f"{name}: \"{escape_quote(value)}\";")
|
||||
elif type.assignable_to(FloatType()):
|
||||
self.print(f"{name}: {value};")
|
||||
elif type.assignable_to(BoolType()):
|
||||
val = _truthy(value)
|
||||
val = truthy(value)
|
||||
self.print(f"{name}: {'true' if val else 'false'};")
|
||||
elif (
|
||||
type.assignable_to(self.gir.namespaces["Gtk"].lookup_type("Gdk.Pixbuf"))
|
||||
|
@ -139,7 +138,7 @@ class DecompileCtx:
|
|||
or type.assignable_to(self.gir.namespaces["Gtk"].lookup_type("Gtk.ShortcutAction"))
|
||||
or type.assignable_to(self.gir.namespaces["Gtk"].lookup_type("Gtk.ShortcutTrigger"))
|
||||
):
|
||||
self.print(f"{name}: \"{_escape_quote(value)}\";")
|
||||
self.print(f"{name}: \"{escape_quote(value)}\";")
|
||||
elif type.assignable_to(self.gir.namespaces["Gtk"].lookup_type("GObject.Object")):
|
||||
self.print(f"{name}: {value};")
|
||||
elif isinstance(type, Enumeration):
|
||||
|
@ -153,7 +152,7 @@ class DecompileCtx:
|
|||
flags = re.sub(r"\s*\|\s*", " | ", value).replace("-", "_")
|
||||
self.print(f"{name}: {flags};")
|
||||
else:
|
||||
self.print(f"{name}: \"{_escape_quote(value)}\";")
|
||||
self.print(f"{name}: \"{escape_quote(value)}\";")
|
||||
|
||||
|
||||
def _decompile_element(ctx: DecompileCtx, gir, xml):
|
||||
|
@ -162,7 +161,7 @@ def _decompile_element(ctx: DecompileCtx, gir, xml):
|
|||
if decompiler is None:
|
||||
raise UnsupportedError(f"unsupported XML tag: <{xml.tag}>")
|
||||
|
||||
args = {_canon(name): value for name, value in xml.attrs.items()}
|
||||
args = {canon(name): value for name, value in xml.attrs.items()}
|
||||
if decompiler._cdata:
|
||||
if len(xml.children):
|
||||
args["cdata"] = None
|
||||
|
@ -194,19 +193,19 @@ def decompile(data):
|
|||
|
||||
|
||||
|
||||
def _canon(string: str) -> str:
|
||||
def canon(string: str) -> str:
|
||||
if string == "class":
|
||||
return "klass"
|
||||
else:
|
||||
return string.replace("-", "_").lower()
|
||||
|
||||
def _truthy(string: str) -> bool:
|
||||
def truthy(string: str) -> bool:
|
||||
return string.lower() in ["yes", "true", "t", "y", "1"]
|
||||
|
||||
def _full_name(gir):
|
||||
def full_name(gir):
|
||||
return gir.name if gir.full_name.startswith("Gtk.") else gir.full_name
|
||||
|
||||
def _lookup_by_cname(gir, cname: str):
|
||||
def lookup_by_cname(gir, cname: str):
|
||||
if isinstance(gir, GirContext):
|
||||
return gir.get_type_by_cname(cname)
|
||||
else:
|
||||
|
@ -221,7 +220,7 @@ def decompiler(tag, cdata=False):
|
|||
return decorator
|
||||
|
||||
|
||||
def _escape_quote(string: str) -> str:
|
||||
def escape_quote(string: str) -> str:
|
||||
return (string
|
||||
.replace("\\", "\\\\")
|
||||
.replace("\'", "\\'")
|
||||
|
@ -239,36 +238,6 @@ def decompile_requires(ctx, gir, lib=None, version=None):
|
|||
return gir
|
||||
|
||||
|
||||
@decompiler("template")
|
||||
def decompile_template(ctx, gir, klass, parent="Widget"):
|
||||
gir_class = ctx.type_by_cname(parent)
|
||||
if gir_class is None:
|
||||
ctx.print(f"template {klass} : .{parent} {{")
|
||||
else:
|
||||
ctx.print(f"template {klass} : {_full_name(gir_class)} {{")
|
||||
return gir_class
|
||||
|
||||
|
||||
@decompiler("object")
|
||||
def decompile_object(ctx, gir, klass, id=None):
|
||||
gir_class = ctx.type_by_cname(klass)
|
||||
klass_name = _full_name(gir_class) if gir_class is not None else "." + klass
|
||||
if id is None:
|
||||
ctx.print(f"{klass_name} {{")
|
||||
else:
|
||||
ctx.print(f"{klass_name} {id} {{")
|
||||
return gir_class
|
||||
|
||||
|
||||
@decompiler("child")
|
||||
def decompile_child(ctx, gir, type=None, internal_child=None):
|
||||
if type is not None:
|
||||
ctx.print(f"[{type}]")
|
||||
elif internal_child is not None:
|
||||
ctx.print(f"[internal-child {internal_child}]")
|
||||
return gir
|
||||
|
||||
|
||||
@decompiler("property", cdata=True)
|
||||
def decompile_property(ctx, gir, name, cdata, bind_source=None, bind_property=None, bind_flags=None, translatable="false", comments=None, context=None):
|
||||
name = name.replace("_", "-")
|
||||
|
@ -288,120 +257,25 @@ def decompile_property(ctx, gir, name, cdata, bind_source=None, bind_property=No
|
|||
if "bidirectional" in bind_flags:
|
||||
flags += " bidirectional"
|
||||
ctx.print(f"{name}: bind {bind_source}.{bind_property}{flags};")
|
||||
elif _truthy(translatable):
|
||||
elif truthy(translatable):
|
||||
if context is not None:
|
||||
ctx.print(f"{name}: C_(\"{_escape_quote(context)}\", \"{_escape_quote(cdata)}\");")
|
||||
ctx.print(f"{name}: C_(\"{escape_quote(context)}\", \"{escape_quote(cdata)}\");")
|
||||
else:
|
||||
ctx.print(f"{name}: _(\"{_escape_quote(cdata)}\");")
|
||||
ctx.print(f"{name}: _(\"{escape_quote(cdata)}\");")
|
||||
elif gir is None or gir.properties.get(name) is None:
|
||||
ctx.print(f"{name}: \"{_escape_quote(cdata)}\";")
|
||||
ctx.print(f"{name}: \"{escape_quote(cdata)}\";")
|
||||
else:
|
||||
ctx.print_attribute(name, cdata, gir.properties.get(name).type)
|
||||
return gir
|
||||
|
||||
|
||||
@decompiler("signal")
|
||||
def decompile_signal(ctx, gir, name, handler, swapped="false", object=None):
|
||||
object_name = object or ""
|
||||
name = name.replace("_", "-")
|
||||
if _truthy(swapped):
|
||||
ctx.print(f"{name} => {handler}({object_name}) swapped;")
|
||||
else:
|
||||
ctx.print(f"{name} => {handler}({object_name});")
|
||||
return gir
|
||||
|
||||
|
||||
@decompiler("style")
|
||||
def decompile_style(ctx, gir):
|
||||
ctx.print(f"styles [")
|
||||
|
||||
|
||||
@decompiler("class")
|
||||
def decompile_class(ctx, gir, name):
|
||||
ctx.print(f'"{name}",')
|
||||
|
||||
|
||||
@decompiler("layout")
|
||||
def decompile_layout(ctx, gir):
|
||||
ctx.print("layout {")
|
||||
|
||||
|
||||
@decompiler("menu")
|
||||
def decompile_menu(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"menu {id} {{")
|
||||
else:
|
||||
ctx.print("menu {")
|
||||
|
||||
@decompiler("submenu")
|
||||
def decompile_submenu(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"submenu {id} {{")
|
||||
else:
|
||||
ctx.print("submenu {")
|
||||
|
||||
@decompiler("item")
|
||||
def decompile_item(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"item {id} {{")
|
||||
else:
|
||||
ctx.print("item {")
|
||||
|
||||
@decompiler("section")
|
||||
def decompile_section(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"section {id} {{")
|
||||
else:
|
||||
ctx.print("section {")
|
||||
|
||||
@decompiler("attribute", cdata=True)
|
||||
def decompile_attribute(ctx, gir, name, cdata, translatable="false", comments=None, context=None):
|
||||
decompile_property(ctx, gir, name, cdata, translatable=translatable, comments=comments, context=context)
|
||||
|
||||
@decompiler("accessibility")
|
||||
def decompile_accessibility(ctx, gir):
|
||||
ctx.print("accessibility {")
|
||||
|
||||
@decompiler("attributes")
|
||||
def decompile_attributes(ctx, gir):
|
||||
ctx.print("attributes {")
|
||||
|
||||
@decompiler("relation", cdata=True)
|
||||
def decompile_relation(ctx, gir, name, cdata):
|
||||
ctx.print_attribute(name, cdata, gtk_a11y.get_types(ctx.gir).get(name))
|
||||
|
||||
@decompiler("state", cdata=True)
|
||||
def decompile_state(ctx, gir, name, cdata, translatable="false"):
|
||||
if _truthy(translatable):
|
||||
ctx.print(f"{name}: _(\"{_escape_quote(cdata)}\");")
|
||||
else:
|
||||
ctx.print_attribute(name, cdata, gtk_a11y.get_types(ctx.gir).get(name))
|
||||
|
||||
|
||||
@decompiler("mime-types")
|
||||
def decompile_mime_types(ctx, gir):
|
||||
ctx.print("mime-types [")
|
||||
|
||||
@decompiler("mime-type", cdata=True)
|
||||
def decompile_mime_type(ctx, gir, cdata):
|
||||
ctx.print(f'"{cdata}",')
|
||||
|
||||
@decompiler("patterns")
|
||||
def decompile_patterns(ctx, gir):
|
||||
ctx.print("patterns [")
|
||||
|
||||
@decompiler("pattern", cdata=True)
|
||||
def decompile_pattern(ctx, gir, cdata):
|
||||
ctx.print(f'"{cdata}",')
|
||||
|
||||
@decompiler("suffixes")
|
||||
def decompile_suffixes(ctx, gir):
|
||||
ctx.print("suffixes [")
|
||||
|
||||
@decompiler("suffix", cdata=True)
|
||||
def decompile_suffix(ctx, gir, cdata):
|
||||
ctx.print(f'"{cdata}",')
|
||||
|
||||
|
||||
@dataclass
|
||||
class UnsupportedError(Exception):
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
from .. import gir
|
||||
from ..ast_utils import AstNode, validate, docs
|
||||
from ..completions_utils import *
|
||||
from .. import decompiler as decompile
|
||||
from ..decompiler import DecompileCtx, decompiler
|
||||
from ..gir import StringType, BoolType, IntType, FloatType, GirType
|
||||
from ..lsp_utils import Completion, CompletionItemKind, SemanticToken, SemanticTokenType
|
||||
from ..parse_tree import *
|
||||
|
|
|
@ -95,3 +95,14 @@ def validate_parent_type(node, ns: str, name: str, err_msg: str):
|
|||
container_type = node.parent_by_type(Object).gir_class
|
||||
if container_type and not container_type.assignable_to(parent):
|
||||
raise CompileError(f"{container_type.full_name} is not a {parent.full_name}, so it doesn't have {err_msg}")
|
||||
|
||||
|
||||
@decompiler("object")
|
||||
def decompile_object(ctx, gir, klass, id=None):
|
||||
gir_class = ctx.type_by_cname(klass)
|
||||
klass_name = decompile.full_name(gir_class) if gir_class is not None else "." + klass
|
||||
if id is None:
|
||||
ctx.print(f"{klass_name} {{")
|
||||
else:
|
||||
ctx.print(f"{klass_name} {id} {{")
|
||||
return gir_class
|
||||
|
|
|
@ -100,3 +100,14 @@ class Signal(AstNode):
|
|||
swapped="true" if self.tokens["swapped"] else None,
|
||||
object=self.tokens["object"]
|
||||
)
|
||||
|
||||
|
||||
@decompiler("signal")
|
||||
def decompile_signal(ctx, gir, name, handler, swapped="false", object=None):
|
||||
object_name = object or ""
|
||||
name = name.replace("_", "-")
|
||||
if decompile.truthy(swapped):
|
||||
ctx.print(f"{name} => {handler}({object_name}) swapped;")
|
||||
else:
|
||||
ctx.print(f"{name} => {handler}({object_name});")
|
||||
return gir
|
||||
|
|
|
@ -177,3 +177,19 @@ def a11y_completer(ast_node, match_variables):
|
|||
def a11y_name_completer(ast_node, match_variables):
|
||||
for name, type in get_types(ast_node.root.gir).items():
|
||||
yield Completion(name, CompletionItemKind.Property, docs=_get_docs(ast_node.root.gir, type))
|
||||
|
||||
|
||||
@decompiler("relation", cdata=True)
|
||||
def decompile_relation(ctx, gir, name, cdata):
|
||||
ctx.print_attribute(name, cdata, get_types(ctx.gir).get(name))
|
||||
|
||||
@decompiler("state", cdata=True)
|
||||
def decompile_state(ctx, gir, name, cdata, translatable="false"):
|
||||
if decompile.truthy(translatable):
|
||||
ctx.print(f"{name}: _(\"{_escape_quote(cdata)}\");")
|
||||
else:
|
||||
ctx.print_attribute(name, cdata, get_types(ctx.gir).get(name))
|
||||
|
||||
@decompiler("accessibility")
|
||||
def decompile_accessibility(ctx, gir):
|
||||
ctx.print("accessibility {")
|
||||
|
|
|
@ -78,3 +78,27 @@ def file_filter_completer(ast_node, match_variables):
|
|||
yield Completion("patterns", CompletionItemKind.Snippet, snippet="patterns [\"$0\"]")
|
||||
yield Completion("suffixes", CompletionItemKind.Snippet, snippet="suffixes [\"$0\"]")
|
||||
|
||||
|
||||
@decompiler("mime-types")
|
||||
def decompile_mime_types(ctx, gir):
|
||||
ctx.print("mime-types [")
|
||||
|
||||
@decompiler("mime-type", cdata=True)
|
||||
def decompile_mime_type(ctx, gir, cdata):
|
||||
ctx.print(f'"{cdata}",')
|
||||
|
||||
@decompiler("patterns")
|
||||
def decompile_patterns(ctx, gir):
|
||||
ctx.print("patterns [")
|
||||
|
||||
@decompiler("pattern", cdata=True)
|
||||
def decompile_pattern(ctx, gir, cdata):
|
||||
ctx.print(f'"{cdata}",')
|
||||
|
||||
@decompiler("suffixes")
|
||||
def decompile_suffixes(ctx, gir):
|
||||
ctx.print("suffixes [")
|
||||
|
||||
@decompiler("suffix", cdata=True)
|
||||
def decompile_suffix(ctx, gir, cdata):
|
||||
ctx.print(f'"{cdata}",')
|
||||
|
|
|
@ -71,3 +71,8 @@ def layout_completer(ast_node, match_variables):
|
|||
"layout", CompletionItemKind.Snippet,
|
||||
snippet="layout {\n $0\n}"
|
||||
)
|
||||
|
||||
|
||||
@decompiler("layout")
|
||||
def decompile_layout(ctx, gir):
|
||||
ctx.print("layout {")
|
||||
|
|
|
@ -185,3 +185,31 @@ def menu_content_completer(ast_node, match_variables):
|
|||
snippet='icon: "$0";'
|
||||
)
|
||||
|
||||
|
||||
@decompiler("menu")
|
||||
def decompile_menu(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"menu {id} {{")
|
||||
else:
|
||||
ctx.print("menu {")
|
||||
|
||||
@decompiler("submenu")
|
||||
def decompile_submenu(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"submenu {id} {{")
|
||||
else:
|
||||
ctx.print("submenu {")
|
||||
|
||||
@decompiler("item")
|
||||
def decompile_item(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"item {id} {{")
|
||||
else:
|
||||
ctx.print("item {")
|
||||
|
||||
@decompiler("section")
|
||||
def decompile_section(ctx, gir, id=None):
|
||||
if id:
|
||||
ctx.print(f"section {id} {{")
|
||||
else:
|
||||
ctx.print("section {")
|
||||
|
|
|
@ -56,3 +56,11 @@ class Styles(AstNode):
|
|||
def style_completer(ast_node, match_variables):
|
||||
yield Completion("styles", CompletionItemKind.Keyword, snippet="styles [\"$0\"]")
|
||||
|
||||
|
||||
@decompiler("style")
|
||||
def decompile_style(ctx, gir):
|
||||
ctx.print(f"styles [")
|
||||
|
||||
@decompiler("class")
|
||||
def decompile_style_class(ctx, gir, name):
|
||||
ctx.print(f'"{name}",')
|
||||
|
|
|
@ -43,3 +43,12 @@ class Child(AstNode):
|
|||
for child in self.children:
|
||||
child.emit_xml(xml)
|
||||
xml.end_tag()
|
||||
|
||||
|
||||
@decompiler("child")
|
||||
def decompile_child(ctx, gir, type=None, internal_child=None):
|
||||
if type is not None:
|
||||
ctx.print(f"[{type}]")
|
||||
elif internal_child is not None:
|
||||
ctx.print(f"[internal-child {internal_child}]")
|
||||
return gir
|
||||
|
|
|
@ -44,3 +44,13 @@ class Template(Object):
|
|||
for child in self.children:
|
||||
child.emit_xml(xml)
|
||||
xml.end_tag()
|
||||
|
||||
|
||||
@decompiler("template")
|
||||
def decompile_template(ctx: DecompileCtx, gir, klass, parent="Widget"):
|
||||
gir_class = ctx.type_by_cname(parent)
|
||||
if gir_class is None:
|
||||
ctx.print(f"template {klass} : .{parent} {{")
|
||||
else:
|
||||
ctx.print(f"template {klass} : {decompile.full_name(gir_class)} {{")
|
||||
return gir_class
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue