Skip to content

Commit 1c7a062

Browse files
feat, wip: support for optional
1 parent 7225e6e commit 1c7a062

File tree

11 files changed

+105
-14
lines changed

11 files changed

+105
-14
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ${${QT_VERSIONED_PREFIX}_POSITION_INDEPENDEN
4949
if(UNIX)
5050
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
5151
# using Clang
52-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wno-pessimizing-move -Wno-mismatched-tags -Wno-unused-private-field -Wno-self-assign-overloaded")
52+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pessimizing-move -Wno-mismatched-tags -Wno-unused-private-field -Wno-self-assign-overloaded")
5353
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
5454
# using GCC
55-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wno-error=deprecated-declarations")
55+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=deprecated-declarations")
5656
endif()
5757
elseif(WIN32)
5858
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")

cmake/QtProtobufGen.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function(qtprotobuf_link_target TARGET GENERATED_TARGET)
55
endfunction()
66

77
function(qtprotobuf_generate)
8-
set(options MULTI QML COMMENTS FOLDER FIELDENUM)
8+
set(options MULTI QML COMMENTS FOLDER FIELDENUM ALLOW_PROTO3_OPTIONAL)
99
set(oneValueArgs OUT_DIR TARGET GENERATED_TARGET EXTRA_NAMESPACE)
1010
set(multiValueArgs GENERATED_HEADERS EXCLUDE_HEADERS PROTO_FILES PROTO_INCLUDES)
1111
cmake_parse_arguments(qtprotobuf_generate "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -143,6 +143,7 @@ function(qtprotobuf_generate)
143143
OUTPUT ${GENERATED_SOURCES_FULL} ${GENERATED_HEADERS_FULL}
144144
COMMAND ${PROTOC_COMMAND}
145145
--plugin=protoc-gen-qtprotobufgen=${QT_PROTOBUF_EXECUTABLE}
146+
$<IF:$<BOOL:${qtprotobuf_generate_ALLOW_PROTO3_OPTIONAL}>,--experimental_allow_proto3_optional,>
146147
--qtprotobufgen_out=${OUT_DIR}
147148
${PROTO_INCLUDES}
148149
${qtprotobuf_generate_PROTO_FILES}

cmake/QtProtobufInternalHelpers.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ function(qt_protobuf_internal_add_test)
5454
PROTO_FILES ${proto_files}
5555
GENERATED_HEADERS ${add_test_target_GENERATED_HEADERS}
5656
EXCLUDE_HEADERS ${add_test_target_EXCLUDE_HEADERS}
57+
ALLOW_PROTO3_OPTIONAL
5758
${EXTRA_OPTIONS}
5859
PROTO_INCLUDES ${add_test_target_PROTO_INCLUDES})
5960

src/generator/generatorbase.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ class GeneratorBase: public ::google::protobuf::compiler::CodeGenerator
136136
GeneratorBase(Mode mode);
137137
virtual ~GeneratorBase() = default;
138138

139+
::google::protobuf::uint64 GetSupportedFeatures() const override { return FEATURE_PROTO3_OPTIONAL; }
140+
139141
virtual bool GenerateAll(const std::vector<const ::google::protobuf::FileDescriptor *> &files,
140142
const std::string &parameter,
141143
::google::protobuf::compiler::GeneratorContext *generatorContext,

src/generator/generatorcommon.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,22 @@ PropertyMap common::producePropertyMap(const FieldDescriptor *field, const Descr
347347
return propertyMap;
348348
}
349349

350+
PropertyMap common::produceOptionalPropertyMap(const FieldDescriptor *field, const Descriptor *scope)
351+
{
352+
PropertyMap map = producePropertyMap(field, scope);
353+
354+
map["property_type"] = "bool";
355+
map["getter_type"] = "bool";
356+
map["setter_type"] = "bool";
357+
map["scope_type"] = "bool";
358+
map["initializer"] = "true";
359+
map["scriptable"] = "true";
360+
map["property_name"] = "has_" + map["property_name"];
361+
map["property_name_cap"] = utils::upperCaseName(map["property_name"]);
362+
363+
return map;
364+
}
365+
350366
std::string common::qualifiedName(const std::string &name)
351367
{
352368
std::string fieldName(name);

src/generator/generatorcommon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct common {
8080
static TypeMap produceSimpleTypeMap(::google::protobuf::FieldDescriptor::Type type);
8181
static TypeMap produceTypeMap(const ::google::protobuf::FieldDescriptor *field, const ::google::protobuf::Descriptor *scope);
8282
static PropertyMap producePropertyMap(const ::google::protobuf::FieldDescriptor *field, const ::google::protobuf::Descriptor *scope);
83+
static PropertyMap produceOptionalPropertyMap(const ::google::protobuf::FieldDescriptor *field, const ::google::protobuf::Descriptor *scope);
8384
static std::string qualifiedName(const std::string &name);
8485
static bool isLocalEnum(const ::google::protobuf::EnumDescriptor *type, const google::protobuf::Descriptor *scope);
8586
static EnumVisibility enumVisibility(const ::google::protobuf::EnumDescriptor *type, const ::google::protobuf::Descriptor *scope);

src/generator/messagedeclarationprinter.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,16 @@ void MessageDeclarationPrinter::printProperties()
242242
}
243243
}
244244

245+
for (int i = 0; i < mDescriptor->field_count(); i++) {
246+
const FieldDescriptor *field = mDescriptor->field(i);
247+
248+
if (!field->is_optional()) {
249+
continue;
250+
}
251+
252+
mPrinter->Print(common::produceOptionalPropertyMap(field, mDescriptor), Templates::ReadOnlyPropertyTemplate);
253+
}
254+
245255
Outdent();
246256
}
247257

@@ -257,6 +267,12 @@ void MessageDeclarationPrinter::printGetters()
257267
mPrinter->Print(propertyMap, Templates::GetterTemplate);
258268
}
259269

