objects/property-read-only-auto.vala \
objects/property-read-only-member-write.test \
objects/property-read-only-write.test \
+ objects/property-class-invalid-name.test \
objects/property-construct-only.vala \
objects/property-construct-only-write.test \
objects/property-construct-only-write-after.test \
objects/property-delegate.vala \
objects/property-delegate-owned.vala \
objects/property-gboxed-nullable.vala \
+ objects/property-interface-invalid-name.test \
objects/property-real-struct-assignment.vala \
objects/property-real-struct-no-accessor.test \
objects/property-simple-type-struct-nullable.vala \
--- /dev/null
+Invalid Code
+
+class Foo : Object {
+ public string 1foo { get; set; }
+}
+
+void main () {
+}
--- /dev/null
+Invalid Code
+
+interface IFoo : Object {
+ public abstract string _foo { get; set; }
+}
+
+void main () {
+}
checked = true;
+ if (context.profile == Profile.GOBJECT && parent_symbol is ObjectTypeSymbol
+ && ((ObjectTypeSymbol) parent_symbol).is_subtype_of (context.analyzer.object_type)) {
+ if (!is_valid_name (name)) {
+ error = true;
+ Report.error (source_reference, "Name `%s' is not valid for a GLib.Object property", name);
+ }
+ }
+
if (this_parameter != null) {
this_parameter.check (context);
}
return !error;
}
+
+ // Ported from glib's "g_param_spec_is_valid_name"
+ static bool is_valid_name (string name) {
+ char* p;
+
+ if ((name[0] < 'A' || name[0] > 'Z')
+ && (name[0] < 'a' || name[0] > 'z')) {
+ return false;
+ }
+
+ for (p = name; *p != '\0'; p++) {
+ char c = *p;
+ if (c != '-' && c != '_' && (c < '0' || c > '9')
+ && (c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
return false;
}
- if (!prop.name[0].isalpha ()) {
- // GObject requires properties to start with a letter
- return false;
- }
-
if (type_sym is Interface && !prop.is_abstract && !prop.external && !prop.external_package) {
// GObject does not support non-abstract interface properties,
// however we assume external properties always are GObject properties