Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

THRIFT-5837 Delphi implementation for THRIFT-5835 #3068

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
984 changes: 421 additions & 563 deletions compiler/cpp/src/thrift/generate/t_delphi_generator.cc

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions compiler/cpp/src/thrift/parse/t_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<t_field*>::const_iterator it;
std::vector<t_field*> 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
}
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/cpp/src/thrift/parse/t_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions compiler/cpp/src/thrift/parse/t_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions compiler/cpp/src/thrift/parse/t_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
6 changes: 4 additions & 2 deletions compiler/cpp/src/thrift/parse/t_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -144,11 +143,14 @@ class t_struct : public t_type {
std::vector<t_field*> 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
}
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/cpp/src/thrift/parse/t_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <stdint.h>
#include <string>

#define ALLOW_EXCEPTIONS_AS_TYPE

class t_program;

/**
Expand Down Expand Up @@ -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; }
Expand Down
19 changes: 18 additions & 1 deletion lib/delphi/test/serializer/SerializerData.dpr
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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;
Expand Down
33 changes: 11 additions & 22 deletions lib/delphi/test/serializer/SerializerData.dproj
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
<!--
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.
-->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{B523D1D7-2C9A-4B39-A6CF-69EF536D5079}</ProjectGuid>
<MainSource>SerializerData.dpr</MainSource>
Expand Down Expand Up @@ -85,6 +67,8 @@
<DCCReference Include="..\..\src\Thrift.TypeRegistry.pas"/>
<DCCReference Include="gen-delphi\System_.pas"/>
<DCCReference Include="gen-delphi\SysUtils_.pas"/>
<DCCReference Include="gen-delphi\test.ExceptionStruct.pas"/>
<DCCReference Include="gen-delphi\test.SimpleException.pas"/>
<DCCReference Include="gen-delphi\DebugProtoTest.pas"/>
<DCCReference Include="TestSerializer.Data.pas"/>
<BuildConfiguration Include="Release">
Expand All @@ -100,10 +84,12 @@
</BuildConfiguration>
</ItemGroup>
<Import Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')" Project="$(BDS)\Bin\CodeGear.Delphi.Targets"/>
<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj"/>
<Import Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\8.0\UserTools.proj')" Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\8.0\UserTools.proj"/>
<PropertyGroup>
<PreBuildEvent><![CDATA[thrift.exe -r -gen delphi:com_types ..\keywords\ReservedKeywords.thrift
thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift]]></PreBuildEvent>
<PreBuildEvent><![CDATA[thrift.exe -r -gen delphi:com_types,rtti ..\keywords\ReservedKeywords.thrift
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]]></PreBuildEvent>
</PropertyGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
Expand Down Expand Up @@ -140,6 +126,9 @@ thrift.exe -r -gen delphi:com_types ..\..\..\..\test\DebugProtoTest.thrift]]></P
<Source>
<Source Name="MainSource">SerializerData.dpr</Source>
</Source>
<Parameters>
<Parameters Name="HostApplication">bin\Debug\Win32\TestSerializer.exe</Parameters>
</Parameters>
</Delphi.Personality>
<Platforms>
<Platform value="Win32">True</Platform>
Expand Down
32 changes: 32 additions & 0 deletions lib/delphi/test/serializer/SimpleException.thrift
Original file line number Diff line number Diff line change
@@ -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
49 changes: 49 additions & 0 deletions lib/delphi/test/serializer/TestSerializer.Data.pas
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ interface
ComObj,
Thrift.Protocol,
Thrift.Collections,
test.ExceptionStruct,
test.SimpleException,
DebugProtoTest;


Expand All @@ -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
Expand Down Expand Up @@ -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<WideString, IGetRequest>.Create;
result.Responses.Add( REQUEST_ID, data);
result.Errors := TThriftDictionaryImpl<WideString, ISomeException>.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.
Expand Down
Loading
Loading