270+
if (field->is_optional()) {
271+
auto optionalMap = common::produceOptionalPropertyMap(field, mDescriptor);
272+
273+
mPrinter->Print(optionalMap, Templates::GetterTemplate);
274+
}
275+
260276
if (field->is_repeated()) {
261277
mPrinter->Print(propertyMap, Templates::GetterContainerExtraTemplate);
262278
if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map()
@@ -286,6 +302,11 @@ void MessageDeclarationPrinter::printSetters()
286302
break;
287303
default:
288304
mPrinter->Print(propertyMap, Templates::SetterTemplate);
305+
if (field->is_optional()) {
306+
mPrinter->Print(propertyMap, Templates::EndOptionalSetterTemplate);
307+
} else {
308+
mPrinter->Print(propertyMap, Templates::EndSetterTemplate);
309+
}
289310
break;
290311
}
291312
});
@@ -318,7 +339,12 @@ void MessageDeclarationPrinter::printSignals()
318339
{
319340
Indent();
320341
for (int i = 0; i < mDescriptor->field_count(); i++) {
321-
mPrinter->Print(common::producePropertyMap(mDescriptor->field(i), mDescriptor), Templates::SignalTemplate);
342+
const auto field = mDescriptor->field(i);
343+
mPrinter->Print(common::producePropertyMap(field, mDescriptor), Templates::SignalTemplate);
344+
345+
if (field->is_optional()) {
346+
mPrinter->Print(common::produceOptionalPropertyMap(field, mDescriptor), Templates::SignalTemplate);
347+
}
322348
}
323349
Outdent();
324350
}
@@ -331,6 +357,11 @@ void MessageDeclarationPrinter::printPrivateMethods()
331357
if (common::hasQmlAlias(field)) {
332358
mPrinter->Print(propertyMap, Templates::NonScriptableGetterTemplate);
333359
mPrinter->Print(propertyMap, Templates::NonScriptableSetterTemplate);
360+
if (field->is_optional()) {
361+
mPrinter->Print(propertyMap, Templates::EndOptionalSetterTemplate);
362+
} else {
363+
mPrinter->Print(propertyMap, Templates::EndSetterTemplate);
364+
}
334365
}
335366
});
336367
Outdent();
@@ -428,6 +459,9 @@ void MessageDeclarationPrinter::printClassMembers()
428459
} else {
429460
mPrinter->Print(propertyMap, Templates::MemberTemplate);
430461
}
462+
if (field->is_optional()) {
463+
mPrinter->Print(common::produceOptionalPropertyMap(field, mDescriptor), Templates::MemberTemplate);
464+
}
431465
});
432466
Outdent();
433467
}

