mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 19:49:12 +02:00
fcl-passrc: resolver: option to allow class property with non static getter/setter
git-svn-id: trunk@41255 -
This commit is contained in:
parent
6ec527df23
commit
67dd6b5bf3
@ -1295,7 +1295,7 @@ type
|
|||||||
|
|
||||||
TPasResolverOption = (
|
TPasResolverOption = (
|
||||||
proFixCaseOfOverrides, // fix Name of overriding proc/property to the overriden proc/property
|
proFixCaseOfOverrides, // fix Name of overriding proc/property to the overriden proc/property
|
||||||
proClassPropertyNonStatic, // class property accessors are non static
|
proClassPropertyNonStatic, // class property accessors can be non static
|
||||||
proPropertyAsVarParam, // allows to pass a property as a var/out argument
|
proPropertyAsVarParam, // allows to pass a property as a var/out argument
|
||||||
proClassOfIs, // class-of supports is and as operator
|
proClassOfIs, // class-of supports is and as operator
|
||||||
proExtClassInstanceNoTypeMembers, // class members of external class cannot be accessed by instance
|
proExtClassInstanceNoTypeMembers, // class members of external class cannot be accessed by instance
|
||||||
@ -5942,14 +5942,13 @@ begin
|
|||||||
RaiseMsg(20181218195552,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'abstract'],Proc);
|
RaiseMsg(20181218195552,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'abstract'],Proc);
|
||||||
if Proc.IsForward then
|
if Proc.IsForward then
|
||||||
RaiseMsg(20181218195514,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'forward'],Proc);
|
RaiseMsg(20181218195514,nInvalidXModifierY,sInvalidXModifierY,['record '+GetElementTypeName(Proc),'forward'],Proc);
|
||||||
if Proc.IsStatic then
|
|
||||||
if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
|
|
||||||
RaiseMsg(20190206150922,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'static'],Proc);
|
|
||||||
if IsClassMethod(Proc) then
|
if IsClassMethod(Proc) then
|
||||||
begin
|
begin
|
||||||
if not Proc.IsStatic then
|
if not Proc.IsStatic then
|
||||||
RaiseMsg(20190106121503,nClassMethodsMustBeStaticInX,sClassMethodsMustBeStaticInX,['records'],Proc);
|
RaiseMsg(20190106121503,nClassMethodsMustBeStaticInX,sClassMethodsMustBeStaticInX,['records'],Proc);
|
||||||
end;
|
end
|
||||||
|
else if Proc.IsStatic then
|
||||||
|
RaiseMsg(20190206150922,nInvalidXModifierY,sInvalidXModifierY,[GetElementTypeName(Proc),'static'],Proc);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -6476,12 +6475,15 @@ var
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function ExpectedClassAccessorStatic: boolean;
|
function CheckClassAccessorStatic(ProcIsStatic: boolean): boolean;
|
||||||
begin
|
begin
|
||||||
if (ClassScope<>nil) and (proClassPropertyNonStatic in Options) then
|
if ClassScope=nil then
|
||||||
Result:=false
|
// record: class getter/setter must be static
|
||||||
|
Result:=ProcIsStatic=true
|
||||||
|
else if proClassPropertyNonStatic in Options then
|
||||||
|
Result:=true // both allowed
|
||||||
else
|
else
|
||||||
Result:=true;
|
Result:=ProcIsStatic=true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure CheckIndexArg(ArgNo: integer; const IndexResolved: TPasResolverResult;
|
procedure CheckIndexArg(ArgNo: integer; const IndexResolved: TPasResolverResult;
|
||||||
@ -6893,7 +6895,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if Proc.ClassType<>TPasClassFunction then
|
if Proc.ClassType<>TPasClassFunction then
|
||||||
RaiseXExpectedButYFound(20170216151834,'class function',GetElementTypeName(Proc),PropEl.ReadAccessor);
|
RaiseXExpectedButYFound(20170216151834,'class function',GetElementTypeName(Proc),PropEl.ReadAccessor);
|
||||||
if Proc.IsStatic<>ExpectedClassAccessorStatic then
|
if not CheckClassAccessorStatic(Proc.IsStatic) then
|
||||||
if Proc.IsStatic then
|
if Proc.IsStatic then
|
||||||
RaiseMsg(20170216151837,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.ReadAccessor)
|
RaiseMsg(20170216151837,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.ReadAccessor)
|
||||||
else
|
else
|
||||||
@ -6948,7 +6950,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if Proc.ClassType<>TPasClassProcedure then
|
if Proc.ClassType<>TPasClassProcedure then
|
||||||
RaiseXExpectedButYFound(20170216151903,'class procedure',GetElementTypeName(Proc),PropEl.WriteAccessor);
|
RaiseXExpectedButYFound(20170216151903,'class procedure',GetElementTypeName(Proc),PropEl.WriteAccessor);
|
||||||
if Proc.IsStatic<>ExpectedClassAccessorStatic then
|
if not CheckClassAccessorStatic(Proc.IsStatic) then
|
||||||
if Proc.IsStatic then
|
if Proc.IsStatic then
|
||||||
RaiseMsg(20170216151905,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.WriteAccessor)
|
RaiseMsg(20170216151905,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.WriteAccessor)
|
||||||
else
|
else
|
||||||
|
@ -585,6 +585,7 @@ type
|
|||||||
Procedure TestClass_FuncReturningObjectMember;
|
Procedure TestClass_FuncReturningObjectMember;
|
||||||
Procedure TestClass_StaticWithoutClassFail;
|
Procedure TestClass_StaticWithoutClassFail;
|
||||||
Procedure TestClass_SelfInStaticFail;
|
Procedure TestClass_SelfInStaticFail;
|
||||||
|
Procedure TestClass_SelfDotInStaticFail;
|
||||||
Procedure TestClass_PrivateProtectedInSameUnit;
|
Procedure TestClass_PrivateProtectedInSameUnit;
|
||||||
Procedure TestClass_PrivateInMainBeginFail;
|
Procedure TestClass_PrivateInMainBeginFail;
|
||||||
Procedure TestClass_PrivateInDescendantFail;
|
Procedure TestClass_PrivateInDescendantFail;
|
||||||
@ -692,7 +693,11 @@ type
|
|||||||
Procedure TestPropertyArgs2;
|
Procedure TestPropertyArgs2;
|
||||||
Procedure TestPropertyArgsWithDefaultsFail;
|
Procedure TestPropertyArgsWithDefaultsFail;
|
||||||
Procedure TestPropertyArgs_StringConstDefault;
|
Procedure TestPropertyArgs_StringConstDefault;
|
||||||
Procedure TestProperty_Index;
|
Procedure TestClassProperty;
|
||||||
|
Procedure TestClassPropertyNonStaticFail;
|
||||||
|
Procedure TestClassPropertyNonStaticAllow;
|
||||||
|
//Procedure TestClassPropertyStaticMismatchFail;
|
||||||
|
Procedure TestArrayProperty;
|
||||||
Procedure TestProperty_WrongTypeAsIndexFail;
|
Procedure TestProperty_WrongTypeAsIndexFail;
|
||||||
Procedure TestProperty_Option_ClassPropertyNonStatic;
|
Procedure TestProperty_Option_ClassPropertyNonStatic;
|
||||||
Procedure TestDefaultProperty;
|
Procedure TestDefaultProperty;
|
||||||
@ -10038,6 +10043,23 @@ begin
|
|||||||
CheckResolverException('identifier not found "Self"',nIdentifierNotFound);
|
CheckResolverException('identifier not found "Self"',nIdentifierNotFound);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestClass_SelfDotInStaticFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add('type');
|
||||||
|
Add(' TObject = class');
|
||||||
|
Add(' class var FLeft: word;');
|
||||||
|
Add(' class function DoIt: word; static;');
|
||||||
|
Add(' class property Left: word read FLeft;');
|
||||||
|
Add(' end;');
|
||||||
|
Add('class function TObject.DoIt: word;');
|
||||||
|
Add('begin');
|
||||||
|
Add(' Result:=Self.Left;');
|
||||||
|
Add('end;');
|
||||||
|
Add('begin');
|
||||||
|
CheckResolverException('identifier not found "Self"',nIdentifierNotFound);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestResolver.TestClass_PrivateProtectedInSameUnit;
|
procedure TTestResolver.TestClass_PrivateProtectedInSameUnit;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
@ -12175,7 +12197,89 @@ begin
|
|||||||
ParseProgram;
|
ParseProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestResolver.TestProperty_Index;
|
procedure TTestResolver.TestClassProperty;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' class function GetStatic: word; static;',
|
||||||
|
' class procedure SetStatic(Value: word); static;',
|
||||||
|
' class property StaticP: word read GetStatic write SetStatic;',
|
||||||
|
' end;',
|
||||||
|
'class function TObject.GetStatic: word;',
|
||||||
|
'begin',
|
||||||
|
' StaticP:=StaticP;',
|
||||||
|
'end;',
|
||||||
|
'class procedure TObject.SetStatic(Value: word);',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
'']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestClassPropertyNonStaticFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' class function GetNonStatic: word;',
|
||||||
|
' class property NonStatic: word read GetNonStatic;',
|
||||||
|
' end;',
|
||||||
|
'class function TObject.GetNonStatic: word;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
'']);
|
||||||
|
CheckResolverException(sClassPropertyAccessorMustBeStatic,nClassPropertyAccessorMustBeStatic);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestClassPropertyNonStaticAllow;
|
||||||
|
begin
|
||||||
|
ResolverEngine.Options:=ResolverEngine.Options+[proClassPropertyNonStatic];
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'type',
|
||||||
|
' TObject = class',
|
||||||
|
' class function GetStatic: word; static;',
|
||||||
|
' class procedure SetStatic(Value: word); static;',
|
||||||
|
' class property StaticP: word read GetStatic write SetStatic;',
|
||||||
|
' class function GetNonStatic: word;',
|
||||||
|
' class procedure SetNonStatic(Value: word);',
|
||||||
|
' class property NonStatic: word read GetNonStatic write SetNonStatic;',
|
||||||
|
' end;',
|
||||||
|
' TClass = class of TObject;',
|
||||||
|
'class function TObject.GetStatic: word;',
|
||||||
|
'begin',
|
||||||
|
' StaticP:=StaticP;',
|
||||||
|
' NonStatic:=NonStatic;',
|
||||||
|
'end;',
|
||||||
|
'class procedure TObject.SetStatic(Value: word);',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'class function TObject.GetNonStatic: word;',
|
||||||
|
'begin',
|
||||||
|
' StaticP:=StaticP;',
|
||||||
|
' NonStatic:=NonStatic;',
|
||||||
|
'end;',
|
||||||
|
'class procedure TObject.SetNonStatic(Value: word);',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'var',
|
||||||
|
' c: TClass;',
|
||||||
|
' o: TObject;',
|
||||||
|
'begin',
|
||||||
|
' c.STaticP:=c.StaticP;',
|
||||||
|
' o.STaticP:=o.StaticP;',
|
||||||
|
' c.NonStatic:=c.NonStatic;',
|
||||||
|
' o.NonStatic:=o.NonStatic;',
|
||||||
|
'']);
|
||||||
|
ParseProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestResolver.TestArrayProperty;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add('type');
|
Add('type');
|
||||||
|
Loading…
Reference in New Issue
Block a user