mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-13 14:09:16 +02:00
IDE+codetools: implemented creating event override for nested components
git-svn-id: trunk@15738 -
This commit is contained in:
parent
edb42bf15c
commit
4d27d2dca5
@ -649,7 +649,8 @@ type
|
|||||||
function CreatePublishedMethod(Code: TCodeBuffer; const AClassName,
|
function CreatePublishedMethod(Code: TCodeBuffer; const AClassName,
|
||||||
NewMethodName: string; ATypeInfo: PTypeInfo;
|
NewMethodName: string; ATypeInfo: PTypeInfo;
|
||||||
UseTypeInfoForParameters: boolean = false;
|
UseTypeInfoForParameters: boolean = false;
|
||||||
const APropertyUnitName: string = ''; const APropertyPath: string = ''
|
const APropertyUnitName: string = ''; const APropertyPath: string = '';
|
||||||
|
const CallAncestorMethod: string = ''
|
||||||
): boolean;
|
): boolean;
|
||||||
|
|
||||||
// private class parts
|
// private class parts
|
||||||
@ -2912,7 +2913,8 @@ end;
|
|||||||
function TCodeToolManager.CreatePublishedMethod(Code: TCodeBuffer;
|
function TCodeToolManager.CreatePublishedMethod(Code: TCodeBuffer;
|
||||||
const AClassName, NewMethodName: string; ATypeInfo: PTypeInfo;
|
const AClassName, NewMethodName: string; ATypeInfo: PTypeInfo;
|
||||||
UseTypeInfoForParameters: boolean;
|
UseTypeInfoForParameters: boolean;
|
||||||
const APropertyUnitName: string; const APropertyPath: string): boolean;
|
const APropertyUnitName: string; const APropertyPath: string;
|
||||||
|
const CallAncestorMethod: string): boolean;
|
||||||
begin
|
begin
|
||||||
{$IFDEF CTDEBUG}
|
{$IFDEF CTDEBUG}
|
||||||
DebugLn('TCodeToolManager.CreatePublishedMethod A');
|
DebugLn('TCodeToolManager.CreatePublishedMethod A');
|
||||||
@ -2923,7 +2925,8 @@ begin
|
|||||||
SourceChangeCache.Clear;
|
SourceChangeCache.Clear;
|
||||||
Result:=FCurCodeTool.CreateMethod(UpperCaseStr(AClassName),
|
Result:=FCurCodeTool.CreateMethod(UpperCaseStr(AClassName),
|
||||||
NewMethodName,ATypeInfo,APropertyUnitName,APropertyPath,
|
NewMethodName,ATypeInfo,APropertyUnitName,APropertyPath,
|
||||||
SourceChangeCache,UseTypeInfoForParameters,pcsPublished);
|
SourceChangeCache,UseTypeInfoForParameters,pcsPublished,
|
||||||
|
CallAncestorMethod);
|
||||||
except
|
except
|
||||||
on e: Exception do Result:=HandleException(e);
|
on e: Exception do Result:=HandleException(e);
|
||||||
end;
|
end;
|
||||||
|
@ -90,13 +90,15 @@ type
|
|||||||
const APropertyUnitName, APropertyPath: string;
|
const APropertyUnitName, APropertyPath: string;
|
||||||
SourceChangeCache: TSourceChangeCache;
|
SourceChangeCache: TSourceChangeCache;
|
||||||
UseTypeInfoForParameters: boolean = false;
|
UseTypeInfoForParameters: boolean = false;
|
||||||
Section: TPascalClassSection = pcsPublished): boolean;
|
Section: TPascalClassSection = pcsPublished;
|
||||||
|
const CallAncestorMethod: string = ''): boolean;
|
||||||
function CreateMethod(ClassNode: TCodeTreeNode;
|
function CreateMethod(ClassNode: TCodeTreeNode;
|
||||||
const AMethodName: string;
|
const AMethodName: string;
|
||||||
ATypeInfo: PTypeInfo; const APropertyUnitName, APropertyPath: string;
|
ATypeInfo: PTypeInfo; const APropertyUnitName, APropertyPath: string;
|
||||||
SourceChangeCache: TSourceChangeCache;
|
SourceChangeCache: TSourceChangeCache;
|
||||||
UseTypeInfoForParameters: boolean = false;
|
UseTypeInfoForParameters: boolean = false;
|
||||||
Section: TPascalClassSection = pcsPublished): boolean;
|
Section: TPascalClassSection = pcsPublished;
|
||||||
|
const CallAncestorMethod: string = ''): boolean;
|
||||||
|
|
||||||
function CreateExprListFromMethodTypeData(TypeData: PTypeData;
|
function CreateExprListFromMethodTypeData(TypeData: PTypeData;
|
||||||
Params: TFindDeclarationParams): TExprTypeList;
|
Params: TFindDeclarationParams): TExprTypeList;
|
||||||
@ -651,7 +653,8 @@ function TEventsCodeTool.CreateMethod(const UpperClassName,
|
|||||||
const APropertyUnitName, APropertyPath: string;
|
const APropertyUnitName, APropertyPath: string;
|
||||||
SourceChangeCache: TSourceChangeCache;
|
SourceChangeCache: TSourceChangeCache;
|
||||||
UseTypeInfoForParameters: boolean;
|
UseTypeInfoForParameters: boolean;
|
||||||
Section: TPascalClassSection): boolean;
|
Section: TPascalClassSection;
|
||||||
|
const CallAncestorMethod: string): boolean;
|
||||||
var AClassNode: TCodeTreeNode;
|
var AClassNode: TCodeTreeNode;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
@ -659,14 +662,16 @@ begin
|
|||||||
AClassNode:=FindClassNodeInInterface(UpperClassName,true,false,true);
|
AClassNode:=FindClassNodeInInterface(UpperClassName,true,false,true);
|
||||||
Result:=CreateMethod(AClassNode,AMethodName,ATypeInfo,
|
Result:=CreateMethod(AClassNode,AMethodName,ATypeInfo,
|
||||||
APropertyUnitName,APropertyPath,
|
APropertyUnitName,APropertyPath,
|
||||||
SourceChangeCache,UseTypeInfoForParameters,Section);
|
SourceChangeCache,UseTypeInfoForParameters,Section,
|
||||||
|
CallAncestorMethod);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TEventsCodeTool.CreateMethod(ClassNode: TCodeTreeNode;
|
function TEventsCodeTool.CreateMethod(ClassNode: TCodeTreeNode;
|
||||||
const AMethodName: string; ATypeInfo: PTypeInfo;
|
const AMethodName: string; ATypeInfo: PTypeInfo;
|
||||||
const APropertyUnitName, APropertyPath: string;
|
const APropertyUnitName, APropertyPath: string;
|
||||||
SourceChangeCache: TSourceChangeCache; UseTypeInfoForParameters: boolean;
|
SourceChangeCache: TSourceChangeCache; UseTypeInfoForParameters: boolean;
|
||||||
Section: TPascalClassSection): boolean;
|
Section: TPascalClassSection;
|
||||||
|
const CallAncestorMethod: string): boolean;
|
||||||
|
|
||||||
procedure AddNeededUnits(const AFindContext: TFindContext);
|
procedure AddNeededUnits(const AFindContext: TFindContext);
|
||||||
var
|
var
|
||||||
@ -733,6 +738,9 @@ var
|
|||||||
FindContext: TFindContext;
|
FindContext: TFindContext;
|
||||||
ATypeData: PTypeData;
|
ATypeData: PTypeData;
|
||||||
NewSection: TNewClassPart;
|
NewSection: TNewClassPart;
|
||||||
|
InsertCall: String;
|
||||||
|
ProcBody: String;
|
||||||
|
BeautifyCodeOpts: TBeautifyCodeOptions;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
try
|
try
|
||||||
@ -746,7 +754,7 @@ begin
|
|||||||
CodeCompleteSrcChgCache:=SourceChangeCache;
|
CodeCompleteSrcChgCache:=SourceChangeCache;
|
||||||
// check if method definition already exists in class
|
// check if method definition already exists in class
|
||||||
if UseTypeInfoForParameters then begin
|
if UseTypeInfoForParameters then begin
|
||||||
// do not lookup the declaration in the source
|
// do not lookup the declaration in the source, use RTTI instead
|
||||||
ATypeData:=GetTypeData(ATypeInfo);
|
ATypeData:=GetTypeData(ATypeInfo);
|
||||||
if ATypeData=nil then exit(false);
|
if ATypeData=nil then exit(false);
|
||||||
CleanMethodDefinition:=UpperCaseStr(AMethodName)
|
CleanMethodDefinition:=UpperCaseStr(AMethodName)
|
||||||
@ -765,20 +773,33 @@ begin
|
|||||||
DebugLn('[TEventsCodeTool.CreateMethod] insert method definition to class');
|
DebugLn('[TEventsCodeTool.CreateMethod] insert method definition to class');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
// insert method definition into class
|
// insert method definition into class
|
||||||
|
InsertCall:='';
|
||||||
if UseTypeInfoForParameters then begin
|
if UseTypeInfoForParameters then begin
|
||||||
MethodDefinition:=MethodTypeDataToStr(ATypeData,
|
MethodDefinition:=MethodTypeDataToStr(ATypeData,
|
||||||
[phpWithStart, phpWithoutClassKeyword, phpWithoutClassName,
|
[phpWithStart, phpWithoutClassKeyword, phpWithoutClassName,
|
||||||
phpWithoutName, phpWithVarModifiers, phpWithParameterNames,
|
phpWithoutName, phpWithVarModifiers, phpWithParameterNames,
|
||||||
phpWithDefaultValues, phpWithResultType]);
|
phpWithDefaultValues, phpWithResultType]);
|
||||||
|
if CallAncestorMethod<>'' then begin
|
||||||
|
InsertCall:=CallAncestorMethod+MethodTypeDataToStr(ATypeData,
|
||||||
|
[phpWithoutClassKeyword, phpWithoutClassName,
|
||||||
|
phpWithoutName, phpWithParameterNames,
|
||||||
|
phpWithoutParamTypes]);
|
||||||
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
MethodDefinition:=TrimCodeSpace(FindContext.Tool.ExtractProcHead(
|
MethodDefinition:=TrimCodeSpace(FindContext.Tool.ExtractProcHead(
|
||||||
FindContext.Node,
|
FindContext.Node,
|
||||||
[phpWithStart, phpWithoutClassKeyword, phpWithoutClassName,
|
[phpWithStart, phpWithoutClassKeyword, phpWithoutClassName,
|
||||||
phpWithoutName, phpWithVarModifiers, phpWithParameterNames,
|
phpWithoutName, phpWithVarModifiers, phpWithParameterNames,
|
||||||
phpWithDefaultValues, phpWithResultType]));
|
phpWithDefaultValues, phpWithResultType]));
|
||||||
|
if CallAncestorMethod<>'' then begin
|
||||||
|
InsertCall:=CallAncestorMethod
|
||||||
|
+TrimCodeSpace(FindContext.Tool.ExtractProcHead(
|
||||||
|
FindContext.Node,
|
||||||
|
[phpWithoutClassKeyword, phpWithoutClassName,
|
||||||
|
phpWithoutName, phpWithParameterNames,
|
||||||
|
phpWithoutParamTypes]));
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
MethodDefinition:=SourceChangeCache.BeautifyCodeOptions.
|
|
||||||
AddClassAndNameToProc(MethodDefinition, '', AMethodName);
|
|
||||||
{$IFDEF CTDEBUG}
|
{$IFDEF CTDEBUG}
|
||||||
DebugLn('[TEventsCodeTool.CreateMethod] MethodDefinition="',MethodDefinition,'"');
|
DebugLn('[TEventsCodeTool.CreateMethod] MethodDefinition="',MethodDefinition,'"');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -786,8 +807,25 @@ begin
|
|||||||
NewSection:=ncpPublishedProcs
|
NewSection:=ncpPublishedProcs
|
||||||
else
|
else
|
||||||
NewSection:=ncpPrivateProcs;
|
NewSection:=ncpPrivateProcs;
|
||||||
|
ProcBody:='';
|
||||||
|
if InsertCall<>'' then begin
|
||||||
|
BeautifyCodeOpts:=SourceChangeCache.BeautifyCodeOptions;
|
||||||
|
ProcBody:=SourceChangeCache.BeautifyCodeOptions.
|
||||||
|
AddClassAndNameToProc(MethodDefinition,
|
||||||
|
ExtractClassName(CodeCompleteClassNode,false),
|
||||||
|
AMethodName)
|
||||||
|
+BeautifyCodeOpts.LineEnd
|
||||||
|
+'begin'+BeautifyCodeOpts.LineEnd
|
||||||
|
+GetIndentStr(BeautifyCodeOpts.Indent)
|
||||||
|
+InsertCall+BeautifyCodeOpts.LineEnd
|
||||||
|
+'end;';
|
||||||
|
//DebugLn(['TEventsCodeTool.CreateMethod ProcBody=""',ProcBody,'']);
|
||||||
|
end;
|
||||||
|
|
||||||
|
MethodDefinition:=SourceChangeCache.BeautifyCodeOptions.
|
||||||
|
AddClassAndNameToProc(MethodDefinition, '', AMethodName);
|
||||||
AddClassInsertion(CleanMethodDefinition, MethodDefinition, AMethodName,
|
AddClassInsertion(CleanMethodDefinition, MethodDefinition, AMethodName,
|
||||||
NewSection);
|
NewSection,nil,ProcBody);
|
||||||
end;
|
end;
|
||||||
{$IFDEF CTDEBUG}
|
{$IFDEF CTDEBUG}
|
||||||
DebugLn('[TEventsCodeTool.CreateMethod] invoke class completion');
|
DebugLn('[TEventsCodeTool.CreateMethod] invoke class completion');
|
||||||
|
47
ide/main.pp
47
ide/main.pp
@ -13908,6 +13908,12 @@ var
|
|||||||
ActiveUnitInfo: TUnitInfo;
|
ActiveUnitInfo: TUnitInfo;
|
||||||
r: boolean;
|
r: boolean;
|
||||||
OldChange: Boolean;
|
OldChange: Boolean;
|
||||||
|
p: Integer;
|
||||||
|
APropName: String;
|
||||||
|
OldMethod: TMethod;
|
||||||
|
JITMethod: TJITMethod;
|
||||||
|
OverrideMethodName: String;
|
||||||
|
AComponent: TComponent;
|
||||||
begin
|
begin
|
||||||
Result.Code:=nil;
|
Result.Code:=nil;
|
||||||
Result.Data:=nil;
|
Result.Data:=nil;
|
||||||
@ -13919,7 +13925,43 @@ begin
|
|||||||
DebugLn(['[TMainIDE.OnPropHookCreateMethod] Persistent=',dbgsName(APersistent),' Unit=',GetClassUnitName(APersistent.ClassType),' Path=',APropertyPath]);
|
DebugLn(['[TMainIDE.OnPropHookCreateMethod] Persistent=',dbgsName(APersistent),' Unit=',GetClassUnitName(APersistent.ClassType),' Path=',APropertyPath]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
DebugLn(['TMainIDE.OnPropHookCreateMethod ',APropertyPath]);
|
OverrideMethodName:='';
|
||||||
|
if APersistent is TComponent then begin
|
||||||
|
AComponent:=TComponent(APersistent);
|
||||||
|
p:=length(APropertyPath);
|
||||||
|
while (p>0) and (APropertyPath[p]<>'.') do dec(p);
|
||||||
|
if p>0 then begin
|
||||||
|
APropName:=copy(APropertyPath,p+1,length(APropertyPath));
|
||||||
|
OldMethod:=GetMethodProp(APersistent,APropName);
|
||||||
|
if IsJITMethod(OldMethod) then begin
|
||||||
|
// there is an old method
|
||||||
|
JITMethod:=TJITMethod(OldMethod.Data);
|
||||||
|
if JITMethod.ClassType<>ActiveUnitInfo.Component.ClassType then begin
|
||||||
|
// the old method is inherited
|
||||||
|
// => search the component that has the method
|
||||||
|
//DebugLn(['TMainIDE.OnPropHookCreateMethod ',dbgsName(JITMethod.TheClass),' ',dbgsName(APersistent.ClassType),' ',dbgsName(APersistent)]);
|
||||||
|
while (AComponent<>nil)
|
||||||
|
and (not JITMethod.TheClass.InheritsFrom(AComponent.ClassType)) do
|
||||||
|
AComponent:=AComponent.Owner;
|
||||||
|
// create a path to the component
|
||||||
|
while (AComponent<>nil) and (AComponent<>ActiveUnitInfo.Component) do
|
||||||
|
begin
|
||||||
|
if OverrideMethodName<>'' then
|
||||||
|
OverrideMethodName:='.'+OverrideMethodName;
|
||||||
|
OverrideMethodName:=AComponent.Name+OverrideMethodName;
|
||||||
|
AComponent:=AComponent.Owner;
|
||||||
|
end;
|
||||||
|
if (AComponent=ActiveUnitInfo.Component)
|
||||||
|
and (OverrideMethodName<>'') then begin
|
||||||
|
// the old value does not belong to this main component, but to
|
||||||
|
// a nested/inline component
|
||||||
|
OverrideMethodName:=OverrideMethodName+'.'+JITMethod.TheMethodName;
|
||||||
|
DebugLn(['TMainIDE.OnPropHookCreateMethod OverrideMethodName=',OverrideMethodName]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
OldChange:=OpenEditorsOnCodeToolChange;
|
OldChange:=OpenEditorsOnCodeToolChange;
|
||||||
OpenEditorsOnCodeToolChange:=true;
|
OpenEditorsOnCodeToolChange:=true;
|
||||||
@ -13927,7 +13969,8 @@ begin
|
|||||||
// create published method
|
// create published method
|
||||||
r:=CodeToolBoss.CreatePublishedMethod(ActiveUnitInfo.Source,
|
r:=CodeToolBoss.CreatePublishedMethod(ActiveUnitInfo.Source,
|
||||||
ActiveUnitInfo.Component.ClassName,AMethodName,
|
ActiveUnitInfo.Component.ClassName,AMethodName,
|
||||||
ATypeInfo,false,GetClassUnitName(APersistent.ClassType),APropertyPath);
|
ATypeInfo,false,GetClassUnitName(APersistent.ClassType),APropertyPath,
|
||||||
|
OverrideMethodName);
|
||||||
{$IFDEF IDE_DEBUG}
|
{$IFDEF IDE_DEBUG}
|
||||||
writeln('');
|
writeln('');
|
||||||
writeln('[TMainIDE.OnPropHookCreateMethod] ************2 ',r,' ',AMethodName);
|
writeln('[TMainIDE.OnPropHookCreateMethod] ************2 ',r,' ',AMethodName);
|
||||||
|
Loading…
Reference in New Issue
Block a user