src/generator/messagedefinitionprinter.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ void MessageDefinitionPrinter::printInitializationList(int fieldCount)
194194
}
195195
}
196196
}
197+
198+
if (field->is_optional()) {
199+
mPrinter->Print(common::produceOptionalPropertyMap(field, mDescriptor), Templates::PropertyDefaultInitializerTemplate);
200+
}
197201
}
198202
}
199203

@@ -372,16 +376,33 @@ void MessageDefinitionPrinter::printGetters()
372376
case FieldDescriptor::TYPE_MESSAGE:
373377
if (!field->is_map() && !field->is_repeated() && !common::isQtType(field)) {
374378
mPrinter->Print(propertyMap, Templates::SetterPrivateTemplateDefinitionMessageType);
379+
if (field->is_optional()) {
380+
mPrinter->Print(propertyMap, Templates::EndOptionalSetterTemplate);
381+
} else {
382+
mPrinter->Print(propertyMap, Templates::EndSetterTemplate);
383+
}
384+
375385
mPrinter->Print(propertyMap, Templates::SetterTemplateDefinitionMessageType);
376386
} else {
377387
mPrinter->Print(propertyMap, Templates::SetterTemplateDefinitionComplexType);
378388
}
389+
if (field->is_optional()) {
390+
mPrinter->Print(propertyMap, Templates::EndOptionalSetterTemplate);
391+
} else {
392+
mPrinter->Print(propertyMap, Templates::EndSetterTemplate);
393+
}
379394
break;
380395
case FieldDescriptor::FieldDescriptor::TYPE_STRING:
381396
case FieldDescriptor::FieldDescriptor::TYPE_BYTES:
382397
mPrinter->Print(propertyMap, Templates::SetterTemplateDefinitionComplexType);
398+
if (field->is_optional()) {
399+
mPrinter->Print(propertyMap, Templates::EndOptionalSetterTemplate);
400+
} else {
401+
mPrinter->Print(propertyMap, Templates::EndSetterTemplate);
402+
}
383403
break;
384404
default:
405+
mPrinter->Print(propertyMap, "/* default ending */");
385406
break;
386407
}
387408
});

src/generator/templates.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ const char *Templates::ProtoClassDeclarationBeginTemplate = "\nclass $classname$
8686
" Q_DECLARE_PROTOBUF_SERIALIZERS($classname$)\n";
8787

8888
const char *Templates::PropertyTemplate = "Q_PROPERTY($property_type$ $property_name$ READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE $scriptable$)\n";
89+
const char *Templates::ReadOnlyPropertyTemplate = "Q_PROPERTY($property_type$ $property_name$ READ $property_name$ NOTIFY $property_name$Changed SCRIPTABLE $scriptable$)\n";
8990
const char *Templates::RepeatedPropertyTemplate = "Q_PROPERTY($property_list_type$ $property_name$Data READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE $scriptable$)\n";
9091
const char *Templates::NonScriptablePropertyTemplate = "Q_PROPERTY($property_type$ $property_name$_p READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE false)\n";
9192
const char *Templates::NonScriptableAliasPropertyTemplate = "Q_PROPERTY($qml_alias_type$ $property_name$ READ $property_name$_p WRITE set$property_name_cap$_p NOTIFY $property_name$Changed SCRIPTABLE true)\n";
@@ -207,37 +208,40 @@ const char *Templates::SetterPrivateTemplateDefinitionMessageType = "void $class
207208
" if (m_$property_name$.get() != $property_name$) {\n"
208209
" m_$property_name$.reset($property_name$);\n"
209210
" $property_name$Changed();\n"
210-
" }\n"
211-
"}\n\n";
211+
" }\n";
212212

