]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add support for partial classes
authorSimon Werbeck <simon.werbeck@gmail.com>
Sun, 31 Mar 2013 20:30:07 +0000 (22:30 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Sat, 30 Oct 2021 11:28:07 +0000 (13:28 +0200)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/370

tests/Makefile.am
tests/objects/class-partial-conflict-abstract.test [new file with mode: 0644]
tests/objects/class-partial-conflict-access.test [new file with mode: 0644]
tests/objects/class-partial-conflict-partial.test [new file with mode: 0644]
tests/objects/class-partial-conflict-sealed.test [new file with mode: 0644]
tests/objects/class-partial.vala [new file with mode: 0644]
vala/valaclass.vala
vala/valaparser.vala
vala/valascanner.vala
vala/valatokentype.vala

index d0062f879ae856d0a039e4c5b91031a2edbc5db3..518a22f4369d0495f04437ad33c929f1b5e2cfaa 100644 (file)
@@ -451,6 +451,11 @@ TESTS = \
        objects/class-destroysinstance.vala \
        objects/class-inner-types.vala \
        objects/class-new-no-override.vala \
+       objects/class-partial.vala \
+       objects/class-partial-conflict-abstract.test \
+       objects/class-partial-conflict-access.test \
+       objects/class-partial-conflict-partial.test \
+       objects/class-partial-conflict-sealed.test \
        objects/class-vfunc-base-access.vala \
        objects/classes.vala \
        objects/classes-interfaces.vala \
diff --git a/tests/objects/class-partial-conflict-abstract.test b/tests/objects/class-partial-conflict-abstract.test
new file mode 100644 (file)
index 0000000..c34126d
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+partial abstract class Foo {
+}
+
+partial class Foo {
+}
+
+void main () {
+}
diff --git a/tests/objects/class-partial-conflict-access.test b/tests/objects/class-partial-conflict-access.test
new file mode 100644 (file)
index 0000000..d52e975
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+public partial class Foo {
+}
+
+partial class Foo {
+}
+
+void main () {
+}
diff --git a/tests/objects/class-partial-conflict-partial.test b/tests/objects/class-partial-conflict-partial.test
new file mode 100644 (file)
index 0000000..6ae9843
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+class Foo {
+}
+
+partial class Foo {
+}
+
+void main () {
+}
diff --git a/tests/objects/class-partial-conflict-sealed.test b/tests/objects/class-partial-conflict-sealed.test
new file mode 100644 (file)
index 0000000..16f7e80
--- /dev/null
@@ -0,0 +1,10 @@
+Invalid Code
+
+partial sealed class Foo {
+}
+
+partial class Foo {
+}
+
+void main () {
+}
diff --git a/tests/objects/class-partial.vala b/tests/objects/class-partial.vala
new file mode 100644 (file)
index 0000000..15477f0
--- /dev/null
@@ -0,0 +1,70 @@
+public interface IFoo {
+       public abstract void i1 ();
+}
+
+public interface IBar {
+       public abstract void i2 ();
+}
+
+public partial class Foo : Object {
+       public string p0 { get; set; }
+       public string f0;
+       public void m0 () {
+       }
+       public virtual void v0 () {
+       }
+       public virtual signal void s0 () {
+       }
+}
+
+public partial class Foo : IFoo {
+       public string p1 { get; set; }
+       public string f1;
+       public void m1 () {
+       }
+       public virtual void v1 () {
+       }
+       public virtual signal void s1 () {
+       }
+       public void i1 () {
+       }
+}
+
+public partial class Foo : IBar {
+       public string p2 { get; set; }
+       public string f2;
+       public void m2 () {
+       }
+       public virtual void v2 () {
+       }
+       public virtual signal void s2 () {
+       }
+       public void i2 () {
+       }
+}
+
+void main () {
+       var foo = new Foo ();
+       foo.p0 = "p0";
+       foo.f0 = "f0";
+       foo.m0 ();
+       foo.v0 ();
+       foo.s0 ();
+
+       foo.p1 = "p1";
+       foo.f1 = "f1";
+       foo.m1 ();
+       foo.v1 ();
+       foo.s1 ();
+
+       foo.p2 = "p2";
+       foo.f2 = "f2";
+       foo.m2 ();
+       foo.v2 ();
+       foo.s2 ();
+
+       assert (foo is IFoo);
+       foo.i1 ();
+       assert (foo is IBar);
+       foo.i2 ();
+}
index ee4ed624fc51c9a9709bc1441e6f5db1166bc367..a6f5ae6339679a4faf8551fc7919da7412e5de89 100644 (file)
@@ -37,6 +37,8 @@ public class Vala.Class : ObjectTypeSymbol {
         */
        public bool is_abstract { get; set; }
 
+       public bool is_partial { get; set; }
+
        /**
         * Specifies whether this class is sealed. Sealed classes may not be
         * sub-classed.
index f71f6e89cb4f1974ae128d769de738d01e12a206..a2b99f9ed77b326ae128d3930df95b4471f5367f 100644 (file)
@@ -61,7 +61,8 @@ public class Vala.Parser : CodeVisitor {
                STATIC,
                VIRTUAL,
                ASYNC,
-               SEALED
+               SEALED,
+               PARTIAL
        }
 
        public Parser () {
@@ -253,6 +254,7 @@ public class Vala.Parser : CodeVisitor {
                case TokenType.OVERRIDE:
                case TokenType.OWNED:
                case TokenType.PARAMS:
+               case TokenType.PARTIAL:
                case TokenType.PRIVATE:
                case TokenType.PROTECTED:
                case TokenType.PUBLIC:
@@ -2733,6 +2735,7 @@ public class Vala.Parser : CodeVisitor {
                        case TokenType.NAMESPACE:
                        case TokenType.NEW:
                        case TokenType.OVERRIDE:
+                       case TokenType.PARTIAL:
                        case TokenType.PRIVATE:
                        case TokenType.PROTECTED:
                        case TokenType.PUBLIC:
@@ -2842,9 +2845,42 @@ public class Vala.Parser : CodeVisitor {
                if (ModifierFlags.SEALED in flags) {
                        cl.is_sealed = true;
                }
+               if (ModifierFlags.PARTIAL in flags) {
+                       if (!context.experimental) {
+                               Report.warning (cl.source_reference, "`partial' classes are experimental");
+                       }
+                       cl.is_partial = true;
+               }
                if (ModifierFlags.EXTERN in flags) {
                        cl.is_extern = true;
                }
+
+               var old_cl = parent.scope.lookup (cl.name) as Class;
+               if (old_cl != null && old_cl.is_partial) {
+                       if (cl.is_partial != old_cl.is_partial) {
+                               Report.error (cl.source_reference, "conflicting partial and not partial declarations of `%s'".printf (cl.name));
+                               cl.error = true;
+                       }
+                       if (cl.access != old_cl.access) {
+                               Report.error (cl.source_reference, "partial declarations of `%s' have conflicting accessiblity modifiers".printf (cl.name));
+                               cl.error = true;
+                       }
+                       if (cl.is_abstract != old_cl.is_abstract) {
+                               Report.error (cl.source_reference, "partial declarations of `%s' have conflicting abstract modifiers".printf (cl.name));
+                               cl.error = true;
+                       }
+                       if (cl.is_sealed != old_cl.is_sealed) {
+                               Report.error (cl.source_reference, "partial declarations of `%s' have conflicting sealed modifiers".printf (cl.name));
+                               cl.error = true;
+                       }
+                       if (cl.error) {
+                               Report.notice (old_cl.source_reference, "previous declaration of `%s' was here", old_cl.name);
+                               return;
+                       }
+
+                       cl = old_cl;
+               }
+
                set_attributes (cl, attrs);
                foreach (TypeParameter type_param in type_param_list) {
                        cl.add_type_parameter (type_param);
@@ -2855,6 +2891,10 @@ public class Vala.Parser : CodeVisitor {
 
                parse_declarations (cl);
 
+               if (old_cl != null && old_cl.is_partial) {
+                       return;
+               }
+
                // ensure there is always a default construction method
                if (scanner.source_file.file_type == SourceFileType.SOURCE
                    && cl.default_construction_method == null) {
@@ -3530,6 +3570,10 @@ public class Vala.Parser : CodeVisitor {
                                next ();
                                flags |= ModifierFlags.EXTERN;
                                break;
+                       case TokenType.PARTIAL:
+                               next ();
+                               flags |= ModifierFlags.PARTIAL;
+                               break;
                        case TokenType.SEALED:
                                next ();
                                flags |= ModifierFlags.SEALED;
@@ -3872,6 +3916,7 @@ public class Vala.Parser : CodeVisitor {
                case TokenType.NAMESPACE:
                case TokenType.NEW:
                case TokenType.OVERRIDE:
+               case TokenType.PARTIAL:
                case TokenType.PRIVATE:
                case TokenType.PROTECTED:
                case TokenType.PUBLIC:
index 36f274e6fc9cbd36d8771ba64b9b173e3902bbed..daeb97febe3a4c65e72297f3ee95effa3bafaf17 100644 (file)
@@ -533,7 +533,14 @@ public class Vala.Scanner {
                                }
                                break;
                        case 'p':
-                               if (matches (begin, "private")) return TokenType.PRIVATE;
+                               switch (begin[1]) {
+                               case 'r':
+                                       if (matches (begin, "private")) return TokenType.PRIVATE;
+                                       break;
+                               case 'a':
+                                       if (matches (begin, "partial")) return TokenType.PARTIAL;
+                                       break;
+                               }
                                break;
                        case 'u':
                                if (matches (begin, "unowned")) return TokenType.UNOWNED;
index 9cc6d1c746480611b6009890070105984256b762..2c64ec1b00c618715858303191e8991a835afb46 100644 (file)
@@ -115,6 +115,7 @@ public enum Vala.TokenType {
        OVERRIDE,
        OWNED,
        PARAMS,
+       PARTIAL,
        PERCENT,
        PLUS,
        PRIVATE,
@@ -249,6 +250,7 @@ public enum Vala.TokenType {
                case OVERRIDE: return "`override'";
                case OWNED: return "`owned'";
                case PARAMS: return "`params'";
+               case PARTIAL: return "`partial'";
                case PERCENT: return "`%'";
                case PLUS: return "`+'";
                case PRIVATE: return "`private'";