From 3f0ecd1d0db1e989d534674da7235c6c3ffd4033 Mon Sep 17 00:00:00 2001
From: Jens Geyer
Date: Sat, 16 Nov 2024 10:40:55 +0100
Subject: [PATCH 1/2] THRIFT-5835 Allow exceptions to be used as regular struct
datatype Initial feature testcase added, compiler checks disabled. Patch:
Jens Geyer
---
compiler/cpp/src/thrift/parse/t_function.h | 6 +++
compiler/cpp/src/thrift/parse/t_list.h | 2 +
compiler/cpp/src/thrift/parse/t_map.h | 2 +
compiler/cpp/src/thrift/parse/t_set.h | 2 +
compiler/cpp/src/thrift/parse/t_struct.h | 6 ++-
compiler/cpp/src/thrift/parse/t_type.h | 3 ++
test/ExceptionStruct.thrift | 56 ++++++++++++++++++++++
7 files changed, 75 insertions(+), 2 deletions(-)
create mode 100644 test/ExceptionStruct.thrift
diff --git a/compiler/cpp/src/thrift/parse/t_function.h b/compiler/cpp/src/thrift/parse/t_function.h
index 57cf5ffce37..d2cb19bbc3a 100644
--- a/compiler/cpp/src/thrift/parse/t_function.h
+++ b/compiler/cpp/src/thrift/parse/t_function.h
@@ -85,17 +85,23 @@ class t_function : public t_doc {
void validate() const {
get_returntype()->validate();
+
+#ifndef ALLOW_EXCEPTIONS_AS_TYPE
if (get_returntype()->get_true_type()->is_xception()) {
failure("method %s(): exception type \"%s\" cannot be used as function return", get_name().c_str(), get_returntype()->get_name().c_str());
}
+#endif
std::vector::const_iterator it;
std::vector list = get_arglist()->get_members();
for(it=list.begin(); it != list.end(); ++it) {
(*it)->get_type()->validate();
+
+#ifndef ALLOW_EXCEPTIONS_AS_TYPE
if( (*it)->get_type()->get_true_type()->is_xception()) {
failure("method %s(): exception type \"%s\" cannot be used as function argument %s", get_name().c_str(), (*it)->get_type()->get_name().c_str(), (*it)->get_name().c_str());
}
+#endif
}
}
diff --git a/compiler/cpp/src/thrift/parse/t_list.h b/compiler/cpp/src/thrift/parse/t_list.h
index 5daa412bdcf..162281cc088 100644
--- a/compiler/cpp/src/thrift/parse/t_list.h
+++ b/compiler/cpp/src/thrift/parse/t_list.h
@@ -35,9 +35,11 @@ class t_list : public t_container {
bool is_list() const override { return true; }
void validate() const {
+#ifndef ALLOW_EXCEPTIONS_AS_TYPE
if( get_elem_type()->get_true_type()->is_xception()) {
failure("exception type \"%s\" cannot be used inside a list", get_elem_type()->get_name().c_str());
}
+#endif
}
private:
diff --git a/compiler/cpp/src/thrift/parse/t_map.h b/compiler/cpp/src/thrift/parse/t_map.h
index 444fca79800..30a8b06c9b9 100644
--- a/compiler/cpp/src/thrift/parse/t_map.h
+++ b/compiler/cpp/src/thrift/parse/t_map.h
@@ -38,12 +38,14 @@ class t_map : public t_container {
bool is_map() const override { return true; }
void validate() const {
+#ifndef ALLOW_EXCEPTIONS_AS_TYPE
if( get_key_type()->get_true_type()->is_xception()) {
failure("exception type \"%s\" cannot be used inside a map", get_key_type()->get_name().c_str());
}
if( get_val_type()->get_true_type()->is_xception()) {
failure("exception type \"%s\" cannot be used inside a map", get_val_type()->get_name().c_str());
}
+#endif
}
private:
diff --git a/compiler/cpp/src/thrift/parse/t_set.h b/compiler/cpp/src/thrift/parse/t_set.h
index 4a02dcc08ae..88de93f44c4 100644
--- a/compiler/cpp/src/thrift/parse/t_set.h
+++ b/compiler/cpp/src/thrift/parse/t_set.h
@@ -37,9 +37,11 @@ class t_set : public t_container {
bool is_set() const override { return true; }
void validate() const {
+#ifndef ALLOW_EXCEPTIONS_AS_TYPE
if( get_elem_type()->get_true_type()->is_xception()) {
failure("exception type \"%s\" cannot be used inside a set", get_elem_type()->get_name().c_str());
}
+#endif
}
private:
diff --git a/compiler/cpp/src/thrift/parse/t_struct.h b/compiler/cpp/src/thrift/parse/t_struct.h
index 941712d80ef..3aa67c0e16a 100644
--- a/compiler/cpp/src/thrift/parse/t_struct.h
+++ b/compiler/cpp/src/thrift/parse/t_struct.h
@@ -112,9 +112,8 @@ class t_struct : public t_type {
const members_type& get_sorted_members() const { return members_in_id_order_; }
bool is_struct() const override { return !is_xception_; }
-
bool is_xception() const override { return is_xception_; }
-
+ bool is_method_xcepts() const override { return is_method_xcepts_; }
bool is_union() const { return is_union_; }
t_field* get_field_by_name(std::string field_name) {
@@ -144,11 +143,14 @@ class t_struct : public t_type {
std::vector list = get_members();
for(it=list.begin(); it != list.end(); ++it) {
(*it)->get_type()->validate();
+
+#ifndef ALLOW_EXCEPTIONS_AS_TYPE
if (!is_method_xcepts_) { // this is in fact the only legal usage for any exception type
if( (*it)->get_type()->get_true_type()->is_xception()) {
failure("%s %s: exception type \"%s\" cannot be used as member field type %s", what.c_str(), get_name().c_str(), (*it)->get_type()->get_name().c_str(), (*it)->get_name().c_str());
}
}
+#endif
}
}
diff --git a/compiler/cpp/src/thrift/parse/t_type.h b/compiler/cpp/src/thrift/parse/t_type.h
index f4082426c8e..d087601aeca 100644
--- a/compiler/cpp/src/thrift/parse/t_type.h
+++ b/compiler/cpp/src/thrift/parse/t_type.h
@@ -26,6 +26,8 @@
#include
#include
+#define ALLOW_EXCEPTIONS_AS_TYPE
+
class t_program;
/**
@@ -54,6 +56,7 @@ class t_type : public t_doc {
virtual bool is_enum() const { return false; }
virtual bool is_struct() const { return false; }
virtual bool is_xception() const { return false; }
+ virtual bool is_method_xcepts() const { return false; }
virtual bool is_container() const { return false; }
virtual bool is_list() const { return false; }
virtual bool is_set() const { return false; }
diff --git a/test/ExceptionStruct.thrift b/test/ExceptionStruct.thrift
new file mode 100644
index 00000000000..b962209b3d1
--- /dev/null
+++ b/test/ExceptionStruct.thrift
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+namespace * test.ExceptionStruct
+
+enum ErrorCode {
+ GenericError,
+ ServerOverload,
+ InvalidData
+}
+
+struct GetRequest {
+ 1: string id
+ 2: binary data // some arbitrary data
+}
+
+struct GetResponse {
+ 1: i32 job_nr
+ 2: binary data // some arbitrary data
+}
+
+struct BatchGetRequest {
+ 1: list requests
+}
+
+struct BatchGetResponse {
+ 1: map responses, // key is id
+ 2: map errors, // key is id
+}
+
+exception SomeException {
+ 2: ErrorCode error
+}
+
+service Foo {
+ GetResponse get(1: GetRequest request) throws(1: SomeException error);
+ BatchGetResponse batchGet(1: BatchGetRequest request) throws(1: SomeException error); // may or may not be the same exception type, only throw exception when full request failed
+}
+
+# eof
From ffca732b87d3dc0c7faea07385c63d073ee6fc79 Mon Sep 17 00:00:00 2001
From: Jens Geyer
Date: Sat, 23 Nov 2024 01:01:13 +0100
Subject: [PATCH 2/2] THRIFT-5837 Delphi implementation for THRIFT-5835 Client:
Delphi Patch: Jens Geyer
---
.../src/thrift/generate/t_delphi_generator.cc | 984 ++++++++----------
lib/delphi/test/serializer/SerializerData.dpr | 19 +-
.../test/serializer/SerializerData.dproj | 33 +-
.../test/serializer/SimpleException.thrift | 32 +
.../test/serializer/TestSerializer.Data.pas | 49 +
.../test/serializer/TestSerializer.Tests.pas | 116 ++-
lib/delphi/test/serializer/TestSerializer.dpr | 2 +
.../test/serializer/TestSerializer.dproj | 28 +-
8 files changed, 652 insertions(+), 611 deletions(-)
create mode 100644 lib/delphi/test/serializer/SimpleException.thrift
diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
index 670383281f7..ca371f74935 100644
--- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
@@ -118,8 +118,7 @@ class t_delphi_generator : public t_oop_generator {
void generate_delphi_property(ostream& out,
bool struct_is_exception,
t_field* tfield,
- bool isPublic,
- std::string fieldPrefix = "");
+ bool isPublic);
void generate_delphi_isset_reader_writer_definition(ostream& out, t_field* tfield, bool is_xception);
void generate_delphi_property_reader_definition(ostream& out,
t_field* tfield,
@@ -141,9 +140,7 @@ class t_delphi_generator : public t_oop_generator {
t_field* tfield,
std::string fieldPrefix,
bool is_xception_class,
- bool is_union,
- bool is_xception_factory,
- std::string xception_factory_name);
+ bool is_union);
void generate_delphi_clear_union_value(ostream& out,
std::string cls_prefix,
std::string name,
@@ -151,40 +148,30 @@ class t_delphi_generator : public t_oop_generator {
t_field* tfield,
std::string fieldPrefix,
bool is_xception_class,
- bool is_union,
- bool is_xception_factory,
- std::string xception_factory_name);
+ bool is_union);
void generate_delphi_isset_reader_writer_impl(ostream& out,
- std::string cls_prefix,
- std::string name,
- t_type* type,
- t_field* tfield,
- std::string fieldPrefix,
- bool is_xception);
+ std::string cls_prefix,
+ std::string name,
+ t_type* type,
+ t_field* tfield,
+ std::string fieldPrefix,
+ bool is_xception_class);
void generate_delphi_struct_writer_impl(ostream& out,
std::string cls_prefix,
t_struct* tstruct,
- bool is_exception,
- bool is_x_factory);
- void generate_delphi_struct_result_writer_impl(ostream& out,
- std::string cls_prefix,
- t_struct* tstruct,
- bool is_exception,
- bool is_x_factory);
+ bool is_exception);
void generate_delphi_struct_tostring_impl(ostream& out,
std::string cls_prefix,
t_struct* tstruct,
- bool is_exception,
- bool is_x_factory);
+ bool is_exception);
void add_delphi_uses_list(string unitname);
void generate_delphi_struct_reader_impl(ostream& out,
std::string cls_prefix,
t_struct* tstruct,
- bool is_exception,
- bool is_x_factory);
+ bool is_exception);
void generate_delphi_create_exception_impl(ostream& out,
string cls_prefix,
t_struct* tstruct,
@@ -200,12 +187,14 @@ class t_delphi_generator : public t_oop_generator {
std::ostream& out,
std::string name,
t_type* type,
- t_const_value* value);
+ t_const_value* value,
+ bool is_const_class);
void initialize_field(std::ostream& vars,
std::ostream& out,
std::string name,
t_type* type,
- t_const_value* value);
+ t_const_value* value,
+ bool is_const_class);
void finalize_field(std::ostream& out,
std::string name,
t_type* type,
@@ -213,7 +202,6 @@ class t_delphi_generator : public t_oop_generator {
std::string cls_nm = "");
std::string render_const_value(std::ostream& local_vars,
std::ostream& out,
- std::string name,
t_type* type,
t_const_value* value,
bool guidAsLiteral);
@@ -225,32 +213,27 @@ class t_delphi_generator : public t_oop_generator {
std::string cls_nm = "");
std::string make_constants_classname();
- void generate_delphi_struct(t_struct* tstruct, bool is_exception);
+ void generate_delphi_struct(t_struct* tstruct);
+ void generate_delphi_exception(t_struct* tstruct);
void generate_delphi_struct_impl(ostream& out,
std::string cls_prefix,
t_struct* tstruct,
- bool is_exception,
- bool is_result = false,
- bool is_x_factory = false);
+ bool is_result,
+ bool is_const_class);
+ void generate_delphi_exception_impl(ostream& out,
+ std::string cls_prefix,
+ t_struct* tstruct);
void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct);
void generate_delphi_struct_type_factory(ostream& out,
std::string cls_prefix,
- t_struct* tstruct,
- bool is_exception,
- bool is_result = false,
- bool is_x_factory = false);
+ t_struct* tstruct);
void generate_delphi_struct_type_factory_registration(ostream& out,
std::string cls_prefix,
- t_struct* tstruct,
- bool is_exception,
- bool is_result = false,
- bool is_x_factory = false);
+ t_struct* tstruct);
void generate_delphi_struct_definition(std::ostream& out,
- t_struct* tstruct,
- bool is_xception = false,
- bool in_class = false,
- bool is_result = false,
- bool is_x_factory = false);
+ t_struct* tstruct);
+ void generate_delphi_exception_definition(std::ostream& out,
+ t_struct* tstruct);
void generate_function_helpers(t_function* tfunction);
void generate_service_interface(t_service* tservice);
@@ -327,9 +310,7 @@ class t_delphi_generator : public t_oop_generator {
std::string type_name(t_type* ttype,
bool b_cls = false,
- bool b_no_postfix = false,
- bool b_exception_factory = false,
- bool b_full_exception_factory = false);
+ bool b_no_postfix = false);
std::string normalize_clsnm(std::string name,
std::string prefix,
bool b_no_check_keyword = false);
@@ -339,7 +320,6 @@ class t_delphi_generator : public t_oop_generator {
std::string base_type_name(t_base_type* tbase);
std::string declare_field(t_field* tfield,
- bool init = false,
std::string prefix = "",
bool is_xception_class = false);
std::string function_signature(t_function* tfunction,
@@ -369,10 +349,7 @@ class t_delphi_generator : public t_oop_generator {
void generate_delphi_docstring_comment(std::ostream& out, string contents);
bool type_can_be_null(t_type* ttype) {
- while (ttype->is_typedef()) {
- ttype = ((t_typedef*)ttype)->get_type();
- }
-
+ ttype = ttype->get_true_type();
return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
}
@@ -426,10 +403,10 @@ class t_delphi_generator : public t_oop_generator {
};
// reserved exception class method names (lowercase!)
- const std::string DELPHI_RESERVED_METHOD_EXCEPTION[23] = {
+ const std::string DELPHI_RESERVED_METHOD_EXCEPTION[24] = {
"setinnerexception", "setstackinfo", "getstacktrace", "raisingexception", "createfmt", "createres",
"createresfmt", "createhelp", "createfmthelp", "createreshelp", "createresfmthelp", "getbaseexception",
- "baseexception", "helpcontext", "innerexception", "message", "stacktrace", "stackinfo",
+ "baseexception", "helpcontext", "innerexception", "exceptiondata", "message", "stacktrace", "stackinfo",
"getexceptionstackinfoproc", "getstackinfostringproc", "cleanupstackinfoproc", "raiseouterexception",
"throwouterexception"
};
@@ -830,11 +807,11 @@ void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) {
has_forward = true;
pdebug("forward declaration of %s\n", type_name(tstruct).c_str());
- string what = tstruct->is_xception() ? "class" : "interface";
-
indent_up();
- indent(s_forward_decr) << type_name(tstruct, tstruct->is_xception(), true) << " = " << what << ";"
- << '\n';
+ indent(s_forward_decr) << type_name(tstruct, false, true) << " = interface;" << '\n';
+ if( tstruct->is_xception()) {
+ indent(s_forward_decr) << type_name(tstruct, true, true) << " = class;" << '\n';
+ }
indent_down();
add_defined_type(tstruct);
@@ -1070,7 +1047,8 @@ void t_delphi_generator::generate_consts(std::vector consts) {
code,
prop_name((*c_iter)->get_name(), false, "F"),
(*c_iter)->get_type(),
- (*c_iter)->get_value());
+ (*c_iter)->get_value(),
+ true);
}
indent_down_impl();
@@ -1114,7 +1092,8 @@ void t_delphi_generator::generate_consts(std::vector consts) {
code,
constants_class + "." + prop_name((*c_iter)->get_name(), false, "F"),
(*c_iter)->get_type(),
- (*c_iter)->get_value());
+ (*c_iter)->get_value(),
+ true);
}
}
indent_down_impl();
@@ -1175,7 +1154,7 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars,
if (field_type == nullptr) {
throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
}
- string val = render_const_value(vars, out, name, field_type, v_iter->second, false);
+ string val = render_const_value(vars, out, field_type, v_iter->second, false);
indent_impl(out) << cls_prefix << normalize_name(name) << "."
<< prop_name(v_iter->first->get_string(), type->is_xception())
<< " := " << val << ";" << '\n';
@@ -1186,8 +1165,8 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars,
const map& val = value->get_map();
map::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
- string key = render_const_value(vars, out, name, ktype, v_iter->first, false);
- string val = render_const_value(vars, out, name, vtype, v_iter->second, false);
+ string key = render_const_value(vars, out, ktype, v_iter->first, false);
+ string val = render_const_value(vars, out, vtype, v_iter->second, false);
indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]"
<< " := " << val << ";" << '\n';
}
@@ -1202,7 +1181,7 @@ void t_delphi_generator::print_const_def_value(std::ostream& vars,
const vector& val = value->get_list();
vector::const_iterator v_iter;
for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
- string val = render_const_value(vars, out, name, etype, *v_iter, false);
+ string val = render_const_value(vars, out, etype, *v_iter, false);
indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << '\n';
}
}
@@ -1217,10 +1196,7 @@ void t_delphi_generator::print_private_field(std::ostream& out,
}
bool t_delphi_generator::const_needs_var(t_type* type) {
- t_type* truetype = type;
- while (truetype->is_typedef()) {
- truetype = ((t_typedef*)truetype)->get_type();
- }
+ t_type* truetype = type->get_true_type();
if(!truetype->is_base_type()) {
return true;
@@ -1247,7 +1223,7 @@ void t_delphi_generator::print_const_prop(std::ostream& out,
<< '\n';
} else {
std::ostringstream vars; // dummy
- string v2 = render_const_value(vars, out, name, type, value, true);
+ string v2 = render_const_value(vars, out, type, value, true);
indent(out) << "const " << name << " = " << v2 << ";" << '\n';
}
}
@@ -1256,23 +1232,20 @@ void t_delphi_generator::print_const_value(std::ostream& vars,
std::ostream& out,
string name,
t_type* type,
- t_const_value* value) {
- t_type* truetype = type;
- while (truetype->is_typedef()) {
- truetype = ((t_typedef*)truetype)->get_type();
- }
+ t_const_value* value,
+ bool is_const_class) {
+ t_type* truetype = type->get_true_type();
if (truetype->is_base_type()) {
- if(const_needs_var(type)) {
- string the_value = render_const_value( vars, out, name, type, value, false);
+ if(const_needs_var(type) || (!is_const_class)) {
+ string the_value = render_const_value( vars, out, type, value, false);
indent_impl(out) << name << " := " << the_value << ";" << '\n';
}
} else if (truetype->is_enum()) {
indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name()
<< ";" << '\n';
} else {
- string typname;
- typname = type_name(truetype, true, false, type->is_xception(), type->is_xception());
+ string typname = type_name(truetype, true, false/*, type->is_xception(), type->is_xception()*/);
indent_impl(out) << name << " := " << typname << ".Create;" << '\n';
print_const_def_value(vars, out, name, truetype, value);
}
@@ -1282,8 +1255,9 @@ void t_delphi_generator::initialize_field(std::ostream& vars,
std::ostream& out,
string name,
t_type* type,
- t_const_value* value) {
- print_const_value(vars, out, name, type, value);
+ t_const_value* value,
+ bool is_const_class) {
+ print_const_value(vars, out, name, type, value, is_const_class);
}
void t_delphi_generator::finalize_field(std::ostream& out,
@@ -1300,16 +1274,10 @@ void t_delphi_generator::finalize_field(std::ostream& out,
string t_delphi_generator::render_const_value(ostream& vars,
ostream& out,
- string name,
t_type* type,
t_const_value* value,
bool guidAsLiteral) {
- (void)name;
-
- t_type* truetype = type;
- while (truetype->is_typedef()) {
- truetype = ((t_typedef*)truetype)->get_type();
- }
+ t_type* truetype = type->get_true_type();
std::ostringstream render;
@@ -1360,7 +1328,7 @@ string t_delphi_generator::render_const_value(ostream& vars,
} else {
string t = tmp("tmp");
vars << " " << t << " : " << type_name(type) << ";" << '\n';
- print_const_value(vars, out, t, type, value);
+ print_const_value(vars, out, t, type, value, true);
render << t;
}
@@ -1368,54 +1336,53 @@ string t_delphi_generator::render_const_value(ostream& vars,
}
void t_delphi_generator::generate_struct(t_struct* tstruct) {
- generate_delphi_struct(tstruct, false);
+ generate_delphi_struct(tstruct);
}
void t_delphi_generator::generate_xception(t_struct* txception) {
- generate_delphi_struct(txception, true);
+ generate_delphi_exception(txception);
}
-void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) {
+void t_delphi_generator::generate_delphi_struct(t_struct* tstruct) {
indent_up();
- generate_delphi_struct_definition(s_struct, tstruct, is_exception);
+ generate_delphi_struct_definition(s_struct, tstruct);
indent_down();
add_defined_type(tstruct);
- generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception);
+ generate_delphi_struct_impl(s_struct_impl, "", tstruct, false, false/*?*/);
if (register_types_) {
- generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception);
- generate_delphi_struct_type_factory_registration(s_type_factory_registration,
- "",
- tstruct,
- is_exception);
+ generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct);
+ generate_delphi_struct_type_factory_registration(s_type_factory_registration, "", tstruct);
}
}
-void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
- string cls_prefix,
- t_struct* tstruct,
- bool is_exception,
- bool is_result,
- bool is_x_factory) {
-
- if (is_exception && (!is_x_factory)) {
- generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true);
- }
+void t_delphi_generator::generate_delphi_exception(t_struct* tstruct) {
+ // generate exception data class first
+ generate_delphi_struct(tstruct);
- string cls_nm;
+ indent_up();
+ generate_delphi_exception_definition(s_struct, tstruct);
+ indent_down();
- string exception_factory_name;
+ add_defined_type(tstruct);
- if (is_exception) {
- exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
+ generate_delphi_exception_impl(s_struct_impl, "", tstruct);
+ /*
+ if (register_types_) {
+ generate_delphi_exception_type_factory(s_type_factory_funcs, "", tstruct);
+ generate_delphi_exception_type_factory_registration(s_type_factory_registration, "", tstruct);
}
+ */
+}
- if (is_exception) {
- cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
- } else {
- cls_nm = type_name(tstruct, true, false);
- }
+void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
+ string cls_prefix,
+ t_struct* tstruct,
+ bool is_result,
+ bool is_const_class) {
+
+ string cls_nm = type_name(tstruct, true, false);
std::ostringstream vars, code;
@@ -1424,26 +1391,22 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
indent_up_impl();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- t_type* t = (*m_iter)->get_type();
- while (t->is_typedef()) {
- t = ((t_typedef*)t)->get_type();
- }
+ t_type* truetype = (*m_iter)->get_type()->get_true_type();
if ((*m_iter)->get_value() != nullptr) {
initialize_field(vars,
code,
- prop_name((*m_iter)->get_name(), is_exception, ""),
- t,
- (*m_iter)->get_value());
+ prop_name((*m_iter)->get_name(), false, "F"),
+ truetype,
+ (*m_iter)->get_value(),
+ is_const_class);
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
- indent_impl(code) << prop_name((*m_iter), is_exception, "F__isset_") << " := True;"
- << '\n';
+ indent_impl(code) << prop_name((*m_iter), false, "F__isset_") << " := True;" << '\n';
}
}
}
indent_down_impl();
- indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
- << "Create;" << '\n';
+ indent_impl(out) << "constructor " << cls_prefix << cls_nm << ".Create;" << '\n';
if (!vars.str().empty()) {
out << "var" << '\n';
@@ -1452,11 +1415,7 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
indent_impl(out) << "begin" << '\n';
indent_up_impl();
- if (is_exception && (!is_x_factory)) {
- indent_impl(out) << "inherited Create('');" << '\n';
- } else {
- indent_impl(out) << "inherited;" << '\n';
- }
+ indent_impl(out) << "inherited;" << '\n';
if (!code.str().empty()) {
out << code.str();
@@ -1465,82 +1424,25 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
indent_down_impl();
indent_impl(out) << "end;" << '\n' << '\n';
- if ((members.size() > 0) && is_exception && (!is_x_factory)) {
- indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
- << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");"
- << '\n';
- indent_impl(out) << "begin" << '\n';
- indent_up_impl();
- indent_impl(out) << "Create;" << '\n';
- for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- string propname = prop_name((*m_iter)->get_name(), is_exception);
- string param_name = constructor_param_name((*m_iter)->get_name());
- indent_impl(out) << propname << " := " << param_name << ";" << '\n';
- }
- indent_impl(out) << "UpdateMessageProperty;" << '\n';
- indent_down_impl();
- indent_impl(out) << "end;" << '\n' << '\n';
- }
-
- indent_impl(out) << "destructor " << cls_prefix << cls_nm << "."
- << "Destroy;" << '\n';
+ indent_impl(out) << "destructor " << cls_prefix << cls_nm << ".Destroy;" << '\n';
indent_impl(out) << "begin" << '\n';
indent_up_impl();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- t_type* t = (*m_iter)->get_type();
- while (t->is_typedef()) {
- t = ((t_typedef*)t)->get_type();
- }
- finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value());
+ t_type* t = (*m_iter)->get_type()->get_true_type();
+ finalize_field(out, prop_name(*m_iter, false), t, (*m_iter)->get_value());
}
indent_impl(out) << "inherited;" << '\n';
indent_down_impl();
indent_impl(out) << "end;" << '\n' << '\n';
- if (is_exception && (!is_x_factory)) {
- indent_impl(out) << "function " << cls_prefix << cls_nm << "." << exception_factory_name
- << ": I" << exception_factory_name << ";" << '\n';
- indent_impl(out) << "begin" << '\n';
- indent_up_impl();
- indent_impl(out) << "if F" << exception_factory_name << " = nil" << '\n';
- indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << '\n' << '\n';
- indent_impl(out) << "result := F" << exception_factory_name << ";" << '\n';
- indent_down_impl();
- indent_impl(out) << "end;" << '\n' << '\n';
- indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << '\n';
- indent_impl(out) << "begin" << '\n';
- indent_up_impl();
- indent_impl(out) << "if GetInterface(IID, Obj)" << '\n';
- indent_impl(out) << "then result := S_OK" << '\n';
- indent_impl(out) << "else result := E_NOINTERFACE;" << '\n';
- indent_down_impl();
- indent_impl(out) << "end;" << '\n' << '\n';
- indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << '\n';
- indent_impl(out) << "begin" << '\n';
- indent_up_impl();
- indent_impl(out) << "result := -1; // not refcounted" << '\n';
- indent_down_impl();
- indent_impl(out) << "end;" << '\n' << '\n';
- indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << '\n';
- indent_impl(out) << "begin" << '\n';
- indent_up_impl();
- indent_impl(out) << "result := -1; // not refcounted" << '\n';
- indent_down_impl();
- indent_impl(out) << "end;" << '\n' << '\n';
- }
-
if (tstruct->is_union()) {
- indent_impl(out) << "procedure " << cls_prefix << cls_nm << "."
- << "ClearUnionValues;" << '\n';
+ indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".ClearUnionValues;" << '\n';
indent_impl(out) << "begin" << '\n';
indent_up_impl();
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- t_type* t = (*m_iter)->get_type();
- while (t->is_typedef()) {
- t = ((t_typedef*)t)->get_type();
- }
+ t_type* t = (*m_iter)->get_type()->get_true_type();
generate_delphi_clear_union_value(out,
cls_prefix,
@@ -1548,47 +1450,138 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
t,
*m_iter,
"F",
- is_exception,
- tstruct->is_union(),
- is_x_factory,
- exception_factory_name);
+ false,
+ tstruct->is_union());
}
indent_down_impl();
indent_impl(out) << "end;" << '\n' << '\n';
}
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- t_type* t = (*m_iter)->get_type();
- while (t->is_typedef()) {
- t = ((t_typedef*)t)->get_type();
- }
- generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
+ t_type* t = (*m_iter)->get_type()->get_true_type();
+ generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", false);
generate_delphi_property_writer_impl(out,
cls_prefix,
cls_nm,
t,
*m_iter,
"F",
- is_exception,
- tstruct->is_union(),
- is_x_factory,
- exception_factory_name);
+ false,
+ tstruct->is_union());
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
- generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
+ generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", false);
}
}
- generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
- if (is_result) {
- generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
- } else {
- generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
+ generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, false);
+ generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, false);
+ generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, false);
+}
+
+void t_delphi_generator::generate_delphi_exception_impl(ostream& out,
+ string cls_prefix,
+ t_struct* tstruct) {
+
+ string cls_nm = type_name(tstruct, true, true/*, false, true*/);
+
+ const vector& members = tstruct->get_members();
+ vector::const_iterator m_iter;
+
+ indent_impl(out) << "constructor " << cls_prefix << cls_nm << ".Create;" << '\n';
+ indent_impl(out) << "begin" << '\n';
+ indent_up_impl();
+ indent_impl(out) << "inherited Create('');" << '\n';
+ indent_impl(out) << "FData := " << type_name(tstruct, true, false) << ".Create;" << '\n';
+ indent_down_impl();
+ indent_impl(out) << "end;" << '\n' << '\n';
+
+ if (members.size() > 0) {
+ indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
+ << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");"
+ << '\n';
+ indent_impl(out) << "begin" << '\n';
+ indent_up_impl();
+ indent_impl(out) << "Create;" << '\n';
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ string propname = prop_name((*m_iter)->get_name(), true);
+ string param_name = constructor_param_name((*m_iter)->get_name());
+ indent_impl(out) << propname << " := " << param_name << ";" << '\n';
+ }
+ indent_impl(out) << "UpdateMessageProperty;" << '\n';
+ indent_down_impl();
+ indent_impl(out) << "end;" << '\n' << '\n';
+ }
+
+ indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
+ << "Create(const aData: " << type_name(tstruct, false, false) << ");"
+ << '\n';
+ indent_impl(out) << "begin" << '\n';
+ indent_up_impl();
+ indent_impl(out) << "inherited Create('');" << '\n';
+ indent_impl(out) << "if aData <> nil" << '\n';
+ indent_impl(out) << "then FData := aData" << '\n';
+ indent_impl(out) << "else ASSERT(FALSE,'Invalid argument');" << '\n';
+ indent_impl(out) << "UpdateMessageProperty;" << '\n';
+ indent_down_impl();
+ indent_impl(out) << "end;" << '\n' << '\n';
+
+ indent_impl(out) << "destructor " << cls_prefix << cls_nm << "."
+ << "Destroy;" << '\n';
+ indent_impl(out) << "begin" << '\n';
+ indent_up_impl();
+
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ t_type* t = (*m_iter)->get_type()->get_true_type();
+ finalize_field(out, prop_name(*m_iter, true), t, (*m_iter)->get_value());
}
- generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
- if (is_exception && is_x_factory) {
- generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception);
+ indent_impl(out) << "inherited;" << '\n';
+ indent_down_impl();
+ indent_impl(out) << "end;" << '\n' << '\n';
+
+ // non-refcounted IUnknown impl
+ indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << '\n';
+ indent_impl(out) << "begin" << '\n';
+ indent_up_impl();
+ indent_impl(out) << "if GetInterface(IID, Obj)" << '\n';
+ indent_impl(out) << "then result := S_OK" << '\n';
+ indent_impl(out) << "else result := E_NOINTERFACE;" << '\n';
+ indent_down_impl();
+ indent_impl(out) << "end;" << '\n' << '\n';
+ indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << '\n';
+ indent_impl(out) << "begin" << '\n';
+ indent_up_impl();
+ indent_impl(out) << "result := -1; // not refcounted" << '\n';
+ indent_down_impl();
+ indent_impl(out) << "end;" << '\n' << '\n';
+ indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << '\n';
+ indent_impl(out) << "begin" << '\n';
+ indent_up_impl();
+ indent_impl(out) << "result := -1; // not refcounted" << '\n';
+ indent_down_impl();
+ indent_impl(out) << "end;" << '\n' << '\n';
+
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ t_type* t = (*m_iter)->get_type()->get_true_type();
+ generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "", true);
+ generate_delphi_property_writer_impl(out,
+ cls_prefix,
+ cls_nm,
+ t,
+ *m_iter,
+ "",
+ true,
+ tstruct->is_union());
+ if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+ generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "", true);
+ }
}
+
+ generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, true);
+ generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, true);
+ generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, true);
+
+ generate_delphi_create_exception_impl(out, cls_prefix, tstruct, true);
}
void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) {
@@ -1600,17 +1593,8 @@ void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_s
void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out,
string cls_prefix,
- t_struct* tstruct,
- bool is_exception,
- bool is_result,
- bool is_x_factory) {
+ t_struct* tstruct) {
(void)cls_prefix;
- if (is_exception)
- return;
- if (is_result)
- return;
- if (is_x_factory)
- return;
string struct_intf_name = type_name(tstruct);
string cls_nm = type_name(tstruct, true, false);
@@ -1629,17 +1613,8 @@ void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out,
void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out,
string cls_prefix,
- t_struct* tstruct,
- bool is_exception,
- bool is_result,
- bool is_x_factory) {
+ t_struct* tstruct) {
(void)cls_prefix;
- if (is_exception)
- return;
- if (is_result)
- return;
- if (is_x_factory)
- return;
string struct_intf_name = type_name(tstruct);
@@ -1649,12 +1624,8 @@ void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostrea
out << '\n';
}
-void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
- t_struct* tstruct,
- bool is_exception,
- bool in_class,
- bool is_result,
- bool is_x_factory) {
+void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
+ t_struct* tstruct) {
bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
string struct_intf_name;
string struct_name;
@@ -1662,121 +1633,77 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
const vector& members = tstruct->get_members();
vector::const_iterator m_iter;
- string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
-
- if (is_exception) {
- struct_intf_name = type_name(tstruct, false, false, true);
- } else {
- struct_intf_name = type_name(tstruct);
- }
+ struct_intf_name = type_name(tstruct, false, false);
+ struct_name = type_name(tstruct, true);
- if (is_exception) {
- struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory);
+ generate_delphi_doc(out, tstruct);
+ if(rtti_) {
+ indent(out) << "{$TYPEINFO ON}" << '\n';
+ indent(out) << "{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}" << '\n';
+ indent(out) << struct_intf_name << " = interface(IBaseWithTypeInfo)" << '\n';
} else {
- struct_name = type_name(tstruct, true);
+ indent(out) << struct_intf_name << " = interface(IBase)" << '\n';
}
+ indent_up();
- if ((!is_exception) || is_x_factory) {
-
- generate_delphi_doc(out, tstruct);
- if(rtti_) {
- indent(out) << "{$TYPEINFO ON}" << '\n';
- indent(out) << "{$RTTI EXPLICIT METHODS([vcPublic, vcPublished]) PROPERTIES([vcPublic, vcPublished])}" << '\n';
- indent(out) << struct_intf_name << " = interface(IBaseWithTypeInfo)" << '\n';
- } else {
- indent(out) << struct_intf_name << " = interface(IBase)" << '\n';
- }
- indent_up();
+ generate_guid(out);
- generate_guid(out);
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ generate_delphi_property_reader_definition(out, *m_iter, false);
+ generate_delphi_property_writer_definition(out, *m_iter, false);
+ }
+ if (members.size() > 0) {
+ out << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- generate_delphi_property_reader_definition(out, *m_iter, is_exception);
- generate_delphi_property_writer_definition(out, *m_iter, is_exception);
- }
-
- if (is_x_factory) {
- out << '\n';
- indent(out) << "// Create Exception Object" << '\n';
- indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << '\n';
- }
-
- if (members.size() > 0) {
- out << '\n';
- for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- generate_property(out, *m_iter, true, is_exception);
- }
+ generate_property(out, *m_iter, true, false);
}
- if (members.size() > 0) {
- out << '\n';
- for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
- generate_delphi_isset_reader_writer_definition(out, *m_iter, is_exception);
- }
+ out << '\n';
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+ generate_delphi_isset_reader_writer_definition(out, *m_iter, false);
}
}
- if (members.size() > 0) {
- out << '\n';
- for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
- isset_name = prop_name(*m_iter, is_exception, "__isset_");
- indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
- << '\n';
- }
+ out << '\n';
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+ isset_name = prop_name(*m_iter, false, "__isset_");
+ indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
+ << '\n';
}
}
+ }
- indent_down();
- indent(out) << "end;"
- << render_deprecation_attribute(tstruct->annotations_, " {", "}")
- << '\n';
- if(rtti_) {
- indent(out) << "{$IFNDEF TYPEINFO_WAS_ON} {$TYPEINFO OFF} {$ENDIF}" << '\n';
- }
- indent(out) << '\n';
+ indent_down();
+ indent(out) << "end;"
+ << render_deprecation_attribute(tstruct->annotations_, " {", "}")
+ << '\n';
+ if(rtti_) {
+ indent(out) << "{$IFNDEF TYPEINFO_WAS_ON} {$TYPEINFO OFF} {$ENDIF}" << '\n';
}
+ indent(out) << '\n';
generate_delphi_doc(out, tstruct);
indent(out) << struct_name << " = ";
if (is_final) {
out << "sealed ";
}
- out << "class(";
- if (is_exception && (!is_x_factory)) {
- out << "TException, IInterface, IBase, ISupportsToString";
- } else {
- out << "TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name;
- }
- out << ")" << '\n';
-
- if (is_exception && (!is_x_factory)) {
- indent(out) << "public" << '\n';
- indent_up();
- indent(out) << "type" << '\n';
- indent_up();
- generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true);
- indent_down();
- indent_down();
- }
+ out << "class(TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name << ")" << '\n';
indent(out) << "private" << '\n';
indent_up();
- if (is_exception && (!is_x_factory)) {
- indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << '\n' << '\n';
- }
-
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- indent(out) << declare_field(*m_iter, false, "F", is_exception) << '\n';
+ indent(out) << declare_field(*m_iter, "F", false) << '\n';
}
if (members.size() > 0) {
indent(out) << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
- isset_name = prop_name(*m_iter, is_exception, "F__isset_");
+ isset_name = prop_name(*m_iter, false, "F__isset_");
indent(out) << isset_name << ": System.Boolean;" << '\n';
}
}
@@ -1785,8 +1712,8 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
indent(out) << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- generate_delphi_property_reader_definition(out, *m_iter, is_exception);
- generate_delphi_property_writer_definition(out, *m_iter, is_exception);
+ generate_delphi_property_reader_definition(out, *m_iter, false);
+ generate_delphi_property_writer_definition(out, *m_iter, false);
}
if (tstruct->is_union()) {
@@ -1799,72 +1726,134 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
out << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
- isset_name = prop_name(*m_iter, is_exception, "__isset_");
+ isset_name = prop_name(*m_iter, false, "__isset_");
indent(out) << "function Get" << isset_name << ": System.Boolean;" << '\n';
indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << '\n';
}
}
}
- if (is_exception && (!is_x_factory)) {
+ indent_down();
+ indent(out) << "public" << '\n';
+ indent_up();
+ indent(out) << "constructor Create;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
+ indent(out) << "destructor Destroy; override;" << '\n';
+
+ out << '\n';
+ indent(out) << "function ToString: string; override;" << '\n';
+
+ out << '\n';
+ indent(out) << "// IBase" << '\n';
+ indent(out) << "procedure Read( const iprot: IProtocol);" << '\n';
+ indent(out) << "procedure Write( const oprot: IProtocol);" << '\n';
+
+ if (members.size() > 0) {
out << '\n';
- indent_down();
- indent(out) << "strict protected" << '\n';
- indent_up();
- indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << '\n';
- indent(out) << "function _AddRef: Integer; stdcall;" << '\n';
- indent(out) << "function _Release: Integer; stdcall;" << '\n';
+ indent(out) << "// Properties" << '\n';
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ generate_property(out, *m_iter, true, false);
+ }
+
out << '\n';
+ indent(out) << "// isset" << '\n';
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+ isset_name = prop_name(*m_iter, false, "__isset_");
+ indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
+ << '\n';
+ }
+ }
}
+ indent_down();
+ indent(out) << "end;" << '\n' << '\n';
+}
+
+void t_delphi_generator::generate_delphi_exception_definition(ostream& out,
+ t_struct* tstruct) {
+ bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
+ string struct_intf_name;
+ string struct_name;
+ string isset_name;
+ const vector& members = tstruct->get_members();
+ vector::const_iterator m_iter;
+
+ struct_intf_name = type_name(tstruct, false, false);
+ struct_name = type_name(tstruct, true, true);
+
+ generate_delphi_doc(out, tstruct);
+ indent(out) << struct_name << " = ";
+ if (is_final) {
+ out << "sealed ";
+ }
+ out << "class(TException, IInterface, IBase, ISupportsToString)" << '\n';
+
+ indent(out) << "private" << '\n';
+ indent_up();
+ indent(out) << "FData : " << struct_intf_name << ';' << '\n';
+ indent(out) << '\n';
+
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ generate_delphi_property_reader_definition(out, *m_iter, true);
+ generate_delphi_property_writer_definition(out, *m_iter, true);
+ }
+
+ if (members.size() > 0) {
+ out << '\n';
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
+ isset_name = prop_name(*m_iter, true, "__isset_");
+ indent(out) << "function Get" << isset_name << ": System.Boolean;" << '\n';
+ indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << '\n';
+ }
+ }
+ }
+
+ out << '\n';
+ indent_down();
+ indent(out) << "strict protected" << '\n';
+ indent_up();
+ indent(out) << "// non-refcounted instance" << '\n';
+ indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << '\n';
+ indent(out) << "function _AddRef: Integer; stdcall;" << '\n';
+ indent(out) << "function _Release: Integer; stdcall;" << '\n';
+ out << '\n';
+
indent_down();
indent(out) << "public" << '\n';
indent_up();
- if ((members.size() > 0) && is_exception && (!is_x_factory)) {
- indent(out) << "constructor Create; overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
+ indent(out) << "constructor Create; overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
+ if (members.size() > 0) {
indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent())
<< "); overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
- } else {
- indent(out) << "constructor Create;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
}
+ indent(out) << "constructor Create( const aData: " << struct_intf_name
+ << "); overload;" << render_deprecation_attribute(tstruct->annotations_," ",";") << '\n';
indent(out) << "destructor Destroy; override;" << '\n';
out << '\n';
+ indent(out) << "property ExceptionData : " << struct_intf_name << " read FData;" << '\n';
indent(out) << "function ToString: string; override;" << '\n';
- if (is_exception && (!is_x_factory)) {
- out << '\n';
- indent(out) << "// Exception Factory" << '\n';
- indent(out) << "function " << exception_factory_name << ": " << struct_intf_name << ";" << '\n';
- }
-
out << '\n';
indent(out) << "// IBase" << '\n';
indent(out) << "procedure Read( const iprot: IProtocol);" << '\n';
indent(out) << "procedure Write( const oprot: IProtocol);" << '\n';
- if (is_exception && is_x_factory) {
- out << '\n';
- indent(out) << "// Create Exception Object" << '\n';
- indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << '\n';
- }
-
if (members.size() > 0) {
out << '\n';
indent(out) << "// Properties" << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- generate_property(out, *m_iter, true, is_exception);
+ generate_property(out, *m_iter, true, true);
}
- }
- if (members.size() > 0) {
out << '\n';
indent(out) << "// isset" << '\n';
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
- isset_name = prop_name(*m_iter, is_exception, "__isset_");
+ isset_name = prop_name(*m_iter, true, "__isset_");
indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";"
<< '\n';
}
@@ -1957,11 +1946,11 @@ void t_delphi_generator::generate_service_helpers(t_service* tservice) {
for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
t_struct* ts = (*f_iter)->get_arglist();
- generate_delphi_struct_definition(s_service, ts, false, true);
+ generate_delphi_struct_definition(s_service, ts);
generate_delphi_struct_impl(s_service_impl,
normalize_clsnm(service_name_, "T") + ".",
ts,
- false);
+ false, false);
generate_function_helpers(*f_iter);
}
}
@@ -2076,7 +2065,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) {
// Delphi forces us to specify a type with IFuture, so we use Integer=0 for void methods
indent_impl(s_service_impl) << "result := TTask.Future(function: System.Integer" << '\n';
} else {
- string rettype = type_name(ttype, false, true, false, true);
+ string rettype = type_name(ttype, false, true/*, false, true*/);
indent_impl(s_service_impl) << "result := TTask.Future<" << rettype << ">(function: " << rettype << '\n';
}
indent_impl(s_service_impl) << "begin" << '\n';
@@ -2227,8 +2216,10 @@ void t_delphi_generator::generate_service_client(t_service* tservice) {
indent_impl(s_service_impl) << "if (" << retvar << "." << prop_name(*x_iter, false, "__isset_")
<< ") then begin" << '\n';
indent_up_impl();
- indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter)
- << ".CreateException;" << '\n';
+ indent_impl(s_service_impl) << exceptvar
+ << " := " << type_name((*x_iter)->get_type(),true,true/*,false,true*/)
+ << ".Create(" << retvar << "." << prop_name(*x_iter) << ");"
+ << '\n';
indent_impl(s_service_impl) << "raise " << exceptvar << ";" << '\n';
indent_down_impl();
indent_impl(s_service_impl) << "end;" << '\n';
@@ -2434,18 +2425,21 @@ void t_delphi_generator::generate_function_helpers(t_function* tfunction) {
result.append(&success);
}
+ int num_excepts = 0;
t_struct* xs = tfunction->get_xceptions();
const vector& fields = xs->get_members();
vector::const_iterator f_iter;
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
result.append(*f_iter);
+ ++num_excepts;
}
+ result.set_method_xcepts(num_excepts > 0);
- generate_delphi_struct_definition(s_service, &result, false, true, true);
+ generate_delphi_struct_definition(s_service, &result);
generate_delphi_struct_impl(s_service_impl,
normalize_clsnm(service_name_, "T") + ".",
&result,
- false);
+ true, false);
}
void t_delphi_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
@@ -2543,10 +2537,7 @@ void t_delphi_generator::generate_process_function(t_service* tservice, t_functi
<< " do begin" << '\n';
indent_up_impl();
if (!tfunction->is_oneway()) {
- string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(), "", true)
- + "Factory";
- indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E." << factory_name << ";"
- << '\n';
+ indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E.ExceptionData;" << '\n';
}
indent_down_impl();
indent_impl(s_service_impl) << "end;" << '\n';
@@ -2616,10 +2607,7 @@ void t_delphi_generator::generate_deserialize_field(ostream& out,
t_field* tfield,
string prefix,
ostream& local_vars) {
- t_type* type = tfield->get_type();
- while (type->is_typedef()) {
- type = ((t_typedef*)type)->get_type();
- }
+ t_type* type = tfield->get_type()->get_true_type();
if (type->is_void()) {
throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
@@ -2695,11 +2683,7 @@ void t_delphi_generator::generate_deserialize_struct(ostream& out,
string prefix) {
string typ_name;
- if (tstruct->is_xception()) {
- typ_name = type_name(tstruct, true, false, true, true);
- } else {
- typ_name = type_name(tstruct, true, false);
- }
+ typ_name = type_name(tstruct, true, false);
indent_impl(out) << prefix << name << " := " << typ_name << ".Create;" << '\n';
indent_impl(out) << prefix << name << ".Read(iprot);" << '\n';
@@ -2819,10 +2803,7 @@ void t_delphi_generator::generate_serialize_field(ostream& out,
ostream& local_vars) {
(void)local_vars;
- t_type* type = tfield->get_type();
- while (type->is_typedef()) {
- type = ((t_typedef*)type)->get_type();
- }
+ t_type* type = tfield->get_type()->get_true_type();
string name = prefix + prop_name(tfield, is_xception);
@@ -2999,22 +2980,21 @@ void t_delphi_generator::generate_property(ostream& out,
t_field* tfield,
bool isPublic,
bool is_xception) {
- generate_delphi_property(out, is_xception, tfield, isPublic, "Get");
+ generate_delphi_property(out, is_xception, tfield, isPublic);
}
void t_delphi_generator::generate_delphi_property(ostream& out,
bool struct_is_xception,
t_field* tfield,
- bool isPublic,
- std::string fieldPrefix) {
+ bool isPublic) {
(void)isPublic;
t_type* ftype = tfield->get_type();
bool is_xception = ftype->is_xception();
generate_delphi_doc(out, tfield);
indent(out) << "property " << prop_name(tfield, struct_is_xception) << ": "
- << type_name(ftype, false, true, is_xception, true)
- << " read " << prop_name(tfield, struct_is_xception, fieldPrefix)
+ << type_name(ftype, false, true/*, false, true*/)
+ << " read " << prop_name(tfield, struct_is_xception, "Get")
<< " write " << prop_name(tfield, struct_is_xception, "Set")
<< ";"
<< render_deprecation_attribute(tfield->annotations_, " {", "}")
@@ -3050,9 +3030,7 @@ string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_n
string t_delphi_generator::type_name(t_type* ttype,
bool b_cls,
- bool b_no_postfix,
- bool b_exception_factory,
- bool b_full_exception_factory) {
+ bool b_no_postfix) {
if (ttype->is_typedef()) {
t_typedef* tdef = (t_typedef*)ttype;
@@ -3060,9 +3038,7 @@ string t_delphi_generator::type_name(t_type* ttype,
if (tdef->get_type() != nullptr) {
return type_name(tdef->get_type(),
b_cls,
- b_no_postfix,
- b_exception_factory,
- b_full_exception_factory);
+ b_no_postfix);
} else {
throw "unresolved forward declaration: " + tdef->get_symbolic();
}
@@ -3117,20 +3093,12 @@ string t_delphi_generator::type_name(t_type* ttype,
string nm = normalize_clsnm(ttype->get_name(), type_prefix);
- if (b_exception_factory) {
- nm = normalize_clsnm(ttype->get_name(), type_prefix, true) + "Factory";
- }
-
if (b_cls) {
if (!b_no_postfix) {
nm = nm + "Impl";
}
}
- if (b_exception_factory && b_full_exception_factory) {
- return type_name(ttype, true, true, false, false) + "." + nm;
- }
-
return nm;
}
@@ -3217,16 +3185,14 @@ string t_delphi_generator::base_type_name(t_base_type* tbase) {
}
string t_delphi_generator::declare_field(t_field* tfield,
- bool init,
std::string prefix,
bool is_xception_class) {
- (void)init;
-
t_type* ftype = tfield->get_type();
bool is_xception = ftype->is_xception();
string result = prop_name(tfield, is_xception_class, prefix) + ": "
- + type_name(ftype, false, true, is_xception, true) + ";";
+ + type_name(ftype, false, true) + ";";
+
return result;
}
@@ -3251,7 +3217,7 @@ string t_delphi_generator::function_signature(t_function* tfunction,
} else {
signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async("
+ argument_list(tfunction->get_arglist()) + "): IFuture<"
- + type_name(ttype, false, true, is_xception, true) + ">;";
+ + type_name(ttype, false, true/*, is_xception, true*/) + ">;";
}
} else {
if (is_void(ttype)) {
@@ -3260,7 +3226,7 @@ string t_delphi_generator::function_signature(t_function* tfunction,
} else {
signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
+ argument_list(tfunction->get_arglist()) + "): "
- + type_name(ttype, false, true, is_xception, true) + ";";
+ + type_name(ttype, false, true/*, is_xception, true*/) + ";";
}
}
@@ -3289,7 +3255,7 @@ string t_delphi_generator::argument_list(t_struct* tstruct) {
tt = (*f_iter)->get_type();
result += input_arg_prefix(tt); // const?
result += normalize_name((*f_iter)->get_name()) + ": "
- + type_name(tt, false, true, tt->is_xception(), true);
+ + type_name(tt, false, true/*, tt->is_xception(), true*/);
}
return result;
}
@@ -3326,7 +3292,7 @@ string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string c
tt = (*f_iter)->get_type();
line += input_arg_prefix(tt); // const?
line += constructor_param_name((*f_iter)->get_name()) + ": "
- + type_name(tt, false, true, tt->is_xception(), true);
+ + type_name(tt, false, true/*, tt->is_xception(), true*/);
}
if (line.size() > 0) {
@@ -3345,9 +3311,7 @@ string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string c
}
string t_delphi_generator::type_to_enum(t_type* type) {
- while (type->is_typedef()) {
- type = ((t_typedef*)type)->get_type();
- }
+ type = type->get_true_type();
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -3387,9 +3351,7 @@ string t_delphi_generator::type_to_enum(t_type* type) {
}
string t_delphi_generator::empty_value(t_type* type) {
- while (type->is_typedef()) {
- type = ((t_typedef*)type)->get_type();
- }
+ type = type->get_true_type();
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
@@ -3436,7 +3398,7 @@ void t_delphi_generator::generate_delphi_property_writer_definition(ostream& out
bool is_xception = ftype->is_xception();
indent(out) << "procedure " << prop_name(tfield, is_xception_class, "Set")
- << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
+ << "( const Value: " << type_name(ftype, false, true/*, false, true*/) << ");"
<< render_deprecation_attribute(tfield->annotations_, " ", ";")
<< '\n';
}
@@ -3448,7 +3410,7 @@ void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out
bool is_xception = ftype->is_xception();
indent(out) << "function " << prop_name(tfield, is_xception_class, "Get") << ": "
- << type_name(ftype, false, true, is_xception, true) << ";"
+ << type_name(ftype, false, true/*, false*/) << ";"
<< render_deprecation_attribute(tfield->annotations_, " ", ";")
<< '\n';
}
@@ -3456,8 +3418,8 @@ void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out
void t_delphi_generator::generate_delphi_isset_reader_writer_definition(ostream& out,
t_field* tfield,
bool is_xception) {
- indent(out) << "function " << prop_name(tfield, is_xception,"Get__isset_") << ": System.Boolean;" << '\n';
- indent(out) << "procedure " << prop_name(tfield, is_xception, "Set__isset_") << "( const value : System.Boolean);" << '\n';
+ indent(out) << "function " << prop_name(tfield, false,"Get__isset_") << ": System.Boolean;" << '\n';
+ indent(out) << "procedure " << prop_name(tfield, false, "Set__isset_") << "( const value : System.Boolean);" << '\n';
}
void t_delphi_generator::generate_delphi_clear_union_value(ostream& out,
@@ -3467,25 +3429,20 @@ void t_delphi_generator::generate_delphi_clear_union_value(ostream& out,
t_field* tfield,
std::string fieldPrefix,
bool is_xception_class,
- bool is_union,
- bool is_xception_factory,
- std::string xception_factory_name) {
+ bool is_union) {
(void)cls_prefix;
(void)name;
(void)type;
(void)is_union;
- (void)is_xception_factory;
- (void)xception_factory_name;
t_type* ftype = tfield->get_type();
bool is_xception = ftype->is_xception();
- indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin"
- << '\n';
+ indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin" << '\n';
indent_up_impl();
indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := False;" << '\n';
indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := "
- << "Default( " << type_name(ftype, false, true, is_xception, true) << ");"
+ << "Default( " << type_name(ftype, false, true/*, is_xception, true*/) << ");"
<< '\n';
indent_down_impl();
indent_impl(out) << "end;" << '\n';
@@ -3498,9 +3455,7 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out,
t_field* tfield,
std::string fieldPrefix,
bool is_xception_class,
- bool is_union,
- bool is_xception_factory,
- std::string xception_factory_name) {
+ bool is_union) {
(void)type;
t_type* ftype = tfield->get_type();
@@ -3508,21 +3463,20 @@ void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out,
indent_impl(out) << "procedure " << cls_prefix << name << "."
<< prop_name(tfield, is_xception_class,"Set")
- << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
+ << "( const Value: " << type_name(ftype, false, true) << ");"
<< '\n';
indent_impl(out) << "begin" << '\n';
indent_up_impl();
if (is_union) {
indent_impl(out) << "ClearUnionValues;" << '\n';
}
- if (tfield->get_req() != t_field::T_REQUIRED) {
- indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := True;" << '\n';
- }
- indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := Value;" << '\n';
-
- if (is_xception_class && (!is_xception_factory)) {
- indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class)
- << " := Value;" << '\n';
+ if(is_xception_class) {
+ indent_impl(out) << "FData." << prop_name(tfield, false, fieldPrefix) << " := Value;" << '\n';
+ } else {
+ if (tfield->get_req() != t_field::T_REQUIRED) {
+ indent_impl(out) << prop_name(tfield, is_xception_class, "F__isset_") << " := True;" << '\n';
+ }
+ indent_impl(out) << prop_name(tfield, is_xception_class, fieldPrefix) << " := Value;" << '\n';
}
indent_down_impl();
@@ -3543,11 +3497,14 @@ void t_delphi_generator::generate_delphi_property_reader_impl(ostream& out,
indent_impl(out) << "function " << cls_prefix << name << "."
<< prop_name(tfield, is_xception_class,"Get") << ": "
- << type_name(ftype, false, true, is_xception, true) << ";" << '\n';
+ << type_name(ftype, false, true) << ";" << '\n';
indent_impl(out) << "begin" << '\n';
indent_up_impl();
- indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class,fieldPrefix) << ";"
- << '\n';
+ if(is_xception_class) {
+ indent_impl(out) << "Result := FData." << prop_name(tfield, false, fieldPrefix) << ";" << '\n';
+ } else {
+ indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class, fieldPrefix) << ";" << '\n';
+ }
indent_down_impl();
indent_impl(out) << "end;" << '\n' << '\n';
}
@@ -3558,16 +3515,20 @@ void t_delphi_generator::generate_delphi_isset_reader_writer_impl(ostream& out,
t_type* type,
t_field* tfield,
std::string fieldPrefix,
- bool is_xception) {
+ bool is_xception_class) {
(void)type;
- string isset_name = prop_name(tfield, is_xception, "__isset_");
+ string isset_name = prop_name(tfield, false, "__isset_");
indent_impl(out) << "function " << cls_prefix << name << "."
<< "Get" << isset_name << ": System.Boolean;" << '\n';
indent_impl(out) << "begin" << '\n';
indent_up_impl();
- indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << '\n';
+ if(is_xception_class) {
+ indent_impl(out) << "Result := FData." << fieldPrefix << isset_name << ";" << '\n';
+ } else {
+ indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << '\n';
+ }
indent_down_impl();
indent_impl(out) << "end;" << '\n' << '\n';
@@ -3575,7 +3536,11 @@ void t_delphi_generator::generate_delphi_isset_reader_writer_impl(ostream& out,
<< "Set" << isset_name << "( const value: System.Boolean);" << '\n';
indent_impl(out) << "begin" << '\n';
indent_up_impl();
- indent_impl(out) << fieldPrefix << isset_name << " := value;" << '\n';
+ if(is_xception_class) {
+ indent_impl(out) << "FData." << fieldPrefix << isset_name << " := value;" << '\n';
+ } else {
+ indent_impl(out) << fieldPrefix << isset_name << " := value;" << '\n';
+ }
indent_down_impl();
indent_impl(out) << "end;" << '\n' << '\n';
}
@@ -3587,47 +3552,13 @@ void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out,
(void)cls_prefix;
string exception_cls_nm = type_name(tstruct, true, true);
- string cls_nm = type_name(tstruct, true, false, is_exception, is_exception);
-
- indent_impl(out) << "function " << cls_nm << ".CreateException: " << exception_cls_nm << ";"
- << '\n';
-
- indent_impl(out) << "begin" << '\n';
- indent_up_impl();
-
- indent_impl(out) << "Result := " << exception_cls_nm << ".Create;" << '\n';
- string factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
- indent_impl(out) << "Result.F" << factory_name << " := Self;" << '\n';
-
- const vector& fields = tstruct->get_members();
- vector::const_iterator f_iter;
-
- string propname;
-
- for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
- propname = prop_name(*f_iter, is_exception);
- if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
- indent_impl(out) << "if " << prop_name(*f_iter, is_exception,"__isset_") << " then begin" << '\n';
- indent_up_impl();
- }
- indent_impl(out) << "Result." << propname << " := " << propname << ";" << '\n';
- if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
- indent_down_impl();
- indent_impl(out) << "end;" << '\n';
- }
- }
-
- indent_impl(out) << "Result.UpdateMessageProperty;" << '\n';
-
- indent_down_impl();
- indent_impl(out) << "end;" << '\n' << '\n';
+ string cls_nm = type_name(tstruct, true, false/*, is_exception, is_exception*/);
}
void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
string cls_prefix,
t_struct* tstruct,
- bool is_exception,
- bool is_x_factory) {
+ bool is_exception) {
ostringstream local_vars;
ostringstream code_block;
@@ -3746,7 +3677,7 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
}
}
- if( is_exception && (!is_x_factory)) {
+ if( is_exception) {
code_block << '\n';
indent_impl(code_block) << "UpdateMessageProperty;" << '\n';
}
@@ -3755,10 +3686,9 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
string cls_nm;
- cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory);
+ cls_nm = type_name(tstruct, true, is_exception);
- indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);"
- << '\n';
+ indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);" << '\n';
indent_impl(out) << "var" << '\n';
indent_up_impl();
indent_impl(out) << "field_ : TThriftField;" << '\n';
@@ -3768,76 +3698,10 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
out << code_block.str();
}
-void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out,
- string cls_prefix,
- t_struct* tstruct,
- bool is_exception,
- bool is_x_factory) {
-
- ostringstream local_vars;
- ostringstream code_block;
-
- string name = tstruct->get_name();
- const vector& fields = tstruct->get_sorted_members();
- vector::const_iterator f_iter;
-
- indent_impl(code_block) << "begin" << '\n';
- indent_up_impl();
-
- indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << '\n';
- indent_impl(code_block) << "tracker := oprot.NextRecursionLevel;" << '\n';
-
- indent_impl(code_block) << "Thrift.Protocol.Init( struc, '" << name << "');" << '\n';
- indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << '\n';
-
- if (fields.size() > 0) {
- indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << '\n';
- for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
- indent_impl(code_block) << "if (" << prop_name(*f_iter, is_exception,"__isset_") << ") then"
- << '\n';
- indent_impl(code_block) << "begin" << '\n';
- indent_up_impl();
- indent_impl(code_block) << "field_.Name := '" << (*f_iter)->get_name() << "';" << '\n';
- indent_impl(code_block) << "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";"
- << '\n';
- indent_impl(code_block) << "field_.ID := " << (*f_iter)->get_key() << ";" << '\n';
- indent_impl(code_block) << "oprot.WriteFieldBegin(field_);" << '\n';
- generate_serialize_field(code_block, is_exception, *f_iter, "Self.", local_vars);
- indent_impl(code_block) << "oprot.WriteFieldEnd();" << '\n';
- indent_down_impl();
- }
- }
-
- indent_impl(code_block) << "oprot.WriteFieldStop();" << '\n';
- indent_impl(code_block) << "oprot.WriteStructEnd();" << '\n';
-
- indent_down_impl();
- indent_impl(code_block) << "end;" << '\n' << '\n';
-
- string cls_nm;
-
- cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory);
-
- indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);"
- << '\n';
- indent_impl(out) << "var" << '\n';
- indent_up_impl();
- indent_impl(out) << "struc : TThriftStruct;" << '\n';
-
- if (fields.size() > 0) {
- indent_impl(out) << "field_ : TThriftField;" << '\n';
- }
-
- out << local_vars.str();
- indent_down_impl();
- out << code_block.str();
-}
-
void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out,
string cls_prefix,
t_struct* tstruct,
- bool is_exception,
- bool is_x_factory) {
+ bool is_exception) {
ostringstream local_vars;
ostringstream code_block;
@@ -3906,7 +3770,7 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out,
string cls_nm;
- cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory);
+ cls_nm = type_name(tstruct, true, is_exception);
indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);"
<< '\n';
@@ -3924,8 +3788,7 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out,
void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
string cls_prefix,
t_struct* tstruct,
- bool is_exception,
- bool is_x_factory) {
+ bool is_exception) {
const vector& fields = tstruct->get_members();
vector::const_iterator f_iter;
@@ -3933,7 +3796,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
string cls_nm;
if (is_exception) {
- cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
+ cls_nm = type_name(tstruct, true, true/*, false, true*/);
} else {
cls_nm = type_name(tstruct, true, false);
}
@@ -3998,10 +3861,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
<< '\n';
}
- t_type* ttype = (*f_iter)->get_type();
- while (ttype->is_typedef()) {
- ttype = ((t_typedef*)ttype)->get_type();
- }
+ t_type* ttype = (*f_iter)->get_type()->get_true_type();
if (ttype->is_xception() || ttype->is_struct()) {
indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " = nil) then " << tmp_sb
@@ -4009,7 +3869,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
<< prop_name((*f_iter), is_exception) << ".ToString());" << '\n';
} else if (ttype->is_enum()) {
indent_impl(out) << tmp_sb << ".Append(EnumUtils<"
- << type_name(ttype, false, true, false, false)
+ << type_name(ttype, false, true)
<< ">.ToString( System.Ord( Self."
<< prop_name((*f_iter), is_exception) << ")));" << '\n';
} else if (ttype->is_uuid()) {
@@ -4048,9 +3908,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
}
bool t_delphi_generator::is_void(t_type* type) {
- while (type->is_typedef()) {
- type = ((t_typedef*)type)->get_type();
- }
+ type = type->get_true_type();
if (type->is_base_type()) {
t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
diff --git a/lib/delphi/test/serializer/SerializerData.dpr b/lib/delphi/test/serializer/SerializerData.dpr
index 92ed00b0094..637e4ed9925 100644
--- a/lib/delphi/test/serializer/SerializerData.dpr
+++ b/lib/delphi/test/serializer/SerializerData.dpr
@@ -40,6 +40,8 @@ uses
Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
System_ in 'gen-delphi\System_.pas',
SysUtils_ in 'gen-delphi\SysUtils_.pas',
+ test.ExceptionStruct in 'gen-delphi\test.ExceptionStruct.pas',
+ test.SimpleException in 'gen-delphi\test.SimpleException.pas',
DebugProtoTest in 'gen-delphi\DebugProtoTest.pas',
TestSerializer.Data in 'TestSerializer.Data.pas';
@@ -69,11 +71,26 @@ begin
end;
+function CreateBatchGetResponse : IBatchGetResponse; stdcall;
+begin
+ result := Fixtures.CreateBatchGetResponse;
+end;
+
+
+function CreateSimpleException : IError; stdcall;
+begin
+ result := Fixtures.CreateSimpleException;
+end;
+
+
exports
CreateOneOfEach,
CreateNesting,
CreateHolyMoley,
- CreateCompactProtoTestStruct;
+ CreateCompactProtoTestStruct,
+ CreateBatchGetResponse,
+ CreateSimpleException;
+
begin
IsMultiThread := TRUE;
diff --git a/lib/delphi/test/serializer/SerializerData.dproj b/lib/delphi/test/serializer/SerializerData.dproj
index cfc27f8781d..cdad3120517 100644
--- a/lib/delphi/test/serializer/SerializerData.dproj
+++ b/lib/delphi/test/serializer/SerializerData.dproj
@@ -1,22 +1,4 @@
-
-
+
{B523D1D7-2C9A-4B39-A6CF-69EF536D5079}
SerializerData.dpr
@@ -85,6 +67,8 @@
+
+
@@ -100,10 +84,12 @@
-
+
-
+
Delphi.Personality.12
@@ -140,6 +126,9 @@ thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift]]>
SerializerData.dpr
+
+ bin\Debug\Win32\TestSerializer.exe
+
True
diff --git a/lib/delphi/test/serializer/SimpleException.thrift b/lib/delphi/test/serializer/SimpleException.thrift
new file mode 100644
index 00000000000..c13876c8d74
--- /dev/null
+++ b/lib/delphi/test/serializer/SimpleException.thrift
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+namespace * test.SimpleException
+
+exception Error {
+ 1: i32 ErrorCode = 42
+ /** test name collision with Exception class */
+ 2: Error InnerException
+ /** test name collisions with Thrift Delphi implementation details */
+ 3: uuid ExceptionData = '00000000-4444-CCCC-ffff-0123456789ab'
+}
+
+
+
+// EOF
diff --git a/lib/delphi/test/serializer/TestSerializer.Data.pas b/lib/delphi/test/serializer/TestSerializer.Data.pas
index 24f850d2f61..ddf4ba243eb 100644
--- a/lib/delphi/test/serializer/TestSerializer.Data.pas
+++ b/lib/delphi/test/serializer/TestSerializer.Data.pas
@@ -27,6 +27,8 @@ interface
ComObj,
Thrift.Protocol,
Thrift.Collections,
+ test.ExceptionStruct,
+ test.SimpleException,
DebugProtoTest;
@@ -37,6 +39,8 @@ Fixtures = class
class function CreateNesting : INesting;
class function CreateHolyMoley : IHolyMoley;
class function CreateCompactProtoTestStruct : ICompactProtoTestStruct;
+ class function CreateBatchGetResponse : IBatchGetResponse;
+ class function CreateSimpleException : IError;
// These byte arrays are serialized versions of the above structs.
// They were serialized in binary protocol using thrift 0.6.x and are used to
@@ -359,6 +363,51 @@ class function Fixtures.CreateCompactProtoTestStruct : ICompactProtoTestStruct;
end;
+class function Fixtures.CreateBatchGetResponse : IBatchGetResponse;
+var
+ data : IGetRequest;
+ error : ISomeException;
+const
+ REQUEST_ID = '123';
+begin
+ data := TGetRequestImpl.Create;
+ data.Id := REQUEST_ID;
+ data.Data := TThriftBytesImpl.Create( TEncoding.UTF8.GetBytes( #0#1#2#3#4#5#6#7#8));
+
+ error := TSomeExceptionImpl.Create;
+ error.Error := TErrorCode.GenericError;
+
+ result := TBatchGetResponseImpl.Create;
+ result.Responses := TThriftDictionaryImpl.Create;
+ result.Responses.Add( REQUEST_ID, data);
+ result.Errors := TThriftDictionaryImpl.Create;
+ result.Errors.Add( REQUEST_ID, error);
+end;
+
+
+class function Fixtures.CreateSimpleException : IError;
+var i : Integer;
+ inner : IError;
+ guid : TGuid;
+const
+ IDL_GUID_VALUE : TGuid = '{00000000-4444-CCCC-ffff-0123456789ab}';
+begin
+ result := nil;
+ for i := 0 to 4 do begin
+ inner := result;
+ result := TErrorImpl.Create;
+
+ // validate const values set in IDL
+ ASSERT( result.ErrorCode = 42); // IDL default value
+ ASSERT( IsEqualGUID( result.ExceptionData, IDL_GUID_VALUE));
+
+ // set fresh, but reproducible values
+ FillChar( guid, SizeOf(guid), i);
+ result.ErrorCode := i;
+ result.ExceptionData := guid;
+ result.InnerException := inner;
+ end;
+end;
end.
diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas
index e6a309e6861..466fb269efc 100644
--- a/lib/delphi/test/serializer/TestSerializer.Tests.pas
+++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas
@@ -41,6 +41,8 @@ interface
Thrift.WinHTTP,
Thrift.TypeRegistry,
System_,
+ test.ExceptionStruct,
+ test.SimpleException,
DebugProtoTest;
{$TYPEINFO ON}
@@ -82,8 +84,11 @@ TTestSerializer = class //extends TestCase {
procedure Test_Serializer_Deserializer;
procedure Test_COM_Types;
procedure Test_ThriftBytesCTORs;
- procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
- procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+
+ procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+ procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+ procedure Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+ procedure Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
public
constructor Create;
@@ -100,6 +105,8 @@ function CreateOneOfEach : IOneOfEach; stdcall; external SERIALIZERDATA_DLL;
function CreateNesting : INesting; stdcall; external SERIALIZERDATA_DLL;
function CreateHolyMoley : IHolyMoley; stdcall; external SERIALIZERDATA_DLL;
function CreateCompactProtoTestStruct : ICompactProtoTestStruct; stdcall; external SERIALIZERDATA_DLL;
+function CreateBatchGetResponse : IBatchGetResponse; stdcall; external SERIALIZERDATA_DLL;
+function CreateSimpleException : IError; stdcall; external SERIALIZERDATA_DLL;
{ TTestSerializer }
@@ -266,6 +273,105 @@ procedure TTestSerializer.Test_CompactStruct( const method : TMethod; const fact
end;
+procedure TTestSerializer.Test_ExceptionStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+var tested, correct : IBatchGetResponse;
+ bytes : TBytes;
+ corrDP, testDP : TPair;
+ corrEP, testEP : TPair;
+begin
+ // write
+ tested := CreateBatchGetResponse;
+ case method of
+ mt_Bytes: bytes := Serialize( tested, factory);
+ mt_Stream: begin
+ stream.Size := 0;
+ Serialize( tested, factory, stream);
+ end
+ else
+ ASSERT( FALSE);
+ end;
+
+ // init + read
+ correct := TBatchGetResponseImpl.Create;
+ case method of
+ mt_Bytes: Deserialize( bytes, tested, factory);
+ mt_Stream: begin
+ stream.Position := 0;
+ Deserialize( stream, tested, factory);
+ end
+ else
+ ASSERT( FALSE);
+ end;
+
+ // check
+ correct := CreateBatchGetResponse;
+
+ // rewrite the following test if not
+ ASSERT( tested.Responses.Count = 1);
+ ASSERT( correct.Responses.Count = tested.Responses.Count);
+ for corrDP in correct.Responses do begin
+ for testDP in tested.Responses do begin
+ ASSERT( corrDP.Key = testDP.Key);
+ ASSERT( corrDP.Value.Id = testDP.Value.Id);
+ ASSERT( corrDP.Value.Data.Count = testDP.Value.Data.Count);
+ end;
+ end;
+
+ // rewrite the following test if not
+ ASSERT( tested.Errors.Count = 1);
+ ASSERT( correct.Errors.Count = tested.Errors.Count);
+ for corrEP in correct.Errors do begin
+ for testEP in tested.Errors do begin
+ ASSERT( corrEP.Key = testEP.Key);
+ ASSERT( corrEP.Value.Error = testEP.Value.Error);
+ end;
+ end;
+end;
+
+
+procedure TTestSerializer.Test_SimpleException( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream);
+var tested, correct : IError;
+ bytes : TBytes;
+begin
+ // write
+ tested := CreateSimpleException;
+ case method of
+ mt_Bytes: bytes := Serialize( tested, factory);
+ mt_Stream: begin
+ stream.Size := 0;
+ Serialize( tested, factory, stream);
+ end
+ else
+ ASSERT( FALSE);
+ end;
+
+ // init + read
+ correct := TErrorImpl.Create;
+ case method of
+ mt_Bytes: Deserialize( bytes, tested, factory);
+ mt_Stream: begin
+ stream.Position := 0;
+ Deserialize( stream, tested, factory);
+ end
+ else
+ ASSERT( FALSE);
+ end;
+
+ // check
+ correct := CreateSimpleException;
+ while correct <> nil do begin
+ // validate
+ ASSERT( correct.ErrorCode = tested.ErrorCode);
+ ASSERT( IsEqualGUID( correct.ExceptionData, tested.ExceptionData));
+
+ // iterate
+ correct := correct.InnerException;
+ tested := tested.InnerException;
+ ASSERT( (tested <> nil) xor (correct = nil)); // both or none
+ end;
+end;
+
+
procedure TTestSerializer.Test_Serializer_Deserializer;
var factory : TFactoryPair;
stream : TFileStream;
@@ -279,8 +385,10 @@ procedure TTestSerializer.Test_Serializer_Deserializer;
for factory in FProtocols do begin
Writeln('- '+UserFriendlyName(factory));
- Test_OneOfEach( method, factory, stream);
- Test_CompactStruct( method, factory, stream);
+ Test_OneOfEach( method, factory, stream);
+ Test_CompactStruct( method, factory, stream);
+ Test_ExceptionStruct( method, factory, stream);
+ Test_SimpleException( method, factory, stream);
end;
Writeln;
diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr
index b78c0db05d9..8c2f64d9e10 100644
--- a/lib/delphi/test/serializer/TestSerializer.dpr
+++ b/lib/delphi/test/serializer/TestSerializer.dpr
@@ -44,6 +44,8 @@ uses
System_ in 'gen-delphi\System_.pas',
SysUtils_ in 'gen-delphi\SysUtils_.pas',
DebugProtoTest in 'gen-delphi\DebugProtoTest.pas',
+ test.ExceptionStruct in 'gen-delphi\test.ExceptionStruct.pas',
+ test.SimpleException in 'gen-delphi\test.SimpleException.pas',
TestSerializer.Tests in 'TestSerializer.Tests.pas';
diff --git a/lib/delphi/test/serializer/TestSerializer.dproj b/lib/delphi/test/serializer/TestSerializer.dproj
index 383e04a9547..5ea2b796adc 100644
--- a/lib/delphi/test/serializer/TestSerializer.dproj
+++ b/lib/delphi/test/serializer/TestSerializer.dproj
@@ -1,22 +1,4 @@
-
-
+
{9282EDD8-7C12-41B0-8172-61C6BFA6E238}
TestSerializer.dpr
@@ -85,6 +67,8 @@
+
+
Cfg_2
@@ -99,10 +83,12 @@
-
+
+thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift
+thrift.exe -r -gen delphi:com_types ..\..\..\..\test\ExceptionStruct.thrift
+thrift.exe -r -gen delphi:com_types SimpleException.thrift]]>
Delphi.Personality.12