213213
const char *Templates::SetterTemplateDeclarationMessageType = "void set$property_name_cap$(const $setter_type$ &$property_name$);\n";
214214
const char *Templates::SetterTemplateDefinitionMessageType = "void $classname$::set$property_name_cap$(const $setter_type$ &$property_name$)\n{\n"
215215
" if (*m_$property_name$ != $property_name$) {\n"
216216
" *m_$property_name$ = $property_name$;\n"
217217
" $property_name$Changed();\n"
218-
" }\n"
219-
"}\n\n";
218+
" }\n";
220219

221220
const char *Templates::SetterTemplateDeclarationComplexType = "void set$property_name_cap$(const $setter_type$ &$property_name$);\n";
222221
const char *Templates::SetterTemplateDefinitionComplexType = "void $classname$::set$property_name_cap$(const $setter_type$ &$property_name$)\n{\n"
223222
" if (m_$property_name$ != $property_name$) {\n"
224223
" m_$property_name$ = $property_name$;\n"
225224
" $property_name$Changed();\n"
226-
" }\n"
227-
"}\n\n";
225+
" }\n";
228226

229227
const char *Templates::SetterTemplate = "void set$property_name_cap$(const $setter_type$ &$property_name$) {\n"
230228
" if (m_$property_name$ != $property_name$) {\n"
231229
" m_$property_name$ = $property_name$;\n"
232230
" $property_name$Changed();\n"
233-
" }\n"
234-
"}\n\n";
231+
" }\n";
235232
const char *Templates::NonScriptableSetterTemplate = "void set$property_name_cap$_p(const $qml_alias_type$ &$property_name$) {\n"
236233
" if (m_$property_name$ != $property_name$) {\n"
237234
" m_$property_name$ = $property_name$;\n"
238235
" $property_name$Changed();\n"
239-
" }\n"
240-
"}\n\n";
236+
" }\n";
237+
238+
const char *Templates::EndSetterTemplate = "}\n\n";
239+
240+
const char *Templates::EndOptionalSetterTemplate = " if (!m_has_$property_name$) {\n"
241+
" m_has_$property_name$ = true;\n"
242+
" Q_EMIT has_$property_name$Changed();\n"
243+
" }\n"
244+
"}\n\n";
241245

242246
const char *Templates::SignalsBlockTemplate = "\nsignals:\n";
243247
const char *Templates::SignalTemplate = "void $property_name$Changed();\n";

src/generator/templates.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class Templates {
6969
static const char *QObjectMacro;
7070

7171
static const char *PropertyTemplate;
72+
static const char *ReadOnlyPropertyTemplate;
7273
static const char *RepeatedPropertyTemplate;
7374
static const char *NonScriptablePropertyTemplate;
7475
static const char *NonScriptableAliasPropertyTemplate;
@@ -146,6 +147,8 @@ class Templates {
146147
static const char *SetterTemplateDefinitionComplexType;
147148
static const char *SetterTemplate;
148149
static const char *NonScriptableSetterTemplate;
150+
static const char *EndSetterTemplate;
151+
static const char *EndOptionalSetterTemplate;
149152
static const char *SignalsBlockTemplate;
150153
static const char *SignalTemplate;
151154
static const char *FieldsOrderingContainerTemplate;

0 commit comments

Comments
 (0)