]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Add support for sealed classes tintou/sealed
authorCorentin Noël <corentin@elementary.io>
Tue, 7 Jan 2020 20:41:39 +0000 (21:41 +0100)
committerCorentin Noël <corentin@elementary.io>
Wed, 8 Jan 2020 08:38:19 +0000 (09:38 +0100)
tests/Makefile.am
tests/objects/sealed-subclass.test [new file with mode: 0644]
tests/objects/sealed.vala [new file with mode: 0644]
vala/valaclass.vala
vala/valacodewriter.vala
vala/valagirparser.vala
vala/valaparser.vala

index ebeeed0efdec759c083a29ef8c8572b55eac7170..c5301ca05b92acd142e56efc0d9baece3a906228 100644 (file)
@@ -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 (file)
index 0000000..da189d5
--- /dev/null
@@ -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 (file)
index 0000000..8112fc4
--- /dev/null
@@ -0,0 +1,9 @@
+sealed class Foo : GLib.Object {
+       public void do_action () {
+               stdout.printf (" 2");
+       }
+}
+
+void main () {
+       var foo = new Foo ();
+}
index e9312c4158bae50b85d8d3030b5ff6b0272f9c75..d0720dde1d4489da24a8970cf5eaed4a20186849 100644 (file)
@@ -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
+        * 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
@@ -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;
index 2f735e87fd41eedcf1803a31e0bcae281ea45708..50c4878e6da059d0c29e32ebfdebf64df5fa04ff 100644 (file)
@@ -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);
 
index 17b41b1e556e37edb8cfdcfa6431bb7d8d361f5a..5f9aa5f5c491871af3a3ee27c53b8df2d8d960f2 100644 (file)
@@ -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 ();
 
index 45a420955e168dae989c733bb9816538fc219b40..538d9255025a47a590a3a18b6375ae170915495b 100644 (file)
@@ -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;