fcl-passrc: resolver: mode delphi: allow member with same name as ancestor member

git-svn-id: trunk@45054 -
This commit is contained in:
Mattias Gaertner 2020-04-24 16:38:34 +00:00
parent bd01182ff0
commit 1af626817e
4 changed files with 171 additions and 50 deletions

View File

@ -54,8 +54,6 @@ Type
function IsChildStored: boolean;
function StreamChildren(AComp: TComponent): TJSONArray;
protected
Function GetPropertyList(aObject : TObject) : TPropInfoList; virtual;
Procedure StreamProperties(aObject : TObject;aList : TPropInfoList; aParent : TJSONObject); virtual;
function StreamClassProperty(Const AObject: TObject): TJSONData; virtual;
Function StreamProperty(Const AObject : TObject; Const PropertyName : String) : TJSONData;
Function StreamProperty(Const AObject : TObject; PropertyInfo : PPropInfo) : TJSONData;
@ -757,36 +755,12 @@ begin
Result:=(GetChildProperty<>'Children');
end;
Function TJSONStreamer.GetPropertyList(aObject : TObject) : TPropInfoList;
begin
result:=TPropInfoList.Create(AObject,tkProperties);
end;
Procedure TJSONStreamer.StreamProperties(aObject : TObject;aList : TPropInfoList; aParent : TJSONObject);
Var
I : Integer;
PD : TJSONData;
begin
For I:=0 to aList.Count-1 do
begin
PD:=StreamProperty(AObject,aList.Items[i]);
If (PD<>Nil) then
begin
if jsoLowerPropertyNames in Options then
aParent.Add(LowerCase(aList.Items[I]^.Name),PD)
else
aParent.Add(aList.Items[I]^.Name,PD);
end;
end;
end;
function TJSONStreamer.ObjectToJSON(Const AObject: TObject): TJSONObject;
Var
PIL : TPropInfoList;
PD : TJSONData;
I : Integer;
begin
Result:=Nil;
@ -806,12 +780,20 @@ begin
Result.Add('Objects', StreamTList(TList(AObject)))
else
begin
PIL:=GetPropertyList(aObject);
// TPropInfoList.Create(AObject,tkProperties);
PIL:=TPropInfoList.Create(AObject,tkProperties);
try
StreamProperties(aObject,PIL,Result);
For I:=0 to PIL.Count-1 do
begin
PD:=StreamProperty(AObject,PIL.Items[i]);
If (PD<>Nil) then begin
if jsoLowerPropertyNames in Options then
Result.Add(LowerCase(PIL.Items[I]^.Name),PD)
else
Result.Add(PIL.Items[I]^.Name,PD);
end;
end;
finally
FreeAndNil(Pil);
FReeAndNil(Pil);
end;
If (jsoStreamChildren in Options) and (AObject is TComponent) then
Result.Add(ChildProperty,StreamChildren(TComponent(AObject)));

View File

@ -5155,6 +5155,7 @@ var
Proc: TPasProcedure;
Store, SameScope: Boolean;
ProcScope: TPasProcedureScope;
CurResolver: TPasResolver;
procedure CountProcInSameScope;
begin
@ -5188,7 +5189,7 @@ begin
fpkProc:
// proc hides a non proc
if (Data^.Proc.GetModule=El.GetModule) then
// forbidden within same module
// forbidden within same CurModule
RaiseMsg(20170216151649,nDuplicateIdentifier,sDuplicateIdentifier,
[El.Name,GetElementSourcePosStr(El)],Data^.Proc.ProcType)
else
@ -5205,8 +5206,15 @@ begin
end;
fpkMethod:
// method hides a non proc
RaiseMsg(20171118232543,nDuplicateIdentifier,sDuplicateIdentifier,
[El.Name,GetElementSourcePosStr(El)],Data^.Proc.ProcType);
begin
ProcScope:=TPasProcedureScope(Data^.Proc.CustomData);
CurResolver:=ProcScope.Owner as TPasResolver;
if msDelphi in CurResolver.CurrentParser.CurrentModeswitches then
// ok in delphi
else
RaiseMsg(20171118232543,nDuplicateIdentifier,sDuplicateIdentifier,
[El.Name,GetElementSourcePosStr(El)],Data^.Proc.ProcType);
end;
end;
exit;
end;
@ -5491,9 +5499,12 @@ var
i, TypeParamCnt: Integer;
OtherScope: TPasIdentifierScope;
ParentScope: TPasScope;
IsGeneric: Boolean;
IsGeneric, IsDelphi: Boolean;
begin
if aName='' then exit(nil);
IsDelphi:=msDelphi in CurrentParser.CurrentModeswitches;
if Scope is TPasGroupScope then
begin
Group:=TPasGroupScope(Scope);
@ -5523,7 +5534,8 @@ begin
RaiseMsg(20170403223024,nSymbolCannotBePublished,sSymbolCannotBePublished,[],El);
end;
if (Kind=pikSimple) and (Group<>nil) and (El.ClassType<>TPasProperty) then
if (Kind=pikSimple) and (Group<>nil) and (El.ClassType<>TPasProperty)
and not IsDelphi then
begin
// check duplicate in ancestors and helpers
for i:=1 to Group.Count-1 do
@ -5554,7 +5566,7 @@ begin
// check duplicate in current scope
OlderIdentifier:=Identifier.NextSameIdentifier;
if IsGeneric and (msDelphi in CurrentParser.CurrentModeswitches) then
if IsGeneric and IsDelphi then
OlderIdentifier:=SkipGenericTypes(OlderIdentifier,TypeParamCnt);
if OlderIdentifier<>nil then
begin

View File

