From: Rico Tzschichholz Date: Fri, 26 Feb 2021 14:55:09 +0000 (+0100) Subject: vala: Improve context check whether property is writeable on assignments X-Git-Tag: 0.51.3~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e54960ff6b1773d78da4e06e972e6cd5f6eecdd;p=thirdparty%2Fvala.git vala: Improve context check whether property is writeable on assignments --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 5ca793613..449171ca2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -469,8 +469,11 @@ TESTS = \ objects/property-notify-owned-getter.vala \ objects/property-ownership.vala \ objects/property-read-only-auto.vala \ + objects/property-read-only-member-write.test \ objects/property-read-only-write.test \ + objects/property-construct-only.vala \ objects/property-construct-only-write.test \ + objects/property-construct-only-write-after.test \ objects/property-construct-only-write-foreign.test \ objects/property-delegate.vala \ objects/property-delegate-owned.vala \ @@ -480,6 +483,7 @@ TESTS = \ objects/property-simple-type-struct-nullable.vala \ objects/property-static.vala \ objects/property-struct-no-gtype.vala \ + objects/property-write-only-member-read.test \ objects/regex.vala \ objects/sealed-abstract-class.test \ objects/sealed-class.test \ diff --git a/tests/objects/property-construct-only-write-after.test b/tests/objects/property-construct-only-write-after.test new file mode 100644 index 000000000..446145f08 --- /dev/null +++ b/tests/objects/property-construct-only-write-after.test @@ -0,0 +1,10 @@ +Invalid Code + +class Foo : GLib.Object { + public string manam { get; construct; } +} + +void main () { + var foo = new Foo (); + foo.manam = "manam"; +} diff --git a/tests/objects/property-construct-only.vala b/tests/objects/property-construct-only.vala new file mode 100644 index 000000000..700980315 --- /dev/null +++ b/tests/objects/property-construct-only.vala @@ -0,0 +1,46 @@ +class Foo : GLib.Object { + public string manam { get; construct; } + + construct { + manam = "foo"; + } +} + +class Bar : Foo { + construct { + manam = "bar"; + } +} + +class Faz : GLib.Object { + public string manam { get; construct; } + + public Faz () { + Object (manam : "faz"); + } +} + +class Baz : Faz { + public Baz () { + Object (manam : "baz"); + } +} + +void main () { + { + var foo = new Foo (); + assert (foo.manam == "foo"); + } + { + var bar = new Bar (); + assert (bar.manam == "bar"); + } + { + var faz = new Faz (); + assert (faz.manam == "faz"); + } + { + var baz = new Baz (); + assert (baz.manam == "baz"); + } +} diff --git a/tests/objects/property-read-only-member-write.test b/tests/objects/property-read-only-member-write.test new file mode 100644 index 000000000..6696454e1 --- /dev/null +++ b/tests/objects/property-read-only-member-write.test @@ -0,0 +1,15 @@ +Invalid Code + +class Foo : GLib.Object { + public string manam { get; construct; } +} + +class Bar : GLib.Object { + construct { + var foo = new Foo (); + foo.manam = "manam"; + } +} + +void main () { +} diff --git a/tests/objects/property-write-only-member-read.test b/tests/objects/property-write-only-member-read.test new file mode 100644 index 000000000..213387c35 --- /dev/null +++ b/tests/objects/property-write-only-member-read.test @@ -0,0 +1,10 @@ +Invalid Code + +class Foo : GLib.Object { + public string manam { set; } +} + +void main () { + var foo = new Foo (); + var s = foo.manam; +} diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala index 4ffc75735..8902aedf3 100644 --- a/vala/valaassignment.vala +++ b/vala/valaassignment.vala @@ -276,26 +276,6 @@ public class Vala.Assignment : Expression { dynamic_prop.property_type = right.value_type.copy (); left.value_type = dynamic_prop.property_type.copy (); } - - if (prop.set_accessor == null - || (!prop.set_accessor.writable && !(context.analyzer.find_current_method () is CreationMethod || context.analyzer.is_in_constructor ()))) { - ma.error = true; - Report.error (ma.source_reference, "Property `%s' is read-only", prop.get_full_name ()); - return false; - } else if (!context.deprecated - && !prop.set_accessor.writable - && context.analyzer.find_current_method () is CreationMethod) { - if (ma.inner.symbol_reference != context.analyzer.find_current_method ().this_parameter) { - // trying to set construct-only property in creation method for foreign instance - error = true; - Report.error (ma.source_reference, "Property `%s' is read-only", prop.get_full_name ()); - return false; - } else { - error = true; - Report.error (ma.source_reference, "Cannot assign to construct-only properties, use Object (property: value) constructor chain up"); - return false; - } - } } else if (ma.symbol_reference is ArrayLengthField && ((ArrayType) ma.inner.value_type).inline_allocated) { error = true; Report.error (source_reference, "`length' field of fixed length arrays is read-only"); diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala index d56f7ba93..16484a6fd 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -798,6 +798,22 @@ public class Vala.MemberAccess : Expression { error = true; Report.error (source_reference, "Property `%s' is read-only", prop.get_full_name ()); return false; + } else if (!prop.set_accessor.writable && prop.set_accessor.construction) { + if (context.analyzer.find_current_method () is CreationMethod) { + error = true; + Report.error (source_reference, "Cannot assign to construct-only properties, use Object (property: value) constructor chain up"); + return false; + } else if (context.analyzer.is_in_constructor ()) { + if (!context.analyzer.current_type_symbol.is_subtype_of ((TypeSymbol) prop.parent_symbol)) { + error = true; + Report.error (source_reference, "Cannot assign to construct-only property `%s' in `construct' of `%s'", prop.get_full_name (), context.analyzer.current_type_symbol.get_full_name ()); + return false; + } + } else { + error = true; + Report.error (source_reference, "Cannot assign to construct-only property in this context"); + return false; + } } if (prop.access == SymbolAccessibility.PUBLIC) { access = prop.set_accessor.access;