[vala/wip/issue/370: 44/44] Add support for partial classes




commit 554011b393cf9635e2990a589c6323925fe53090
Author: Simon Werbeck <simon werbeck gmail com>
Date:   Sun Mar 31 22:30:07 2013 +0200

    Add support for partial classes
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/370

 tests/Makefile.am                                  |  5 ++
 tests/objects/class-partial-conflict-abstract.test | 10 ++++
 tests/objects/class-partial-conflict-access.test   | 10 ++++
 tests/objects/class-partial-conflict-partial.test  | 10 ++++
 tests/objects/class-partial-conflict-sealed.test   | 10 ++++
 tests/objects/class-partial.vala                   | 70 ++++++++++++++++++++++
 vala/valaclass.vala                                |  2 +
 vala/valaparser.vala                               | 47 ++++++++++++++-
 vala/valascanner.vala                              |  9 ++-
 vala/valatokentype.vala                            |  2 +
 10 files changed, 173 insertions(+), 2 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d0062f879..518a22f43 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 000000000..c34126d15
--- /dev/null
+++ b/tests/objects/class-partial-conflict-abstract.test
@@ -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
index 000000000..d52e97532
--- /dev/null
+++ b/tests/objects/class-partial-conflict-access.test
@@ -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
index 000000000..6ae9843c1
--- /dev/null
+++ b/tests/objects/class-partial-conflict-partial.test
@@ -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
index 000000000..16f7e8083
--- /dev/null
+++ b/tests/objects/class-partial-conflict-sealed.test
@@ -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
index 000000000..15477f01c
--- /dev/null
+++ b/tests/objects/class-partial.vala
@@ -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 ();
+}
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index ee4ed624f..a6f5ae633 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -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.
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index f71f6e89c..a2b99f9ed 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -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:
diff --git a/vala/valascanner.vala b/vala/valascanner.vala
index 36f274e6f..daeb97feb 100644
--- a/vala/valascanner.vala
+++ b/vala/valascanner.vala
@@ -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;
diff --git a/vala/valatokentype.vala b/vala/valatokentype.vala
index 9cc6d1c74..2c64ec1b0 100644
--- a/vala/valatokentype.vala
+++ b/vala/valatokentype.vala
@@ -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'";


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]