From: Rico Tzschichholz Date: Sun, 16 Jun 2019 17:28:24 +0000 (+0200) Subject: Add support for sealed classes in bindings X-Git-Tag: 0.47.92~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c16b665cb90c66c5ed8362fa70989bde1eaee272;p=thirdparty%2Fvala.git Add support for sealed classes in bindings The "sealed" keyword was available and parsed for a long time. So simply pick it up information and expose it in the AST. Issue an error when it is used in vala source. See https://gitlab.gnome.org/GNOME/vala/issues/278 --- diff --git a/libvaladoc/api/class.vala b/libvaladoc/api/class.vala index 9c003e8ab..02f4917d1 100644 --- a/libvaladoc/api/class.vala +++ b/libvaladoc/api/class.vala @@ -78,6 +78,7 @@ public class Valadoc.Api.Class : TypeSymbol { this.is_fundamental = data.is_fundamental (); this.is_abstract = data.is_abstract; + this.is_sealed = data.is_sealed; } string? _get_private_cname (Vala.Class element) { @@ -257,6 +258,15 @@ public class Valadoc.Api.Class : TypeSymbol { get; } + /** + * Specifies whether this class is sealed. Sealed classes may not be + * sub-classed. + */ + public bool is_sealed { + private set; + get; + } + /** * Specifies whether this class is fundamental. */ @@ -322,6 +332,9 @@ public class Valadoc.Api.Class : TypeSymbol { if (is_abstract) { signature.append_keyword ("abstract"); } + if (is_sealed) { + signature.append_keyword ("sealed"); + } signature.append_keyword ("class"); signature.append_symbol (this); diff --git a/tests/Makefile.am b/tests/Makefile.am index e73bc0ac3..c10c72b41 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -385,6 +385,9 @@ TESTS = \ objects/property-simple-type-struct-nullable.vala \ objects/property-static.vala \ objects/regex.vala \ + objects/sealed-abstract-class.test \ + objects/sealed-class.test \ + objects/sealed-compact-class.test \ objects/signals.vala \ objects/signals-enum-marshal.vala \ objects/signals-delegate.vala \ diff --git a/tests/objects/sealed-abstract-class.test b/tests/objects/sealed-abstract-class.test new file mode 100644 index 000000000..337820a04 --- /dev/null +++ b/tests/objects/sealed-abstract-class.test @@ -0,0 +1,7 @@ +Invalid Code + +sealed abstract class Foo { +} + +void main () { +} diff --git a/tests/objects/sealed-class.test b/tests/objects/sealed-class.test new file mode 100644 index 000000000..b5ec1f052 --- /dev/null +++ b/tests/objects/sealed-class.test @@ -0,0 +1,10 @@ +Invalid Code + +sealed class Foo { +} + +class Bar : Foo { +} + +void main () { +} diff --git a/tests/objects/sealed-compact-class.test b/tests/objects/sealed-compact-class.test new file mode 100644 index 000000000..006c7fc02 --- /dev/null +++ b/tests/objects/sealed-compact-class.test @@ -0,0 +1,8 @@ +Invalid Code + +[Compact] +sealed class Foo { +} + +void main () { +} diff --git a/vala/valaclass.vala b/vala/valaclass.vala index e9312c415..c4f196c64 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -37,6 +37,12 @@ public class Vala.Class : ObjectTypeSymbol { */ public bool is_abstract { get; set; } + /** + * Specifies whether this class is sealed. Sealed classes may not be + * sub-classed. + */ + public bool is_sealed { get; set; } + /** * Instances of compact classes are fast to create and have a * compact memory layout. Compact classes don't support runtime @@ -582,6 +588,29 @@ public class Vala.Class : ObjectTypeSymbol { add_constructor (c); } + if (base_class != null && base_class.is_sealed) { + error = true; + Report.error (source_reference, "`%s' cannot inherit from sealed class `%s'".printf (get_full_name (), base_class.get_full_name ())); + } + + if (is_sealed) { + if (is_compact) { + error = true; + Report.error (source_reference, "Sealed class `%s' cannot be compact".printf (get_full_name ())); + return false; + } + if (is_abstract) { + error = true; + Report.error (source_reference, "Sealed class `%s' cannot be abstract".printf (get_full_name ())); + return false; + } + if (!external_package) { + error = true; + Report.error (source_reference, "Sealed classes are not fully supported yet"); + return false; + } + } + /* process enums first to avoid order problems in C code */ foreach (Enum en in get_enums ()) { en.check (context); diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala index 2f735e87f..198ee51c2 100644 --- a/vala/valacodewriter.vala +++ b/vala/valacodewriter.vala @@ -246,6 +246,9 @@ public class Vala.CodeWriter : CodeVisitor { if (cl.is_abstract) { write_string ("abstract "); } + if (cl.is_sealed) { + write_string ("sealed "); + } write_string ("class "); write_identifier (cl.name); diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala index 30468323a..6d6f767d8 100644 --- a/vala/valagirparser.vala +++ b/vala/valagirparser.vala @@ -62,6 +62,7 @@ public class Vala.GirParser : CodeVisitor { VFUNC_NAME, VIRTUAL, ABSTRACT, + SEALED, SCOPE, STRUCT, THROWS, @@ -2884,6 +2885,7 @@ public class Vala.GirParser : CodeVisitor { if (current.new_symbol) { cl = new Class (current.name, current.source_reference); cl.is_abstract = metadata.get_bool (ArgumentType.ABSTRACT, reader.get_attribute ("abstract") == "1"); + cl.is_sealed = metadata.get_bool (ArgumentType.SEALED, false); if (parent != null) { cl.add_base_type (parse_type_from_gir_name (parent)); diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 2b480ce59..62ad72898 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -2636,6 +2636,9 @@ public class Vala.Parser : CodeVisitor { if (ModifierFlags.ABSTRACT in flags) { cl.is_abstract = true; } + if (ModifierFlags.SEALED in flags) { + cl.is_sealed = true; + } if (ModifierFlags.EXTERN in flags) { cl.is_extern = true; }