@ -614,7 +614,8 @@ type
Procedure TestClass_SubObject;
Procedure TestClass_WithDoClassInstance;
Procedure TestClass_ProcedureExternal;
Procedure TestClass_ReintroducePublicVarFail;
Procedure TestClass_ReintroducePublicVarObjFPCFail;
Procedure TestClass_ReintroducePublicVarDelphi;
Procedure TestClass_ReintroducePrivateVar;
Procedure TestClass_ReintroduceProc;
Procedure TestClass_UntypedParam_TypeCast;
@ -11011,22 +11012,59 @@ begin
ParseProgram;
end;
procedure TTestResolver.TestClass_ReintroducePublicVarFail;
procedure TTestResolver.TestClass_ReintroducePublicVarObjFPCFail;
begin
StartProgram(false);
Add('type');
Add(' TObject = class');
Add(' public');
Add(' Some: longint;');
Add(' end;');
Add(' TCar = class(tobject)');
Add(' public');
Add(' Some: longint;');
Add(' end;');
Add('begin');
Add([
'type',
' TObject = class',
' public',
' Some: longint;',
' end;',
' TCar = class(tobject)',
' public',
' Some: longint;',
' end;',
'begin']);
CheckResolverException('Duplicate identifier "Some" at afile.pp(5,5)',nDuplicateIdentifier);
end;
procedure TTestResolver.TestClass_ReintroducePublicVarDelphi;
begin
StartProgram(false);
Add([
'{$mode delphi}',
'type',
' TObject = class',
' public',
' {#Obj_Some}Some: longint;',
' {#Obj_Foo}Foo: word;',
' function {#Obj_Bar}Bar: string;',
' end;',
' TCar = class(tobject)',
' public',
' {#Car_Some}Some: double;',
' function {#Car_Foo}Foo: boolean;',
' {#Car_Bar}Bar: single;',
' end;',
'function TObject.Bar: string;',
'begin',
'end;',
'function TCar.Foo: boolean;',
'begin',
' {@Car_Some}Some:=3.3;',
' {@Car_Bar}Bar:=4.3;',
' inherited {@Obj_Bar}Bar;',
' inherited {@Obj_Bar}Bar();',
' inherited {@Obj_Foo}Foo := 4;',
' if inherited {@Obj_Some}Some = 5 then ;',
'end;',
'var C: TCar;',
'begin',
' C.Some:=1.3;']);
ParseProgram;
end;
procedure TTestResolver.TestClass_ReintroducePrivateVar;
begin
StartProgram(false);

View File

@ -522,6 +522,7 @@ type
Procedure TestClass_OverloadsAncestor;
Procedure TestClass_OverloadConstructor;
Procedure TestClass_OverloadDelphiOverride;
Procedure TestClass_ReintroduceVarDelphi;
Procedure TestClass_ReintroducedVar;
Procedure TestClass_RaiseDescendant;
Procedure TestClass_ExternalMethod;
@ -13889,6 +13890,94 @@ begin
'']));
end;
procedure TTestModule.TestClass_ReintroduceVarDelphi;
begin
StartProgram(false);
Add([
'{$mode delphi}',
'type',
' TObject = class end;',
' TAnimal = class',
' public',
' {#animal_a}A: longint;',
' function {#animal_b}B: longint;',
' end;',
' TBird = class(TAnimal)',
' public',
' {#bird_a}A: double;',
' {#bird_b}B: boolean;',
' end;',
' TEagle = class(TBird)',
' public',
' function {#eagle_a}A: boolean;',
' {#eagle_b}B: double;',
' end;',
'function TAnimal.B: longint;',
'begin',
'end;',
'function TEagle.A: boolean;',
'begin',
' {@eagle_b}B:=3.3;',
' {@eagle_a}A();',
' TBird(Self).{@bird_b}B:=true;',
' TAnimal(Self).{@animal_a}A:=17;',
' inherited {@bird_b}B:=inherited {bird_a}A>1;', // Delphi allows only inherited <functionname>
'end;',
'var',
' e: TEagle;',
'begin',
' e.{@eagle_b}B:=5.3;',
' if e.{@eagle_a}A then ;',
'']);
ConvertProgram;
CheckSource('TestClass_ReintroduceVarDelphi',
LinesToStr([ // statements
'rtl.createClass($mod, "TObject", null, function () {',
' this.$init = function () {',
' };',
' this.$final = function () {',
' };',
'});',
'rtl.createClass($mod, "TAnimal", $mod.TObject, function () {',
' this.$init = function () {',
' $mod.TObject.$init.call(this);',
' this.A = 0;',
' };',
' this.B = function () {',
' var Result = 0;',
' return Result;',
' };',
'});',
'rtl.createClass($mod, "TBird", $mod.TAnimal, function () {',
' this.$init = function () {',
' $mod.TAnimal.$init.call(this);',
' this.A$1 = 0.0;',
' this.B$1 = false;',
' };',
'});',
'rtl.createClass($mod, "TEagle", $mod.TBird, function () {',
' this.$init = function () {',
' $mod.TBird.$init.call(this);',
' this.B$2 = 0.0;',
' };',
' this.A$2 = function () {',
' var Result = false;',
' this.B$2 = 3.3;',
' this.A$2();',
' this.B$1 = true;',
' this.A = 17;',
' this.B$1 = this.A$1 > 1;',
' return Result;',
' };',
'});',
'this.e = null;',
'']),
LinesToStr([ // $mod.$main
'$mod.e.B$2 = 5.3;',
'if ($mod.e.A$2()) ;',
'']));
end;
procedure TTestModule.TestClass_ReintroducedVar;
begin
StartProgram(false);