Skip to content

Commit ac9b849

Browse files
authored
Merge pull request #198 from sempare/add_interface_support
Add interface support
2 parents 015b43a + 39509b8 commit ac9b849

File tree

6 files changed

+83
-8
lines changed

6 files changed

+83
-8
lines changed

.github/workflows/delphi-package.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
run: Sempare.Template.Tester.exe -cm:quiet -exit:continue -b -xmlfile:.\results.xml
3131

3232
- name: publish win32 debug test results
33-
uses: actions/upload-artifact@v2
33+
uses: actions/upload-artifact@v4
3434
with:
3535
name: Win32 Debug Results
3636
path: './Win32/Debug/results.xml'
@@ -53,7 +53,7 @@ jobs:
5353
run: Sempare.Template.Tester.exe -cm:quiet -exit:continue -b -xmlfile:.\results.xml
5454

5555
- name: publish win32 release test results
56-
uses: actions/upload-artifact@v2
56+
uses: actions/upload-artifact@v4
5757
with:
5858
name: Win32 Release Results
5959
path: './Win32/Release/results.xml'
@@ -75,7 +75,7 @@ jobs:
7575
run: Sempare.Template.Tester.exe -cm:quiet -exit:continue -b -xmlfile:.\results.xml
7676

7777
- name: publish win64 debug test results
78-
uses: actions/upload-artifact@v2
78+
uses: actions/upload-artifact@v4
7979
with:
8080
name: Win64 Debug Results
8181
path: './Win64/Debug/results.xml'
@@ -97,7 +97,7 @@ jobs:
9797
run: Sempare.Template.Tester.exe -cm:quiet -exit:continue -b -xmlfile:.\results.xml
9898

