diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2ac83f0..1ec071e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,9 @@ -include: - - project: "GNOME/citemplates" - file: "templates/default-rules.yml" - - component: "gitlab.gnome.org/GNOME/citemplates/release-service@master" - inputs: - dist-job-name: "build" +stages: +- build +- pages build: - image: registry.gitlab.gnome.org/gnome/blueprint-compiler + image: registry.gitlab.gnome.org/jwestman/blueprint-compiler stage: build script: - black --check --diff ./ tests @@ -22,24 +19,21 @@ build: - ninja -C _build docs/en - git clone https://gitlab.gnome.org/jwestman/blueprint-regression-tests.git - cd blueprint-regression-tests - - git checkout 57e988aa0f7c1e16fc806a6751df5abffe4bf8a5 + - git checkout 5f9e155c1333e84e6f683cdb26b02a5925fd8db3 - ./test.sh - cd .. - - meson dist -C _build --include-subprojects --no-tests - - cp -r "_build/meson-dist/" "${CI_PROJECT_DIR}/public-dist/" coverage: '/TOTAL.*\s([.\d]+)%/' artifacts: paths: - _build - htmlcov - - public-dist reports: coverage_report: coverage_format: cobertura path: coverage.xml fuzz: - image: registry.gitlab.gnome.org/gnome/blueprint-compiler + image: registry.gitlab.gnome.org/jwestman/blueprint-compiler stage: build script: - meson _build @@ -52,7 +46,7 @@ fuzz: - crashes pages: - stage: deploy + stage: pages dependencies: - build script: diff --git a/MAINTENANCE.md b/MAINTENANCE.md index 3ab4fa2..220c117 100644 --- a/MAINTENANCE.md +++ b/MAINTENANCE.md @@ -8,7 +8,7 @@ in the NEWS file. 3. Make a new commit with just these two changes. Use `Release v{version}` as the commit message. Tag the commit as `v{version}` and push the tag. 4. Create a "Post-release version bump" commit. 5. Go to the Releases page in GitLab and create a new release from the tag. -6. Announce the release through relevant channels (Mastodon, TWIG, etc.) +6. Announce the release through relevant channels (Twitter, TWIG, etc.) ## Related projects diff --git a/NEWS.md b/NEWS.md index 715aab4..a12dab0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,22 +1,3 @@ -# v0.18.0 - -## Added -- GtkBuilder now allows menus to be specified inline as a property value. Blueprint now supports this as well. - -## Fixed -- Made reference_docs.json build reproducible (Sertonix) -- Correctly emit XML for nested templates (Tom Greig) -- Fix crash in language server while typing an AdwBreakpointSetter rule -- Update URLs after move to GNOME namespace on GitLab -- Fix crash when decompiling a lookup tag with no type attribute -- Fix incorrect result when decompiling a signal that has the template as its object -- Fix an incorrect "Duplicate object ID" error when an Adw.AlertDialog response had the same ID as an object - -## Documentation -- Updated syntax in the example on the Overview page (Chris Mayo) -- Added examples of Gtk.Scale marks (Matthijs Velsink) -- Corrected errors in the index on the Extensions page (Matthijs Velsink) - # v0.16.0 ## Added diff --git a/README.md b/README.md index f01ecf9..503d7a3 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,10 @@ Visual Studio Code - [Blueprint Language Plugin by bodil](https://github.com/bodil/vscode-blueprint) +## Donate + +You can support my work on GitHub Sponsors! + ## Getting in Touch Matrix room: [#blueprint-language:matrix.org](https://matrix.to/#/#blueprint-language:matrix.org) diff --git a/blueprint-compiler.doap b/blueprint-compiler.doap deleted file mode 100644 index f3e4000..0000000 --- a/blueprint-compiler.doap +++ /dev/null @@ -1,27 +0,0 @@ - - - Blueprint - A modern language for creating GTK interfaces - Blueprint is a language and associated tooling for building user interfaces for GTK. - - Python - - - - - - - - James Westman - - jwestman - - - diff --git a/blueprintcompiler/decompiler.py b/blueprintcompiler/decompiler.py index 850b6d8..de6c06f 100644 --- a/blueprintcompiler/decompiler.py +++ b/blueprintcompiler/decompiler.py @@ -255,11 +255,7 @@ def decompile_element( ctx._node_stack.append(xml) ctx.start_block() - - try: - gir = decompiler(*args, **kwargs) - except TypeError as e: - raise UnsupportedError(tag=xml.tag) + gir = decompiler(*args, **kwargs) if not decompiler._skip_children: for child in xml.children: @@ -270,6 +266,8 @@ def decompile_element( except UnsupportedError as e: raise e + except TypeError as e: + raise UnsupportedError(tag=xml.tag) def decompile(data: str) -> str: diff --git a/blueprintcompiler/errors.py b/blueprintcompiler/errors.py index df1c2e1..1e7297c 100644 --- a/blueprintcompiler/errors.py +++ b/blueprintcompiler/errors.py @@ -219,7 +219,7 @@ def report_bug(): # pragma: no cover f"""{Colors.BOLD}{Colors.RED}***** COMPILER BUG ***** The blueprint-compiler program has crashed. Please report the above stacktrace, along with the input file(s) if possible, on GitLab: -{Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues/new?issue +{Colors.BOLD}{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue {Colors.CLEAR}""" ) diff --git a/blueprintcompiler/interactive_port.py b/blueprintcompiler/interactive_port.py index 12dd485..0c37885 100644 --- a/blueprintcompiler/interactive_port.py +++ b/blueprintcompiler/interactive_port.py @@ -71,7 +71,7 @@ def decompile_file(in_file, out_file) -> T.Union[str, CouldNotPort]: print( f"""{Colors.FAINT}Either the original XML file had an error, or there is a bug in the porting tool. If you think it's a bug (which is likely), please file an issue on GitLab: -{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/GNOME/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n""" +{Colors.BLUE}{Colors.UNDERLINE}https://gitlab.gnome.org/jwestman/blueprint-compiler/-/issues/new?issue{Colors.CLEAR}\n""" ) return CouldNotPort("does not compile") @@ -136,7 +136,7 @@ def step1(): wrap.write( f"""[wrap-git] directory = blueprint-compiler -url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git +url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git revision = {VERSION} depth = 1 diff --git a/blueprintcompiler/language/adw_breakpoint.py b/blueprintcompiler/language/adw_breakpoint.py index 3d2c10d..4ad5b24 100644 --- a/blueprintcompiler/language/adw_breakpoint.py +++ b/blueprintcompiler/language/adw_breakpoint.py @@ -81,8 +81,8 @@ class AdwBreakpointSetter(AstNode): return self.tokens["property"] @property - def value(self) -> T.Optional[Value]: - return self.children[Value][0] if len(self.children[Value]) > 0 else None + def value(self) -> Value: + return self.children[Value][0] @property def gir_class(self) -> T.Optional[GirType]: @@ -106,10 +106,7 @@ class AdwBreakpointSetter(AstNode): return None @property - def document_symbol(self) -> T.Optional[DocumentSymbol]: - if self.value is None: - return None - + def document_symbol(self) -> DocumentSymbol: return DocumentSymbol( f"{self.object_id}.{self.property_name}", SymbolKind.Property, diff --git a/blueprintcompiler/language/contexts.py b/blueprintcompiler/language/contexts.py index 9376211..6e26048 100644 --- a/blueprintcompiler/language/contexts.py +++ b/blueprintcompiler/language/contexts.py @@ -60,21 +60,19 @@ class ScopeCtx: passed = {} for obj in self._iter_recursive(self.node): - from .gtk_menu import Menu - - if not (isinstance(obj, Object) or isinstance(obj, Menu)) or obj.id is None: + if obj.tokens["id"] is None: continue - if obj.id in passed: + if obj.tokens["id"] in passed: token = obj.group.tokens["id"] if not isinstance(obj, Template) and not isinstance( obj, ExtListItemFactory ): raise CompileError( - f"Duplicate object ID '{obj.id}'", + f"Duplicate object ID '{obj.tokens['id']}'", token.range, ) - passed[obj.id] = obj + passed[obj.tokens["id"]] = obj def _iter_recursive(self, node: AstNode): yield node diff --git a/blueprintcompiler/language/expression.py b/blueprintcompiler/language/expression.py index de6fbf1..e0b4246 100644 --- a/blueprintcompiler/language/expression.py +++ b/blueprintcompiler/language/expression.py @@ -302,18 +302,12 @@ expr.children = [ @decompiler("lookup", skip_children=True, cdata=True) def decompile_lookup( - ctx: DecompileCtx, - gir: gir.GirContext, - cdata: str, - name: str, - type: T.Optional[str] = None, + ctx: DecompileCtx, gir: gir.GirContext, cdata: str, name: str, type: str ): if ctx.parent_node is not None and ctx.parent_node.tag == "property": ctx.print("expr ") - if type is None: - type = "" - elif t := ctx.type_by_cname(type): + if t := ctx.type_by_cname(type): type = decompile.full_name(t) else: type = "$" + type @@ -333,7 +327,7 @@ def decompile_lookup( if constant == ctx.template_class: ctx.print("template." + name) elif constant == "": - ctx.print(f"item as <{type}>.{name}") + ctx.print("item as <" + type + ">." + name) else: ctx.print(constant + "." + name) return diff --git a/blueprintcompiler/language/gobject_object.py b/blueprintcompiler/language/gobject_object.py index df87a58..1def15b 100644 --- a/blueprintcompiler/language/gobject_object.py +++ b/blueprintcompiler/language/gobject_object.py @@ -71,15 +71,12 @@ class Object(AstNode): @property def signature(self) -> str: - if t := self.class_name.gir_type: - result = t.full_name - else: - result = self.class_name.as_string - if self.id: - result += " " + self.id - - return result + return f"{self.class_name.gir_type.full_name} {self.id}" + elif t := self.class_name.gir_type: + return f"{t.full_name}" + else: + return f"{self.class_name.as_string}" @property def document_symbol(self) -> T.Optional[DocumentSymbol]: diff --git a/blueprintcompiler/language/gobject_property.py b/blueprintcompiler/language/gobject_property.py index c782d2e..50a7512 100644 --- a/blueprintcompiler/language/gobject_property.py +++ b/blueprintcompiler/language/gobject_property.py @@ -21,15 +21,12 @@ from .binding import Binding from .common import * from .contexts import ValueTypeCtx -from .gtk_menu import menu from .values import ArrayValue, ExprValue, ObjectValue, Value class Property(AstNode): grammar = Statement( - UseIdent("name"), - ":", - AnyOf(Binding, ExprValue, menu, ObjectValue, Value, ArrayValue), + UseIdent("name"), ":", AnyOf(Binding, ExprValue, ObjectValue, Value, ArrayValue) ) @property diff --git a/blueprintcompiler/language/gobject_signal.py b/blueprintcompiler/language/gobject_signal.py index 3b4235f..9c27b97 100644 --- a/blueprintcompiler/language/gobject_signal.py +++ b/blueprintcompiler/language/gobject_signal.py @@ -225,14 +225,8 @@ class Signal(AstNode): @decompiler("signal") -def decompile_signal( - ctx: DecompileCtx, gir, name, handler, swapped=None, after="false", object=None -): +def decompile_signal(ctx, gir, name, handler, swapped=None, after="false", object=None): object_name = object or "" - - if object_name == ctx.template_class: - object_name = "template" - name = name.replace("_", "-") line = f"{name} => ${handler}({object_name})" diff --git a/blueprintcompiler/language/gtk_a11y.py b/blueprintcompiler/language/gtk_a11y.py index 92a975c..0cc3cb3 100644 --- a/blueprintcompiler/language/gtk_a11y.py +++ b/blueprintcompiler/language/gtk_a11y.py @@ -31,7 +31,6 @@ def get_property_types(gir): "autocomplete": gir.get_type("AccessibleAutocomplete", "Gtk"), "description": StringType(), "has-popup": BoolType(), - "help-text": StringType(), "key-shortcuts": StringType(), "label": StringType(), "level": IntType(), @@ -87,7 +86,6 @@ def get_state_types(gir): "invalid": gir.get_type("AccessibleInvalidState", "Gtk"), "pressed": gir.get_type("AccessibleTristate", "Gtk"), "selected": BoolType(), - "visited": BoolType(), } diff --git a/blueprintcompiler/language/gtk_menu.py b/blueprintcompiler/language/gtk_menu.py index bc38f37..c7ef5f2 100644 --- a/blueprintcompiler/language/gtk_menu.py +++ b/blueprintcompiler/language/gtk_menu.py @@ -60,6 +60,11 @@ class Menu(AstNode): def items(self) -> T.List[T.Union["Menu", "MenuAttribute"]]: return self.children + @validate("menu") + def has_id(self): + if self.tokens["tag"] == "menu" and self.tokens["id"] is None: + raise CompileError("Menu requires an ID") + @validate("id") def object_id_not_reserved(self): if self.id in RESERVED_IDS: diff --git a/blueprintcompiler/language/values.py b/blueprintcompiler/language/values.py index 7fa6bfa..cb80975 100644 --- a/blueprintcompiler/language/values.py +++ b/blueprintcompiler/language/values.py @@ -225,12 +225,12 @@ class Flag(AstNode): return self.tokens["value"] @property - def value(self) -> T.Optional[str]: + def value(self) -> T.Optional[int]: type = self.context[ValueTypeCtx].value_type if not isinstance(type, Enumeration): return None elif member := type.members.get(self.name): - return member.nick + return member.value else: return None @@ -338,14 +338,7 @@ class IdentLiteral(AstNode): raise CompileError( '"item" can only be used in an expression literal' ) - elif self.ident in ["true", "false"]: - if expected_type is not None and not isinstance( - expected_type, gir.BoolType - ): - raise CompileError( - f"Cannot assign boolean to {expected_type.full_name}" - ) - else: + elif self.ident not in ["true", "false"]: raise CompileError( f"Could not find object with ID {self.ident}", did_you_mean=( diff --git a/blueprintcompiler/main.py b/blueprintcompiler/main.py index 8c47d49..1c3a1c6 100644 --- a/blueprintcompiler/main.py +++ b/blueprintcompiler/main.py @@ -170,18 +170,6 @@ class BlueprintApp: add_typelib_search_path(typelib_path) for file in opts.inputs: - path = os.path.join( - opts.output_dir, - os.path.relpath(os.path.splitext(file.name)[0] + ".ui", opts.input_dir), - ) - - if os.path.isfile(path): - in_time = os.path.getmtime(file.name) - out_time = os.path.getmtime(path) - - if out_time >= in_time: - continue - data = file.read() file_abs = os.path.abspath(file.name) input_dir_abs = os.path.abspath(opts.input_dir) @@ -198,6 +186,12 @@ class BlueprintApp: for warning in warnings: warning.pretty_print(file.name, data, stream=sys.stderr) + path = os.path.join( + opts.output_dir, + os.path.relpath( + os.path.splitext(file.name)[0] + ".ui", opts.input_dir + ), + ) os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, "w") as file: file.write(xml) diff --git a/blueprintcompiler/outputs/xml/__init__.py b/blueprintcompiler/outputs/xml/__init__.py index 32291ee..5c03761 100644 --- a/blueprintcompiler/outputs/xml/__init__.py +++ b/blueprintcompiler/outputs/xml/__init__.py @@ -139,11 +139,6 @@ class XmlOutput(OutputFormat): self._emit_expression(value.expression, xml) xml.end_tag() - elif isinstance(value, Menu): - xml.start_tag("property", **props) - self._emit_menu(value, xml) - xml.end_tag() - elif isinstance(value, ObjectValue): xml.start_tag("property", **props) self._emit_object(value.object, xml) @@ -313,9 +308,6 @@ class XmlOutput(OutputFormat): elif isinstance(extension, AdwBreakpointSetters): for setter in extension.setters: - if setter.value is None: - continue - attrs = {} if isinstance(setter.value.child, Translated): diff --git a/blueprintcompiler/outputs/xml/xml_emitter.py b/blueprintcompiler/outputs/xml/xml_emitter.py index d34eff4..ea91e03 100644 --- a/blueprintcompiler/outputs/xml/xml_emitter.py +++ b/blueprintcompiler/outputs/xml/xml_emitter.py @@ -73,7 +73,6 @@ class XmlEmitter: self._needs_newline = False def put_cdata(self, text: str): - text = text.replace("]]>", "]]]]>") self.result += f"" self._needs_newline = False diff --git a/blueprintcompiler/parse_tree.py b/blueprintcompiler/parse_tree.py index e590539..ae062fb 100644 --- a/blueprintcompiler/parse_tree.py +++ b/blueprintcompiler/parse_tree.py @@ -17,7 +17,7 @@ # # SPDX-License-Identifier: LGPL-3.0-or-later -"""Utilities for parsing an AST from a token stream.""" +""" Utilities for parsing an AST from a token stream. """ import typing as T from enum import Enum diff --git a/docs/collect-sections.py b/docs/collect-sections.py index a2dd004..e6227e7 100755 --- a/docs/collect-sections.py +++ b/docs/collect-sections.py @@ -9,7 +9,7 @@ from pathlib import Path __all__ = ["get_docs_section"] -DOCS_ROOT = "https://gnome.pages.gitlab.gnome.org/blueprint-compiler" +DOCS_ROOT = "https://jwestman.pages.gitlab.gnome.org/blueprint-compiler" sections: dict[str, "Section"] = {} @@ -132,8 +132,5 @@ if __name__ == "__main__": # print the sections to a json file with open(outfile, "w") as f: json.dump( - {name: section.to_json() for name, section in sections.items()}, - f, - indent=2, - sort_keys=True, + {name: section.to_json() for name, section in sections.items()}, f, indent=2 ) diff --git a/docs/flatpak.rst b/docs/flatpak.rst index b2f42a4..86112cf 100644 --- a/docs/flatpak.rst +++ b/docs/flatpak.rst @@ -16,8 +16,8 @@ a module in your flatpak manifest: "sources": [ { "type": "git", - "url": "https://gitlab.gnome.org/GNOME/blueprint-compiler", - "tag": "v0.18.0" + "url": "https://gitlab.gnome.org/jwestman/blueprint-compiler", + "tag": "v0.16.0" } ] } diff --git a/docs/index.rst b/docs/index.rst index 6cd130f..34b942c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,7 +26,7 @@ Blueprint is a markup language and compiler for GTK 4 user interfaces. using Gtk 4.0; - template $MyAppWindow: ApplicationWindow { + template MyAppWindow : ApplicationWindow { default-width: 600; default-height: 300; title: _("Hello, Blueprint!"); @@ -35,7 +35,7 @@ Blueprint is a markup language and compiler for GTK 4 user interfaces. HeaderBar {} Label { - label: bind template.main_text; + label: bind MyAppWindow.main_text; } } @@ -59,7 +59,7 @@ Features Links ----- -- `Source code `_ +- `Source code `_ - `Workbench `_ lets you try, preview and export Blueprint - `GNOME Builder `_ provides builtin support - `Vim syntax highlighting plugin by thetek42 `_ diff --git a/docs/reference/extensions.rst b/docs/reference/extensions.rst index 3a9ad36..0961d14 100644 --- a/docs/reference/extensions.rst +++ b/docs/reference/extensions.rst @@ -10,21 +10,20 @@ Properties are the main way to set values on objects, but they are limited by th Extensions are a feature of ``Gtk.Buildable``--see `Gtk.Buildable.custom_tag_start() `_ for internal details. - Because they aren't part of the type system, they aren't present in typelib files like properties and signals are. Therefore, if a library adds a new extension, syntax for it must be added to Blueprint manually. If there's a commonly used extension that isn't supported by Blueprint, please `file an issue `_. + Because they aren't part of the type system, they aren't present in typelib files like properties and signals are. Therefore, if a library adds a new extension, syntax for it must be added to Blueprint manually. If there's a commonly used extension that isn't supported by Blueprint, please `file an issue `_. .. rst-class:: grammar-block Extension = :ref:`ExtAccessibility` | :ref:`ExtAdwAlertDialog` - | :ref:`ExtAdwBreakpoint` | :ref:`ExtAdwMessageDialog` + | :ref:`ExtAdwBreakpoint` | :ref:`ExtComboBoxItems` | :ref:`ExtFileFilterMimeTypes` | :ref:`ExtFileFilterPatterns` | :ref:`ExtFileFilterSuffixes` | :ref:`ExtLayout` | :ref:`ExtListItemFactory` - | :ref:`ExtScaleMarks` | :ref:`ExtSizeGroupWidgets` | :ref:`ExtStringListStrings` | :ref:`ExtStyles` @@ -48,6 +47,25 @@ The ``accessibility`` block defines values relevant to accessibility software. T Relations which allow for a list of values, for example `labelled-by`, must be given as a single relation with a list of values instead of duplicating the relation like done in Gtk.Builder. +.. _Syntax ExtAdwBreakpoint: + +Adw.Breakpoint +-------------- + +.. rst-class:: grammar-block + + ExtAdwBreakpointCondition = 'condition' '(' `> ')' + ExtAdwBreakpoint = 'setters' '{' ExtAdwBreakpointSetter* '}' + ExtAdwBreakpointSetter = `> '.' `> ':' :ref:`Value ` ';' + +Valid in `Adw.Breakpoint `_. + +Defines the condition for a breakpoint and the properties that will be set at that breakpoint. See the documentation for `Adw.Breakpoint `_. + +.. note:: + + The `Adw.Breakpoint:condition `_ property has type `Adw.BreakpointCondition `_, which GtkBuilder doesn't know how to parse from a string. Therefore, the ``condition`` syntax is used instead. + .. _Syntax ExtAdwAlertDialog: @@ -78,26 +96,6 @@ The ``responses`` block defines the buttons that will be added to the dialog. Th } -.. _Syntax ExtAdwBreakpoint: - -Adw.Breakpoint --------------- - -.. rst-class:: grammar-block - - ExtAdwBreakpointCondition = 'condition' '(' `> ')' - ExtAdwBreakpoint = 'setters' '{' ExtAdwBreakpointSetter* '}' - ExtAdwBreakpointSetter = `> '.' `> ':' :ref:`Value ` ';' - -Valid in `Adw.Breakpoint `_. - -Defines the condition for a breakpoint and the properties that will be set at that breakpoint. See the documentation for `Adw.Breakpoint `_. - -.. note:: - - The `Adw.Breakpoint:condition `_ property has type `Adw.BreakpointCondition `_, which GtkBuilder doesn't know how to parse from a string. Therefore, the ``condition`` syntax is used instead. - - .. _Syntax ExtAdwMessageDialog: Adw.MessageDialog Responses @@ -264,16 +262,6 @@ Valid in `Gtk.Scale `_. The ``marks`` block defines the marks on a scale. A single ``mark`` has up to three arguments: a value, an optional position, and an optional label. The position can be ``left``, ``right``, ``top``, or ``bottom``. The label may be translated. -.. code-block:: blueprint - - Scale { - marks [ - mark (-1, bottom), - mark (0, top, _("Origin")), - mark (2), - ] - } - .. _Syntax ExtSizeGroupWidgets: diff --git a/docs/reference/objects.rst b/docs/reference/objects.rst index d759abe..6f76da6 100644 --- a/docs/reference/objects.rst +++ b/docs/reference/objects.rst @@ -58,7 +58,7 @@ Properties .. rst-class:: grammar-block - Property = `> ':' ( :ref:`Binding` | :ref:`ExprValue` | :ref:`Menu` | :ref:`ObjectValue` | :ref:`Value` ) ';' + Property = `> ':' ( :ref:`Binding` | :ref:`ExprValue` | :ref:`ObjectValue` | :ref:`Value` ) ';' Properties specify the details of each object, like a label's text, an image's icon name, or the margins on a container. diff --git a/docs/setup.rst b/docs/setup.rst index 914c753..839f8f6 100644 --- a/docs/setup.rst +++ b/docs/setup.rst @@ -8,7 +8,7 @@ Setting up Blueprint on a new or existing project Using the porting tool ~~~~~~~~~~~~~~~~~~~~~~ -Clone `blueprint-compiler `_ +Clone `blueprint-compiler `_ from source. You can install it using ``meson _build`` and ``ninja -C _build install``, or you can leave it uninstalled. @@ -29,7 +29,7 @@ blueprint-compiler works as a meson subproject. [wrap-git] directory = blueprint-compiler - url = https://gitlab.gnome.org/GNOME/blueprint-compiler.git + url = https://gitlab.gnome.org/jwestman/blueprint-compiler.git revision = main depth = 1 diff --git a/meson.build b/meson.build index 405ed10..f298d15 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('blueprint-compiler', - version: '0.18.0', + version: '0.16.0', ) prefix = get_option('prefix') diff --git a/tests/fuzz.py b/tests/fuzz.py index 6f1fb06..81a9058 100644 --- a/tests/fuzz.py +++ b/tests/fuzz.py @@ -7,28 +7,25 @@ from blueprintcompiler.outputs.xml import XmlOutput sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) -from blueprintcompiler import gir, parser, tokenizer +from blueprintcompiler import decompiler, gir, parser, tokenizer, utils from blueprintcompiler.completions import complete from blueprintcompiler.errors import ( + CompileError, CompilerBugError, + MultipleErrors, PrintableError, ) -from blueprintcompiler.lsp import LanguageServer - -fuzz_level = int(os.getenv("FUZZ_LEVEL") or "0") +from blueprintcompiler.tokenizer import Token, TokenType, tokenize @PythonFuzz -def fuzz(buf: bytes): +def fuzz(buf): try: blueprint = buf.decode("ascii") tokens = tokenizer.tokenize(blueprint) ast, errors, warnings = parser.parse(tokens) - if fuzz_level >= 1: - assert_ast_doesnt_crash(blueprint, tokens, ast) - xml = XmlOutput() if errors is None and ast is not None: xml.emit(ast) @@ -40,17 +37,6 @@ def fuzz(buf: bytes): pass -def assert_ast_doesnt_crash(text, tokens, ast): - lsp = LanguageServer() - for i in range(len(text) + 1): - ast.get_docs(i) - for i in range(len(text) + 1): - list(complete(lsp, ast, tokens, i)) - for i in range(len(text) + 1): - ast.get_reference(i) - ast.get_document_symbols() - - if __name__ == "__main__": # Make sure Gtk 4.0 is accessible, otherwise every test will fail on that # and nothing interesting will be tested diff --git a/tests/sample_errors/convert_bool_to_obj.blp b/tests/sample_errors/convert_bool_to_obj.blp deleted file mode 100644 index 5f856c0..0000000 --- a/tests/sample_errors/convert_bool_to_obj.blp +++ /dev/null @@ -1,5 +0,0 @@ -using Gtk 4.0; - -Button { - child: false; -} diff --git a/tests/sample_errors/convert_bool_to_obj.err b/tests/sample_errors/convert_bool_to_obj.err deleted file mode 100644 index 389f69c..0000000 --- a/tests/sample_errors/convert_bool_to_obj.err +++ /dev/null @@ -1 +0,0 @@ -4,10,5,Cannot assign boolean to Gtk.Widget \ No newline at end of file diff --git a/tests/samples/inline_menu.blp b/tests/sample_errors/inline_menu.blp similarity index 100% rename from tests/samples/inline_menu.blp rename to tests/sample_errors/inline_menu.blp diff --git a/tests/sample_errors/inline_menu.err b/tests/sample_errors/inline_menu.err new file mode 100644 index 0000000..3115750 --- /dev/null +++ b/tests/sample_errors/inline_menu.err @@ -0,0 +1 @@ +4,15,4,Namespace Gtk does not contain a type called menu \ No newline at end of file diff --git a/tests/samples/menu_no_id.blp b/tests/sample_errors/menu_no_id.blp similarity index 100% rename from tests/samples/menu_no_id.blp rename to tests/sample_errors/menu_no_id.blp diff --git a/tests/sample_errors/menu_no_id.err b/tests/sample_errors/menu_no_id.err new file mode 100644 index 0000000..e97f033 --- /dev/null +++ b/tests/sample_errors/menu_no_id.err @@ -0,0 +1 @@ +3,1,4,Menu requires an ID \ No newline at end of file diff --git a/tests/samples/flags.ui b/tests/samples/flags.ui index 44eb2c4..2f0a26e 100644 --- a/tests/samples/flags.ui +++ b/tests/samples/flags.ui @@ -7,7 +7,7 @@ corresponding .blp file and regenerate this file with blueprint-compiler. - is-service|handles-open + 1|4 1 diff --git a/tests/samples/inline_menu.ui b/tests/samples/inline_menu.ui deleted file mode 100644 index 2910b14..0000000 --- a/tests/samples/inline_menu.ui +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/tests/samples/issue_187.ui b/tests/samples/issue_187.ui deleted file mode 100644 index 941a00f..0000000 --- a/tests/samples/issue_187.ui +++ /dev/null @@ -1,15 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tests/samples/issue_187_dec.blp b/tests/samples/issue_187_dec.blp deleted file mode 100644 index 30b997c..0000000 --- a/tests/samples/issue_187_dec.blp +++ /dev/null @@ -1,7 +0,0 @@ -using Gtk 4.0; - -template ListItem { - child: Label { - label: bind template.item as <$RecentObject>.filename; - }; -} diff --git a/tests/samples/issue_195.blp b/tests/samples/issue_195.blp deleted file mode 100644 index 50b5b95..0000000 --- a/tests/samples/issue_195.blp +++ /dev/null @@ -1,11 +0,0 @@ -using Gtk 4.0; -using Adw 1; - -Adw.AlertDialog dialog1 { - responses [ - ok: "Ok", - cancel: "Cancel", - ] -} - -Button cancel {} diff --git a/tests/samples/issue_195.ui b/tests/samples/issue_195.ui deleted file mode 100644 index b57a379..0000000 --- a/tests/samples/issue_195.ui +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Ok - Cancel - - - - \ No newline at end of file diff --git a/tests/samples/list_factory_nested.blp b/tests/samples/list_factory_nested.blp deleted file mode 100644 index 86a59b3..0000000 --- a/tests/samples/list_factory_nested.blp +++ /dev/null @@ -1,17 +0,0 @@ -using Gtk 4.0; - -Gtk.ListView { - factory: Gtk.BuilderListItemFactory list_item_factory { - template ListItem { - child: Gtk.ListView { - factory: Gtk.BuilderListItemFactory list_item_factory { - template ListItem { - child: Gtk.Label { - label: bind template.item as <$MyObject>.name; - }; - } - }; - }; - } - }; -} diff --git a/tests/samples/list_factory_nested.ui b/tests/samples/list_factory_nested.ui deleted file mode 100644 index 44cdb2b..0000000 --- a/tests/samples/list_factory_nested.ui +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - -]]> - - - - diff --git a/tests/samples/list_factory_nested_dec.blp b/tests/samples/list_factory_nested_dec.blp deleted file mode 100644 index 755491c..0000000 --- a/tests/samples/list_factory_nested_dec.blp +++ /dev/null @@ -1,18 +0,0 @@ -using Gtk 4.0; - -ListView { - factory: BuilderListItemFactory list_item_factory { - template ListItem { - child: ListView { - factory: BuilderListItemFactory list_item_factory { - template ListItem { - child: Label { - label: bind template.item as <$MyObject>.name; - }; - } - }; - }; - } - }; -} - diff --git a/tests/samples/menu_no_id.ui b/tests/samples/menu_no_id.ui deleted file mode 100644 index 934f6da..0000000 --- a/tests/samples/menu_no_id.ui +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/tests/samples/signal_template_object.blp b/tests/samples/signal_template_object.blp deleted file mode 100644 index 16dd5a0..0000000 --- a/tests/samples/signal_template_object.blp +++ /dev/null @@ -1,7 +0,0 @@ -using Gtk 4.0; - -template $MyTemplate { - Button { - clicked => $my_signal_handler(template); - } -} diff --git a/tests/samples/signal_template_object.ui b/tests/samples/signal_template_object.ui deleted file mode 100644 index c9a680a..0000000 --- a/tests/samples/signal_template_object.ui +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - diff --git a/tests/test_samples.py b/tests/test_samples.py index 0807d65..1f56eb6 100644 --- a/tests/test_samples.py +++ b/tests/test_samples.py @@ -181,7 +181,11 @@ class TestSamples(unittest.TestCase): def test_samples(self): # list the samples directory - samples = [f.stem for f in Path(__file__).parent.glob("samples/*.blp")] + samples = [ + f.stem + for f in Path(__file__).parent.glob("samples/*.blp") + if not f.stem.endswith("_dec") + ] samples.sort() for sample in samples: REQUIRE_ADW_1_4 = ["adw_breakpoint"] @@ -198,7 +202,6 @@ class TestSamples(unittest.TestCase): "parseable", "signal", "signal_not_swapped", - "signal_template_object", "template", "template_binding", "template_binding_extern", @@ -212,7 +215,7 @@ class TestSamples(unittest.TestCase): ] # Decompiler-only tests - SKIP_COMPILE = ["issue_177", "issue_187", "translator_comments"] + SKIP_COMPILE = ["issue_177", "translator_comments"] SKIP_DECOMPILE = [ # Comments are not preserved in either direction @@ -225,7 +228,7 @@ class TestSamples(unittest.TestCase): continue with self.subTest(sample): - if sample not in SKIP_COMPILE and not sample.endswith("_dec"): + if sample not in SKIP_COMPILE: self.assert_sample(sample, skip_run=sample in SKIP_RUN) with self.subTest("decompile/" + sample): diff --git a/tests/test_tokenizer.py b/tests/test_tokenizer.py index ad5f828..2bca595 100644 --- a/tests/test_tokenizer.py +++ b/tests/test_tokenizer.py @@ -25,7 +25,7 @@ from blueprintcompiler.tokenizer import Token, TokenType, tokenize class TestTokenizer(unittest.TestCase): - def assert_tokenize(self, string: str, expect: list[Token]): + def assert_tokenize(self, string: str, expect: [Token]): try: tokens = tokenize(string) self.assertEqual(len(tokens), len(expect))