mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 14:29:14 +02:00
fcl-passrc: resolver: mode delphi: allow member with same name as ancestor member
git-svn-id: trunk@45054 -
This commit is contained in:
parent
bd01182ff0
commit
1af626817e
@ -54,8 +54,6 @@ Type
|
|||||||
function IsChildStored: boolean;
|
function IsChildStored: boolean;
|
||||||
function StreamChildren(AComp: TComponent): TJSONArray;
|
function StreamChildren(AComp: TComponent): TJSONArray;
|
||||||
protected
|
protected
|
||||||
Function GetPropertyList(aObject : TObject) : TPropInfoList; virtual;
|
|
||||||
Procedure StreamProperties(aObject : TObject;aList : TPropInfoList; aParent : TJSONObject); virtual;
|
|
||||||
function StreamClassProperty(Const AObject: TObject): TJSONData; virtual;
|
function StreamClassProperty(Const AObject: TObject): TJSONData; virtual;
|
||||||
Function StreamProperty(Const AObject : TObject; Const PropertyName : String) : TJSONData;
|
Function StreamProperty(Const AObject : TObject; Const PropertyName : String) : TJSONData;
|
||||||
Function StreamProperty(Const AObject : TObject; PropertyInfo : PPropInfo) : TJSONData;
|
Function StreamProperty(Const AObject : TObject; PropertyInfo : PPropInfo) : TJSONData;
|
||||||
@ -757,36 +755,12 @@ begin
|
|||||||
Result:=(GetChildProperty<>'Children');
|
Result:=(GetChildProperty<>'Children');
|
||||||
end;
|
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;
|
function TJSONStreamer.ObjectToJSON(Const AObject: TObject): TJSONObject;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
PIL : TPropInfoList;
|
PIL : TPropInfoList;
|
||||||
|
PD : TJSONData;
|
||||||
|
I : Integer;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Result:=Nil;
|
Result:=Nil;
|
||||||
@ -806,12 +780,20 @@ begin
|
|||||||
Result.Add('Objects', StreamTList(TList(AObject)))
|
Result.Add('Objects', StreamTList(TList(AObject)))
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
PIL:=GetPropertyList(aObject);
|
PIL:=TPropInfoList.Create(AObject,tkProperties);
|
||||||
// TPropInfoList.Create(AObject,tkProperties);
|
|
||||||
try
|
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
|
finally
|
||||||
FreeAndNil(Pil);
|
FReeAndNil(Pil);
|
||||||
end;
|
end;
|
||||||
If (jsoStreamChildren in Options) and (AObject is TComponent) then
|
If (jsoStreamChildren in Options) and (AObject is TComponent) then
|
||||||
Result.Add(ChildProperty,StreamChildren(TComponent(AObject)));
|
Result.Add(ChildProperty,StreamChildren(TComponent(AObject)));
|
||||||
|
@ -5155,6 +5155,7 @@ var
|
|||||||
Proc: TPasProcedure;
|
Proc: TPasProcedure;
|
||||||
Store, SameScope: Boolean;
|
Store, SameScope: Boolean;
|
||||||
ProcScope: TPasProcedureScope;
|
ProcScope: TPasProcedureScope;
|
||||||
|
CurResolver: TPasResolver;
|
||||||
|
|
||||||
procedure CountProcInSameScope;
|
procedure CountProcInSameScope;
|
||||||
begin
|
begin
|
||||||
@ -5188,7 +5189,7 @@ begin
|
|||||||
fpkProc:
|
fpkProc:
|
||||||
// proc hides a non proc
|
// proc hides a non proc
|
||||||
if (Data^.Proc.GetModule=El.GetModule) then
|
if (Data^.Proc.GetModule=El.GetModule) then
|
||||||
// forbidden within same module
|
// forbidden within same CurModule
|
||||||
RaiseMsg(20170216151649,nDuplicateIdentifier,sDuplicateIdentifier,
|
RaiseMsg(20170216151649,nDuplicateIdentifier,sDuplicateIdentifier,
|
||||||
[El.Name,GetElementSourcePosStr(El)],Data^.Proc.ProcType)
|
[El.Name,GetElementSourcePosStr(El)],Data^.Proc.ProcType)
|
||||||
else
|
else
|
||||||
@ -5205,8 +5206,15 @@ begin
|
|||||||
end;
|
end;
|
||||||
fpkMethod:
|
fpkMethod:
|
||||||
// method hides a non proc
|
// method hides a non proc
|
||||||
RaiseMsg(20171118232543,nDuplicateIdentifier,sDuplicateIdentifier,
|
begin
|
||||||
[El.Name,GetElementSourcePosStr(El)],Data^.Proc.ProcType);
|
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;
|
end;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
@ -5491,9 +5499,12 @@ var
|
|||||||
i, TypeParamCnt: Integer;
|
i, TypeParamCnt: Integer;
|
||||||
OtherScope: TPasIdentifierScope;
|
OtherScope: TPasIdentifierScope;
|
||||||
ParentScope: TPasScope;
|
ParentScope: TPasScope;
|
||||||
IsGeneric: Boolean;
|
IsGeneric, IsDelphi: Boolean;
|
||||||
begin
|
begin
|
||||||
if aName='' then exit(nil);
|
if aName='' then exit(nil);
|
||||||
|
|
||||||
|
IsDelphi:=msDelphi in CurrentParser.CurrentModeswitches;
|
||||||
|
|
||||||
if Scope is TPasGroupScope then
|
if Scope is TPasGroupScope then
|
||||||
begin
|
begin
|
||||||
Group:=TPasGroupScope(Scope);
|
Group:=TPasGroupScope(Scope);
|
||||||
@ -5523,7 +5534,8 @@ begin
|
|||||||
RaiseMsg(20170403223024,nSymbolCannotBePublished,sSymbolCannotBePublished,[],El);
|
RaiseMsg(20170403223024,nSymbolCannotBePublished,sSymbolCannotBePublished,[],El);
|
||||||
end;
|
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
|
begin
|
||||||
// check duplicate in ancestors and helpers
|
// check duplicate in ancestors and helpers
|
||||||
for i:=1 to Group.Count-1 do
|
for i:=1 to Group.Count-1 do
|
||||||
@ -5554,7 +5566,7 @@ begin
|
|||||||
|
|
||||||
// check duplicate in current scope
|
// check duplicate in current scope
|
||||||
OlderIdentifier:=Identifier.NextSameIdentifier;
|
OlderIdentifier:=Identifier.NextSameIdentifier;
|
||||||
if IsGeneric and (msDelphi in CurrentParser.CurrentModeswitches) then
|
if IsGeneric and IsDelphi then
|
||||||
OlderIdentifier:=SkipGenericTypes(OlderIdentifier,TypeParamCnt);
|
OlderIdentifier:=SkipGenericTypes(OlderIdentifier,TypeParamCnt);
|
||||||
if OlderIdentifier<>nil then
|
if OlderIdentifier<>nil then
|
||||||
begin
|
begin
|
||||||
|
@ -614,7 +614,8 @@ type
|
|||||||
Procedure TestClass_SubObject;
|
Procedure TestClass_SubObject;
|
||||||
Procedure TestClass_WithDoClassInstance;
|
Procedure TestClass_WithDoClassInstance;
|
||||||
Procedure TestClass_ProcedureExternal;
|
Procedure TestClass_ProcedureExternal;
|
||||||
Procedure TestClass_ReintroducePublicVarFail;
|
Procedure TestClass_ReintroducePublicVarObjFPCFail;
|
||||||
|
Procedure TestClass_ReintroducePublicVarDelphi;
|
||||||
Procedure TestClass_ReintroducePrivateVar;
|
Procedure TestClass_ReintroducePrivateVar;
|
||||||
Procedure TestClass_ReintroduceProc;
|
Procedure TestClass_ReintroduceProc;
|
||||||
Procedure TestClass_UntypedParam_TypeCast;
|
Procedure TestClass_UntypedParam_TypeCast;
|
||||||
@ -11011,22 +11012,59 @@ begin
|
|||||||
ParseProgram;
|
ParseProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestResolver.TestClass_ReintroducePublicVarFail;
|
procedure TTestResolver.TestClass_ReintroducePublicVarObjFPCFail;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add('type');
|
Add([
|
||||||
Add(' TObject = class');
|
'type',
|
||||||
Add(' public');
|
' TObject = class',
|
||||||
Add(' Some: longint;');
|
' public',
|
||||||
Add(' end;');
|
' Some: longint;',
|
||||||
Add(' TCar = class(tobject)');
|
' end;',
|
||||||
Add(' public');
|
' TCar = class(tobject)',
|
||||||
Add(' Some: longint;');
|
' public',
|
||||||
Add(' end;');
|
' Some: longint;',
|
||||||
Add('begin');
|
' end;',
|
||||||
|
'begin']);
|
||||||
CheckResolverException('Duplicate identifier "Some" at afile.pp(5,5)',nDuplicateIdentifier);
|
CheckResolverException('Duplicate identifier "Some" at afile.pp(5,5)',nDuplicateIdentifier);
|
||||||
end;
|
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;
|
procedure TTestResolver.TestClass_ReintroducePrivateVar;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
@ -522,6 +522,7 @@ type
|
|||||||
Procedure TestClass_OverloadsAncestor;
|
Procedure TestClass_OverloadsAncestor;
|
||||||
Procedure TestClass_OverloadConstructor;
|
Procedure TestClass_OverloadConstructor;
|
||||||
Procedure TestClass_OverloadDelphiOverride;
|
Procedure TestClass_OverloadDelphiOverride;
|
||||||
|
Procedure TestClass_ReintroduceVarDelphi;
|
||||||
Procedure TestClass_ReintroducedVar;
|
Procedure TestClass_ReintroducedVar;
|
||||||
Procedure TestClass_RaiseDescendant;
|
Procedure TestClass_RaiseDescendant;
|
||||||
Procedure TestClass_ExternalMethod;
|
Procedure TestClass_ExternalMethod;
|
||||||
@ -13889,6 +13890,94 @@ begin
|
|||||||
'']));
|
'']));
|
||||||
end;
|
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;
|
procedure TTestModule.TestClass_ReintroducedVar;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user