From 3dbf0e24e450cc51282eef3f1ac53dcb3d3f0c60 Mon Sep 17 00:00:00 2001 From: Tyler Rockwood Date: Tue, 4 Sep 2018 09:06:29 -0700 Subject: [PATCH] Implement a nullable annotation for fields and messages (#26) * Implement a nullable annotation for fields and messages * Add back deleted tests --- firebase_rules_generator/generator.cc | 10 +++++++++- proto/firebase_rules_options.proto | 2 ++ testdata/testA.proto | 17 +++++++++++++++++ testdata/testA.rules | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 testdata/testA.proto create mode 100644 testdata/testA.rules diff --git a/firebase_rules_generator/generator.cc b/firebase_rules_generator/generator.cc index 4c81bff..50ef1a2 100644 --- a/firebase_rules_generator/generator.cc +++ b/firebase_rules_generator/generator.cc @@ -457,7 +457,15 @@ bool RulesGenerator::GenerateField(const protobuf::FieldDescriptor *field, if (options.has_validate()) { printer.Print(" && ($validate$)", "validate", options.validate()); } - printer.Print("))"); + printer.Print(")"); + const auto &msg_options = + field->containing_type()->options().GetExtension(firebase_rules_message); + bool nullable = + (!options.has_nullable() && msg_options.nullable()) || options.nullable(); + if (nullable) { + printer.Print(" || resource.$name$ is null", "name", field->json_name()); + } + printer.Print(")"); return true; } diff --git a/proto/firebase_rules_options.proto b/proto/firebase_rules_options.proto index fa24389..45297bb 100644 --- a/proto/firebase_rules_options.proto +++ b/proto/firebase_rules_options.proto @@ -7,11 +7,13 @@ import "google/protobuf/descriptor.proto"; message RulesMessageOptions { optional string validate = 1; optional bool extra_properties = 2 [default = false]; + optional bool nullable = 3 [default = false]; } message RulesFieldOptions { optional string validate = 1; optional bool reference_type = 2 [default = false]; + optional bool nullable = 3 [default = false]; } message RulesFileOptions { diff --git a/testdata/testA.proto b/testdata/testA.proto new file mode 100644 index 0000000..4ee223c --- /dev/null +++ b/testdata/testA.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package example; + +import "firebase_rules_options.proto"; + +message NullableExample { + string foo = 1; + string bar = 2 + [(google.firebase.rules.firebase_rules_field).nullable = false]; + option (google.firebase.rules.firebase_rules_message).nullable = true; +} + +message Example { + string foo = 1; + string bar = 2 [(google.firebase.rules.firebase_rules_field).nullable = true]; +} diff --git a/testdata/testA.rules b/testdata/testA.rules new file mode 100644 index 0000000..16172b4 --- /dev/null +++ b/testdata/testA.rules @@ -0,0 +1,14 @@ +// @@START_GENERATED_FUNCTIONS@@ +function isNullableExampleMessage(resource) { + return resource.keys().hasAll([]) && + (resource.keys().hasOnly(['bar','foo'])) && + ((!resource.keys().hasAny(['foo'])) || (resource.foo is string) || resource.foo is null) && + ((!resource.keys().hasAny(['bar'])) || (resource.bar is string)); +} +function isExampleMessage(resource) { + return resource.keys().hasAll([]) && + (resource.keys().hasOnly(['bar','foo'])) && + ((!resource.keys().hasAny(['foo'])) || (resource.foo is string)) && + ((!resource.keys().hasAny(['bar'])) || (resource.bar is string) || resource.bar is null); +} +// @@END_GENERATED_FUNCTIONS@@