9999
- name: publish win64 release test results
100-
uses: actions/upload-artifact@v2
100+
uses: actions/upload-artifact@v4
101101
with:
102102
name: Win64 Release Results
103103
path: './Win64/Release/results.xml'

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
![delphi compatibility](https://img.shields.io/badge/delphi%20compatability-XE%204%20or%20newer-brightgreen)
22
![platform compatibility](https://img.shields.io/badge/platform-Android32%20%7C%20Android64%20%7C%20Linux64%20%7C%20macOS64%20%7C%20Win32%20%7C%20Win64-lightgrey)
3-
![license](https://img.shields.io/github/license/sempare/sempare-delphi-template-engine)
43

54
# ![](./images/sempare-logo-45px.png) Sempare Template Engine
65

@@ -12,6 +11,8 @@ License: [GPL v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html) or [Sempare Li
1211

1312
Open Source: https://github.com/sempare/sempare-delphi-template-engine
1413

14+
*Questionaire*: https://docs.google.com/forms/d/e/1FAIpQLScioIiDxvsWK01fMFqYr9aJ6KhCGeiw4UaU_esGuztEE7vYwA/viewform
15+
1516
## Contents
1617
- [Introduction](#Introduction)
1718
- [Call To Action](#CallToAction)

src/Sempare.Template.Evaluate.pas

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,12 +1112,24 @@ function TEvaluationTemplateVisitor.Invoke(const AExpr: IMethodCallExpr; const A
11121112
LObjType: TRttiType;
11131113
LObject: TValue;
11141114
LMethod: TRttiMethod;
1115+
LIntf: IInterface;
11151116
begin
11161117
LObjType := FContext.RttiContext().GetType(AObject.TypeInfo);
11171118
LMethod := LObjType.GetMethod(AExpr.Method);
11181119
LObject := AObject;
1119-
if AObject.IsType<TValue> then
1120-
LObject := AObject.AsType<TValue>;
1120+
if LObject.Kind = tkInterface then
1121+
begin
1122+
LIntf := LObject.AsInterface;
1123+
LObject := TObject(LIntf);
1124+
LObjType := FContext.RttiContext.GetType(LObject.TypeInfo);
1125+
end
1126+
else
1127+
begin
1128+
if AObject.IsType<TValue> then
1129+
LObject := AObject.AsType<TValue>;
1130+
end;
1131+
LMethod := LObjType.GetMethod(AExpr.Method);
1132+
11211133
exit(DoInvoke(AExpr, LMethod, LObject, AArgs, AHasResult));
11221134
end;
11231135

src/Sempare.Template.Rtti.pas

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ function TryDeref(const APosition: IPosition; const AVar, ADeref: TValue; const
915915
var
916916
LFunctionPair: TPair<TDerefMatchInterfaceFunction, TDerefFunction>;
917917
LIntf: IInterface;
918+
LProperty: TRttiProperty;
919+
LType: TRttiType;
918920
begin
919921
LIntf := AObj.AsInterface;
920922
for LFunctionPair in GDerefInterfaceFunctions do
@@ -925,10 +927,14 @@ function TryDeref(const APosition: IPosition; const AVar, ADeref: TValue; const
925927
exit(true);
926928
end;
927929
end;
930+
LType := AContext.RttiContext.GetType(AObj.TypeInfo);
931+
LProperty := LType.GetProperty(ADeref.AsString);
932+
if assigned(LProperty) then
933+
AResult := LProperty.GetValue(AObj.AsType<pointer>);
928934
exit(ExitEmpty(AResult));
929935
end;
930936

931-
function FixTValue(var AValue: TValue; const AResult:boolean=true): boolean;
937+
function FixTValue(var AValue: TValue; const AResult: boolean = true): boolean;
932938
begin
933939
if (AValue.Kind = tkRecord) and MatchValue(AValue.TypeInfo) then
934940
begin

tests/Sempare.Template.TestDeref.pas

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ TTestTemplateDeref = class
5454
procedure TestDerefError;
5555
[Test]
5656
procedure TestDerefNull;
57+
58+
[Test]
59+
procedure TestIntfProperty;
60+
61+
[Test]
62+
procedure TestIntfMethod;
5763
end;
5864

5965
TNullable = class
@@ -62,13 +68,30 @@ TNullable = class
6268
Other: TNullable;
6369
end;
6470

71+
ITestData = interface
72+
['{7F66CDA3-3C98-41AF-A762-8B48FEBF8700}']
73+
function GetData: string;
74+
property Data: string read GetData;
75+
end;
76+
77+
TTestData = class(TInterfacedObject, ITestData)
78+
function GetData: string;
79+
end;
80+
6581
implementation
6682

6783
uses
84+
System.Rtti,
6885
System.SysUtils,
6986
Sempare.Template.Context,
7087
Sempare.Template;
7188

89+
{ TTestData }
90+
function TTestData.GetData: string;
91+
begin
92+
exit('hello');
93+
end;
94+
7295
{ TTestTemplateDeref }
7396

7497
procedure TTestTemplateDeref.Test<T>(const AValue: T; const AExpect: string; const ATemplate: string);
@@ -129,6 +152,28 @@ procedure TTestTemplateDeref.TestExprDrefef;
129152
Test(rec, '''before 123 after ''', '''before <% suffix := ''def'' %> <% a.b[''abc'' + suffix] %> after ''');
130153
end;
131154

155+
procedure TTestTemplateDeref.TestIntfMethod;
156+
var
157+
LIntf: ITestData;
158+
begin
159+
LIntf := TTestData.Create;
160+
161+
Assert.AreEqual('hello', Template.Eval('<% _.GetData() %>', TValue.From<ITestData>(LIntf)));
162+
163+
end;
164+
165+
procedure TTestTemplateDeref.TestIntfProperty;
166+
var
167+
LIntf: ITestData;
168+
begin
169+
LIntf := TTestData.Create;
170+
Assert.WillRaise(
171+
procedure
172+
begin
173+
Assert.AreEqual('hello', Template.Eval('<% _.data %>', TValue.From<ITestData>(LIntf)));
174+
end);
175+
end;
176+
132177
procedure TTestTemplateDeref.TestSimpleDrefef;
133178
begin
134179
Assert.IsNotNull(Template.parse('before <% a.b %> after '));

tests/Sempare.Template.TestInclude.pas

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ TTestTemplateInclude = class
102102
[Test]
103103
procedure TestFunctionalInclude;
104104

105+
[Test]
106+
procedure TestVariableAfterInclude;
107+
105108
end;
106109

107110
implementation
@@ -242,6 +245,14 @@ TMember = record
242245
Assert.AreEqual('Parent'#13#10'Child', Template.Eval(LTpl, LMember));
243246
end;
244247

248+
procedure TTestTemplateInclude.TestVariableAfterInclude;
249+
var
250+
LResult: string;
251+
begin
252+
LResult := Template.Eval('<% template "my_template" %><% _.var %><% end %><% var := 345 %><% my_template { "var"= 123 } %> <% var %>');
253+
Assert.AreEqual('123 345', LResult);
254+
end;
255+
245256
procedure TTestTemplateInclude.TestFunctionalInclude;
246257
var
247258
LResult: string;

0 commit comments

Comments
 (0)