function RegisterMeasure(MeasureName: String): TMeasure;
procedure UnregisterMeasure(MeasureName: String);
function GetMeasure(MeasureName: String): TMeasure;
procedure SetCurrentMeasure(MeasureName: String);
function GetCurrentMeasure: TMeasure;
function EnumMeasures(Index: Cardinal): TMeasure;
procedure RegisterMeasureChangeNotifier(Callback: TMeasureChange);
procedure UnRegisterMeasureChangeNotifier(Callback: TMeasureChange);
implementation
var
Measures: TList<TMeasure>;
Callbacks: TList<TMeasureChange>;
Default, Current: TMeasure;
procedure NotifyClients(Old, New: TMeasure);
var
Callback: TMeasureChange;
begin
for Callback in Callbacks do begin
Callback(old, new);
end;
end;
function RegisterMeasure(MeasureName: String): TMeasure;
begin
result := NIL;
if not assigned(GetMeasure(MeasureName)) then
result := TMeasure.Create(MeasureName);
end;
procedure UnregisterMeasure(MeasureName: String);
var
i: Integer;
begin
for i := 0 to Measures.Count - 1 do begin
if Measures[i].Name = MeasureName then begin
Measures[i].Destroy;
Measures.Delete(i);
end;
end;
end;
function GetMeasure(MeasureName: String): TMeasure;
var
Measure: TMeasure;
begin
result := NIL;
for Measure in Measures do begin
if Measure.Name = MeasureName then
exit(Measure);
end;
end;
procedure SetCurrentMeasure(MeasureName: String);
var
Measure, OldMeasure: TMeasure;
begin
for Measure in Measures do begin
if Measure.Name = MeasureName then begin
if Measure <> Current then begin
OldMeasure := Current;
Current := Measure;
NotifyClients(OldMeasure, Measure);
end;
exit;
end;
end;
end;
function GetCurrentMeasure: TMeasure;
begin
if Current = Default then
result := NIL
else
result := Current;
end;
function EnumMeasures(Index: Cardinal): TMeasure;
begin
result := NIL;
if Index < Cardinal(Measures.Count) then begin
result := Measures[Index];
end;
end;
procedure RegisterMeasureChangeNotifier(Callback: TMeasureChange);
begin
Callbacks.Add(Callback);
end;
procedure UnRegisterMeasureChangeNotifier(Callback: TMeasureChange);
begin
Callbacks.Remove(Callback);
end;
{ TMeasure }
constructor TMeasure.Create(Name: String);
begin
inherited Create;
FName := Name;
end;
procedure TMeasure.SetConvertFrom(const Value: TMeasureConvert);
begin
FConvertFrom := Value;
end;
procedure TMeasure.SetConvertTo(const Value: TMeasureConvert);
begin
FConvertTo := Value;
end;
procedure TMeasure.SetFormat(const Value: String);
begin
FFormat := Value;
end;
procedure TMeasure.SetPrefix(const Value: TPrefixSuffix);
begin
FPrefix := Value;
end;
procedure TMeasure.SetSuffix(const Value: TPrefixSuffix);
begin
FSuffix := Value;
end;
initialization
Measures := TList<TMeasure>.Create;
Callbacks := TList<TMeasureChange>.Create;
Default := TMeasure.Create('Default');
Default.FPrefix := function : String
begin
result := '';
end;
Default.FSuffix := Default.FPrefix;
Default.FConvertFrom := function (Value: Variant) : Variant
begin
result := Value;
end;
Default.FConvertTo := Default.FConvertFrom;
Current := Default;
Yes now it works but for some reason it adds an extra empty line after the anonymous method. It could be because of my settings but didn't find a way to attach an file so if you can't reproduce it pls guide me how to attach files to my posts.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have verified the issue with the following code:
unit TestAnonFunctionInInitialization;
interface
implementation
Type
TStringFunction = reference to function: string;
var
foo: TStringFunction;
initialization
foo := function: String
begin
result := 'fred';
end;
end.
A fix and test cases have been checked in, and will be in the next version.
hello, downloaded latest version and the test case you used is formating without error. However my code trows same error
here is the full unit
unit MeasuresEngine;
interface
uses
Generics.Collections;
type
TPrefixSuffix = reference to function: string;
TMeasureConvert = reference to function (Value: Variant): Variant;
TMeasure = class
private
FName: String;
FPrefix: TPrefixSuffix;
FSuffix: TPrefixSuffix;
FConvertFrom: TMeasureConvert;
FConvertTo: TMeasureConvert;
FFormat: String;
procedure SetPrefix(const Value: TPrefixSuffix);
procedure SetSuffix(const Value: TPrefixSuffix);
constructor Create(Name: String); REINTRODUCE;
procedure SetConvertFrom(const Value: TMeasureConvert);
procedure SetConvertTo(const Value: TMeasureConvert);
procedure SetFormat(const Value: String);
public
property Name: String READ FName;
property Prefix: TPrefixSuffix READ FPrefix WRITE SetPrefix;
property Suffix: TPrefixSuffix READ FSuffix WRITE SetSuffix;
property Format: String READ FFormat WRITE SetFormat;
property DefaultToMeasure: TMeasureConvert READ FConvertTo WRITE SetConvertTo;
property MeasureToDefault: TMeasureConvert READ FConvertFrom WRITE SetConvertFrom;
end;
TMeasureChange = procedure(oldMeasure, newMeasure: TMeasure);
function RegisterMeasure(MeasureName: String): TMeasure;
procedure UnregisterMeasure(MeasureName: String);
function GetMeasure(MeasureName: String): TMeasure;
procedure SetCurrentMeasure(MeasureName: String);
function GetCurrentMeasure: TMeasure;
function EnumMeasures(Index: Cardinal): TMeasure;
procedure RegisterMeasureChangeNotifier(Callback: TMeasureChange);
procedure UnRegisterMeasureChangeNotifier(Callback: TMeasureChange);
implementation
var
Measures: TList<TMeasure>;
Callbacks: TList<TMeasureChange>;
Default, Current: TMeasure;
procedure NotifyClients(Old, New: TMeasure);
var
Callback: TMeasureChange;
begin
for Callback in Callbacks do begin
Callback(old, new);
end;
end;
function RegisterMeasure(MeasureName: String): TMeasure;
begin
result := NIL;
if not assigned(GetMeasure(MeasureName)) then
result := TMeasure.Create(MeasureName);
end;
procedure UnregisterMeasure(MeasureName: String);
var
i: Integer;
begin
for i := 0 to Measures.Count - 1 do begin
if Measures[i].Name = MeasureName then begin
Measures[i].Destroy;
Measures.Delete(i);
end;
end;
end;
function GetMeasure(MeasureName: String): TMeasure;
var
Measure: TMeasure;
begin
result := NIL;
for Measure in Measures do begin
if Measure.Name = MeasureName then
exit(Measure);
end;
end;
procedure SetCurrentMeasure(MeasureName: String);
var
Measure, OldMeasure: TMeasure;
begin
for Measure in Measures do begin
if Measure.Name = MeasureName then begin
if Measure <> Current then begin
OldMeasure := Current;
Current := Measure;
NotifyClients(OldMeasure, Measure);
end;
exit;
end;
end;
end;
function GetCurrentMeasure: TMeasure;
begin
if Current = Default then
result := NIL
else
result := Current;
end;
function EnumMeasures(Index: Cardinal): TMeasure;
begin
result := NIL;
if Index < Cardinal(Measures.Count) then begin
result := Measures[Index];
end;
end;
procedure RegisterMeasureChangeNotifier(Callback: TMeasureChange);
begin
Callbacks.Add(Callback);
end;
procedure UnRegisterMeasureChangeNotifier(Callback: TMeasureChange);
begin
Callbacks.Remove(Callback);
end;
{ TMeasure }
constructor TMeasure.Create(Name: String);
begin
inherited Create;
FName := Name;
end;
procedure TMeasure.SetConvertFrom(const Value: TMeasureConvert);
begin
FConvertFrom := Value;
end;
procedure TMeasure.SetConvertTo(const Value: TMeasureConvert);
begin
FConvertTo := Value;
end;
procedure TMeasure.SetFormat(const Value: String);
begin
FFormat := Value;
end;
procedure TMeasure.SetPrefix(const Value: TPrefixSuffix);
begin
FPrefix := Value;
end;
procedure TMeasure.SetSuffix(const Value: TPrefixSuffix);
begin
FSuffix := Value;
end;
initialization
Measures := TList<TMeasure>.Create;
Callbacks := TList<TMeasureChange>.Create;
Default := TMeasure.Create('Default');
Default.FPrefix := function : String
begin
result := '';
end;
Default.FSuffix := Default.FPrefix;
Default.FConvertFrom := function (Value: Variant) : Variant
begin
result := Value;
end;
Default.FConvertTo := Default.FConvertFrom;
Current := Default;
finalization
Measures.Destroy;
Callbacks.Destroy;
Default.Destroy;
end.
The issue now is that it fails if there is a statement after the anon function.
I have checked in a fix to this and test case.
Yes now it works but for some reason it adds an extra empty line after the anonymous method. It could be because of my settings but didn't find a way to attach an file so if you can't reproduce it pls guide me how to attach files to my posts.
Just notice one more thing
initialization
Measures := TList<TMeasure>.Create;
Callbacks := TList<TCallbackPair>.Create;
Default := TMeasure.Create('Default');
Default.FPrefix := function: String
begin
result := '';
end;
Default.FSuffix := Default.FPrefix;
Default.FConvertFrom := function (Value: Variant): Variant
begin
result := Value;
end;
Default.FConvertTo := Default.FConvertFrom;
Current := Default;
finalization
Measures.Destroy;
Callbacks.Destroy;
Default.Destroy;
end.
With this code it adds an empty line before the finalization clause. If I comment the code in initialization section there is no extra line.