diff options
author | Corentin Noël <corentin@elementary.io> | 2020-01-07 21:41:39 +0100 |
---|---|---|
committer | Corentin Noël <corentin@elementary.io> | 2020-01-08 09:38:19 +0100 |
commit | b96215c14c7a27e5a782018a0cb4eb33577e1cff (patch) | |
tree | 522c598fdf48b464f19085f91125a6a26b81dbf4 | |
parent | af236c9595e80803ff0e9b38b352e6a5153f4985 (diff) | |
download | vala-tintou/sealed.tar.gz |
vala: Add support for sealed classestintou/sealed
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/objects/sealed-subclass.test | 16 | ||||
-rw-r--r-- | tests/objects/sealed.vala | 9 | ||||
-rw-r--r-- | vala/valaclass.vala | 10 | ||||
-rw-r--r-- | vala/valacodewriter.vala | 4 | ||||
-rw-r--r-- | vala/valagirparser.vala | 10 | ||||
-rw-r--r-- | vala/valaparser.vala | 27 |
7 files changed, 72 insertions, 6 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index ebeeed0ef..c5301ca05 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -363,6 +363,8 @@ TESTS = \ objects/property-simple-type-struct-nullable.vala \ objects/property-static.vala \ objects/regex.vala \ + objects/sealed.vala \ + objects/sealed-subclass.test \ objects/signals.vala \ objects/signals-enum-marshal.vala \ objects/signals-delegate.vala \ diff --git a/tests/objects/sealed-subclass.test b/tests/objects/sealed-subclass.test new file mode 100644 index 000000000..da189d5a9 --- /dev/null +++ b/tests/objects/sealed-subclass.test @@ -0,0 +1,16 @@ +Invalid Code + +sealed class Foo : GLib.Object { + public void do_action () { + stdout.printf (" 1"); + } +} + +class Bar : Foo { + public void do_other_action () { + stdout.printf (" 2"); + } +} + +void main () { +} diff --git a/tests/objects/sealed.vala b/tests/objects/sealed.vala new file mode 100644 index 000000000..8112fc49f --- /dev/null +++ b/tests/objects/sealed.vala @@ -0,0 +1,9 @@ +sealed class Foo : GLib.Object { + public void do_action () { + stdout.printf (" 2"); + } +} + +void main () { + var foo = new Foo (); +} diff --git a/vala/valaclass.vala b/vala/valaclass.vala index e9312c415..d0720dde1 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -38,6 +38,12 @@ public class Vala.Class : ObjectTypeSymbol { public bool is_abstract { get; set; } /** + * Specifies whether this class is sealed. Sealed classes may not be + * subclassed. + */ + 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 * type information or virtual methods. @@ -791,6 +797,10 @@ public class Vala.Class : ObjectTypeSymbol { } } + if (base_class != null && base_class.is_sealed) { + Report.error (source_reference, "`%s' subclasses a `%s' which is a sealed class".printf (get_full_name (), base_class.get_full_name ())); + } + /* all abstract symbols defined in base classes have to be implemented in non-abstract classes */ if (!is_abstract) { unowned Class? base_class = base_class; diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala index 2f735e87f..50c4878e6 100644 --- a/vala/valacodewriter.vala +++ b/vala/valacodewriter.vala @@ -246,6 +246,10 @@ 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 17b41b1e5..5f9aa5f5c 100644 --- a/vala/valagirparser.vala +++ b/vala/valagirparser.vala @@ -1184,6 +1184,10 @@ public class Vala.GirParser : CodeVisitor { // set the interface struct name iface.symbol.set_attribute_string ("CCode", "type_cname", get_cname ()); } + var cls = iface.symbol as Class; + if (iface != null && cls != null && !cls.is_abstract && girdata["disguised"] != "1") { + cls.is_sealed = true; + } merged = true; } } @@ -2813,6 +2817,12 @@ public class Vala.GirParser : CodeVisitor { unresolved_gir_symbols.add (current.gtype_struct_for); } + var disguised = reader.get_attribute ("disguised"); + if (disguised != null) { + current.gtype_struct_for = parse_symbol_from_string (gtype_struct_for, current.source_reference); + unresolved_gir_symbols.add (current.gtype_struct_for); + } + bool first_field = true; next (); diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 45a420955..538d92550 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -2587,6 +2587,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; } @@ -2695,8 +2698,9 @@ public class Vala.Parser : CodeVisitor { if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags - || ModifierFlags.OVERRIDE in flags) { - Report.error (f.source_reference, "abstract, virtual, and override modifiers are not applicable to fields"); + || ModifierFlags.OVERRIDE in flags + || ModifierFlags.SEALED in flags) { + Report.error (f.source_reference, "abstract, virtual, override, and modifiers are not applicable to fields"); } if (ModifierFlags.EXTERN in flags) { f.is_extern = true; @@ -2772,6 +2776,9 @@ public class Vala.Parser : CodeVisitor { if (ModifierFlags.OVERRIDE in flags) { method.overrides = true; } + if (ModifierFlags.SEALED in flags) { + throw new ParseError.SYNTAX ("the modifier `sealed' is not valid for methods"); + } if ((method.is_abstract && method.is_virtual) || (method.is_abstract && method.overrides) || (method.is_virtual && method.overrides)) { @@ -2780,8 +2787,9 @@ public class Vala.Parser : CodeVisitor { } else { if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags - || ModifierFlags.OVERRIDE in flags) { - throw new ParseError.SYNTAX ("the modifiers `abstract', `virtual', and `override' are not valid for %s methods", (ModifierFlags.CLASS in flags) ? "class" : "static"); + || ModifierFlags.OVERRIDE in flags + || ModifierFlags.SEALED in flags) { + throw new ParseError.SYNTAX ("the modifiers `abstract', `virtual', `override', and `sealed' are not valid for %s methods", (ModifierFlags.CLASS in flags) ? "class" : "static"); } } @@ -2847,6 +2855,9 @@ public class Vala.Parser : CodeVisitor { if (ModifierFlags.OVERRIDE in flags) { prop.overrides = true; } + if (ModifierFlags.SEALED in flags) { + throw new ParseError.SYNTAX ("the modifier `sealed' is not valid for properties"); + } if (ModifierFlags.NEW in flags) { prop.hides = true; } @@ -2952,6 +2963,9 @@ public class Vala.Parser : CodeVisitor { } else if (ModifierFlags.CLASS in flags) { throw new ParseError.SYNTAX ("`class' modifier not allowed on signals"); } + if (ModifierFlags.SEALED in flags) { + throw new ParseError.SYNTAX ("`sealed' modifier not allowed on signals"); + } if (ModifierFlags.VIRTUAL in flags) { sig.is_virtual = true; } @@ -3388,8 +3402,9 @@ public class Vala.Parser : CodeVisitor { } if (ModifierFlags.ABSTRACT in flags || ModifierFlags.VIRTUAL in flags - || ModifierFlags.OVERRIDE in flags) { - Report.error (method.source_reference, "abstract, virtual, and override modifiers are not applicable to creation methods"); + || ModifierFlags.OVERRIDE in flags + || ModifierFlags.SEALED in flags) { + Report.error (method.source_reference, "abstract, virtual, override, and sealed modifiers are not applicable to creation methods"); } if (ModifierFlags.ASYNC in flags) { method.coroutine = true; |