IDE: combined remove empty methods

git-svn-id: trunk@17804 -
This commit is contained in:
mattias 2008-12-11 23:00:58 +00:00
parent 0083565937
commit 24e99e928a
5 changed files with 83 additions and 178 deletions

View File

@ -243,14 +243,17 @@ type
out Graph: TCodeGraph; OnlyInterface: boolean): boolean;
procedure WriteCodeGraphDebugReport(Graph: TCodeGraph);
function FindEmptyMethods(CursorPos: TCodeXYPosition;
const AClassName: string;
const Sections: TPascalClassSections;
ListOfPCodeXYPosition: TFPList;
out AllEmpty: boolean): boolean;
function FindEmptyMethods(CursorPos: TCodeXYPosition;
const AClassName: string;
const Sections: TPascalClassSections;
CodeTreeNodeExtensions: TAVLTree;
out AllEmpty: boolean): boolean;
function RemoveEmptyMethods(CursorPos: TCodeXYPosition;
const AClassName: string;
const Sections: TPascalClassSections;
SourceChangeCache: TSourceChangeCache;
out AllRemoved: boolean;
@ -4017,8 +4020,8 @@ begin
end;
function TCodeCompletionCodeTool.FindEmptyMethods(CursorPos: TCodeXYPosition;
const Sections: TPascalClassSections; ListOfPCodeXYPosition: TFPList;
out AllEmpty: boolean): boolean;
const AClassName: string; const Sections: TPascalClassSections;
ListOfPCodeXYPosition: TFPList; out AllEmpty: boolean): boolean;
var
ProcBodyNodes: TAVLTree;
AVLNode: TAVLTreeNode;
@ -4029,7 +4032,7 @@ begin
Result:=false;
ProcBodyNodes:=TAVLTree.Create(@CompareCodeTreeNodeExt);
try
Result:=FindEmptyMethods(CursorPos,Sections,ProcBodyNodes,AllEmpty);
Result:=FindEmptyMethods(CursorPos,AClassName,Sections,ProcBodyNodes,AllEmpty);
if Result then begin
AVLNode:=ProcBodyNodes.FindLowest;
while AVLNode<>nil do begin
@ -4049,7 +4052,8 @@ begin
end;
function TCodeCompletionCodeTool.FindEmptyMethods(CursorPos: TCodeXYPosition;
const Sections: TPascalClassSections; CodeTreeNodeExtensions: TAVLTree;
const AClassName: string; const Sections: TPascalClassSections;
CodeTreeNodeExtensions: TAVLTree;
out AllEmpty: boolean): boolean;
// NodeExt.Node is the body node
// NodeExt.Data is the definition node
@ -4080,9 +4084,15 @@ var
begin
Result:=false;
AllEmpty:=false;
BuildTreeAndGetCleanPos(trAll,CursorPos,CleanCursorPos,[]);
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
CodeCompleteClassNode:=FindClassNode(CursorNode);
if (AClassName<>'') and (CursorPos.Y<1) then begin
BuildTree(false);
CursorNode:=FindClassNodeInInterface(AClassName,true,false,true);
CodeCompleteClassNode:=CursorNode;
end else begin
BuildTreeAndGetCleanPos(trAll,CursorPos,CleanCursorPos,[]);
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
CodeCompleteClassNode:=FindClassNode(CursorNode);
end;
if FCodeCompleteClassNode=nil then begin
DebugLn(['TCodeCompletionCodeTool.FindEmptyMethods no class at ',DbgsCXY(CursorPos)]);
exit;
@ -4141,7 +4151,8 @@ begin
end;
function TCodeCompletionCodeTool.RemoveEmptyMethods(CursorPos: TCodeXYPosition;
const Sections: TPascalClassSections; SourceChangeCache: TSourceChangeCache;
const AClassName: string; const Sections: TPascalClassSections;
SourceChangeCache: TSourceChangeCache;
out AllRemoved: boolean;
const Attr: TProcHeadAttributes; out RemovedProcHeads: TStrings): boolean;
var
@ -4166,9 +4177,10 @@ begin
RemovedProcHeads:=nil;
if (SourceChangeCache=nil) or (Scanner=nil) then exit;
SourceChangeCache.MainScanner:=Scanner;
ProcDefNodes:=nil;
ProcBodyNodes:=TAVLTree.Create(@CompareCodeTreeNodeExt);
try
Result:=FindEmptyMethods(CursorPos,Sections,ProcBodyNodes,AllRemoved);
Result:=FindEmptyMethods(CursorPos,AClassName,Sections,ProcBodyNodes,AllRemoved);
if Result and (ProcBodyNodes<>nil) and (ProcBodyNodes.Count>0) then begin
// sort the nodes for position
ProcBodyNodes.OnCompare:=@CompareCodeTreeNodeExtWithPos;

View File

@ -477,11 +477,13 @@ type
TreeOfCodeTreeNodeExt: TAVLTree): boolean;
function ReplaceAllTypeCastFunctions(Code: TCodeBuffer): boolean;
function FixForwardDefinitions(Code: TCodeBuffer): boolean;
function FindEmptyMethods(Code: TCodeBuffer; X,Y: integer;
function FindEmptyMethods(Code: TCodeBuffer;
const AClassName: string; X,Y: integer;
const Sections: TPascalClassSections;
ListOfPCodeXYPosition: TFPList;
out AllEmpty: boolean): boolean;
function RemoveEmptyMethods(Code: TCodeBuffer; X,Y: integer;
function RemoveEmptyMethods(Code: TCodeBuffer;
const AClassName: string; X,Y: integer;
const Sections: TPascalClassSections;
out AllRemoved: boolean;
const Attr: TProcHeadAttributes;
@ -3430,7 +3432,8 @@ begin
end;
end;
function TCodeToolManager.FindEmptyMethods(Code: TCodeBuffer; X, Y: integer;
function TCodeToolManager.FindEmptyMethods(Code: TCodeBuffer;
const AClassName: string; X, Y: integer;
const Sections: TPascalClassSections; ListOfPCodeXYPosition: TFPList;
out AllEmpty: boolean): boolean;
var
@ -3445,14 +3448,15 @@ begin
CursorPos.Y:=Y;
CursorPos.Code:=Code;
try
Result:=FCurCodeTool.FindEmptyMethods(CursorPos,Sections,
Result:=FCurCodeTool.FindEmptyMethods(CursorPos,AClassName,Sections,
ListOfPCodeXYPosition,AllEmpty);
except
on e: Exception do Result:=HandleException(e);
end;
end;
function TCodeToolManager.RemoveEmptyMethods(Code: TCodeBuffer; X,Y: integer;
function TCodeToolManager.RemoveEmptyMethods(Code: TCodeBuffer;
const AClassName: string; X,Y: integer;
const Sections: TPascalClassSections; out AllRemoved: boolean;
const Attr: TProcHeadAttributes; out RemovedProcHeads: TStrings): boolean;
var
@ -3467,7 +3471,7 @@ begin
CursorPos.Y:=Y;
CursorPos.Code:=Code;
try
Result:=FCurCodeTool.RemoveEmptyMethods(CursorPos,Sections,
Result:=FCurCodeTool.RemoveEmptyMethods(CursorPos,AClassName,Sections,
SourceChangeCache,AllRemoved,Attr,RemovedProcHeads);
except
on e: Exception do Result:=HandleException(e);

View File

@ -76,6 +76,10 @@ type
function ShowEmptyMethodsDialog: TModalResult;
function RemoveEmptyMethods(Code: TCodeBuffer; AClassName: string;
X, Y: integer; CommitSrcEditor: boolean; Sections: TPascalClassSections
): TModalResult;
implementation
@ -106,7 +110,7 @@ begin
ErrMsg:='';
// check cursor is in a class
if not CodeToolBoss.FindEmptyMethods(Code,Caret.X,Caret.Y,
if not CodeToolBoss.FindEmptyMethods(Code,'',Caret.X,Caret.Y,
AllPascalClassSections,ListOfPCodeXYPosition,AllEmpty)
then begin
DebugLn(['ShowEmptyMethodsDialog CodeToolBoss.FindEmptyMethods failed']);
@ -141,28 +145,9 @@ begin
end;
end;
{ TEmptyMethodsDialog }
procedure TEmptyMethodsDialog.FormCreate(Sender: TObject);
begin
Caption:=lisEMDEmtpyMethods;
SectionsGroupBox.Caption:=lisEMDSearchInTheseClassSections;
PrivateCheckBox.Caption:=lisPrivate;
ProtectedCheckBox.Caption:=lisProtected;
PublicCheckBox.Caption:=lisEMDPublic;
PublishedCheckBox.Caption:=lisEMDPublished;
AllButton.Caption:=lisEMDAll;
PublishedButton.Caption:=lisEMDOnlyPublished;
MethodsGroupBox.Caption:=lisEMDFoundEmptyMethods;
Sections:=AllPascalClassSections;
ButtonPanel1.OKButton.OnClick:=@OKButtonClick;
ButtonPanel1.OKButton.Caption:=lisEMDRemoveMethods;
EditorOpts.GetSynEditSettings(MethodsSynEdit);
end;
procedure TEmptyMethodsDialog.OKButtonClick(Sender: TObject);
function RemoveEmptyMethods(Code: TCodeBuffer; AClassName: string;
X, Y: integer; CommitSrcEditor: boolean; Sections: TPascalClassSections
): TModalResult;
var
RemovedProcHeads: TStrings;
PropChanged: boolean;
@ -223,7 +208,7 @@ var
and (SysUtils.CompareText(RemovedProcHeads[i],AMethodName)<>0) do
dec(i);
if i>=0 then begin
DebugLn(['TEmptyMethodsDialog.OKButtonClick Clearing Property=',PropInfo^.Name,' AMethodName=',AMethodName]);
DebugLn(['RemoveEmptyMethods Clearing Property=',PropInfo^.Name,' AMethodName=',AMethodName]);
FillByte(AMethod,SizeOf(AMethod),0);
SetMethodProp(AComponent,PropInfo,AMethod);
PropChanged:=true;
@ -244,31 +229,31 @@ var
LookupRoot: TComponent;
CurClassName: String;
begin
Result:=mrCancel;
if CommitSrcEditor and (not LazarusIDE.BeginCodeTools) then exit;
//DebugLn(['TEmptyMethodsDialog.OKButtonClick ']);
RemovedProcHeads:=nil;
try
if (not CodeToolBoss.RemoveEmptyMethods(Code,Caret.X,Caret.Y,Sections,
AllEmpty,
if (not CodeToolBoss.RemoveEmptyMethods(Code,AClassName,X,Y,
Sections,AllEmpty,
[phpAddClassName,phpDoNotAddSemicolon,phpWithoutParamList,
phpWithoutBrackets,phpWithoutClassKeyword,phpWithoutSemicolon],
RemovedProcHeads))
then begin
DebugLn(['TEmptyMethodsDialog.OKButtonClick failed']);
DebugLn(['RemoveEmptyMethods failed']);
exit;
end;
if (RemovedProcHeads<>nil) and (RemovedProcHeads.Count>0) then begin
// RemovedProcHeads contains a list of classname.procname
// remove the classname from the list
CurClassName:=ExtractClassName;
//DebugLn(['TEmptyMethodsDialog.OKButtonClick CurClassName=',CurClassName]);
if CurClassName<>'' then begin
if (Project1<>nil) then begin
AnUnitInfo:=Project1.UnitInfoWithFilename(Code.Filename);
//DebugLn(['TEmptyMethodsDialog.OKButtonClick AnUnitInfo=',AnUnitInfo<>nil]);
if AnUnitInfo<>nil then begin
// fix events of designer components
LookupRoot:=AnUnitInfo.Component;
//DebugLn(['TEmptyMethodsDialog.OKButtonClick LookupRoot=',DbgSName(LookupRoot)]);
if (LookupRoot<>nil)
and (SysUtils.CompareText(LookupRoot.ClassName,CurClassName)=0) then
begin
@ -287,6 +272,33 @@ begin
finally
RemovedProcHeads.Free;
end;
Result:=mrOk;
end;
{ TEmptyMethodsDialog }
procedure TEmptyMethodsDialog.FormCreate(Sender: TObject);
begin
Caption:=lisEMDEmtpyMethods;
SectionsGroupBox.Caption:=lisEMDSearchInTheseClassSections;
PrivateCheckBox.Caption:=lisPrivate;
ProtectedCheckBox.Caption:=lisProtected;
PublicCheckBox.Caption:=lisEMDPublic;
PublishedCheckBox.Caption:=lisEMDPublished;
AllButton.Caption:=lisEMDAll;
PublishedButton.Caption:=lisEMDOnlyPublished;
MethodsGroupBox.Caption:=lisEMDFoundEmptyMethods;
Sections:=AllPascalClassSections;
ButtonPanel1.OKButton.OnClick:=@OKButtonClick;
ButtonPanel1.OKButton.Caption:=lisEMDRemoveMethods;
EditorOpts.GetSynEditSettings(MethodsSynEdit);
end;
procedure TEmptyMethodsDialog.OKButtonClick(Sender: TObject);
begin
if RemoveEmptyMethods(Code,'',Caret.X,Caret.Y,true,Sections)<>mrOk then exit;
ModalResult:=mrOk;
end;
@ -349,7 +361,7 @@ begin
CurSections:=Sections;
ListOfPCodeXYPosition:=TFPList.Create;
try
if (not CodeToolBoss.FindEmptyMethods(Code,Caret.X,Caret.Y,
if (not CodeToolBoss.FindEmptyMethods(Code,'',Caret.X,Caret.Y,
CurSections,ListOfPCodeXYPosition,AllEmpty))
or (not CodeToolBoss.Explore(Code,Tool,false))
then begin

View File

@ -7151,9 +7151,15 @@ begin
// save source
// a) do before save events
if EditorOpts.AutoRemoveEmptyMethods then
ActiveUnitInfo.RemoveEmptyMethods;
if EditorOpts.AutoRemoveEmptyMethods
and (ActiveUnitInfo.Component<>nil) then begin
// Note: When removing published methods, the source, the lfm, the lrs
// and the form must be changed. At the moment editing the lfm without
// the component is not yet implemented.
Result:=RemoveEmptyMethods(ActiveUnitInfo.Source,
ActiveUnitInfo.Component.ClassName,0,0,false,[pcsPublished]);
if Result<>mrOk then exit;
end;
// b) do actual save
if (sfSaveToTestDir in Flags) or ActiveUnitInfo.IsVirtual then

View File

@ -299,7 +299,6 @@ type
function FindAncestorUnit: TUnitInfo;
procedure ClearUnitComponentDependencies(
ClearTypes: TUnitCompDependencyTypes);
procedure RemoveEmptyMethods;
public
{ Properties }
// Unit lists
@ -1613,134 +1612,6 @@ begin
end;
end;
procedure TUnitInfo.RemoveEmptyMethods;
var
RemovedProcHeads: TStringList;
PropChanged: boolean;
procedure CheckEvents(LookupRoot, AComponent: TComponent);
var
TypeInfo: PTypeInfo;
TypeData: PTypeData;
PropInfo: PPropInfo;
CurCount: Word;
AMethod: TMethod;
AMethodName: String;
i: Integer;
begin
// read all properties and remove doubles
TypeInfo:=PTypeInfo(AComponent.ClassInfo);
repeat
// read all property infos of current class
TypeData:=GetTypeData(TypeInfo);
// skip unitname
PropInfo:=PPropInfo(PByte(@TypeData^.UnitName)+Length(TypeData^.UnitName)+1);
// read property count
CurCount:=PWord(PropInfo)^;
inc(PtrUInt(PropInfo),SizeOf(Word));
// read properties
while CurCount>0 do
begin
// point PropInfo to next propinfo record.
// Located at Name[Length(Name)+1] !
if (PropInfo^.PropType^.Kind=tkMethod) then
begin
// event
AMethod:=GetMethodProp(AComponent,PropInfo);
AMethodName:=GlobalDesignHook.GetMethodName(AMethod,nil);
if AMethodName<>'' then
begin
i:=RemovedProcHeads.Count-1;
while (i>=0)
and (SysUtils.CompareText(RemovedProcHeads[i],AMethodName)<>0) do
dec(i);
if i>=0 then
begin
FillByte(AMethod,SizeOf(AMethod),0);
SetMethodProp(AComponent,PropInfo,AMethod);
PropChanged:=true;
end;
end;
end;
PropInfo:=PPropInfo(pointer(@PropInfo^.Name)+PByte(@PropInfo^.Name)^+1);
dec(CurCount);
end;
TypeInfo:=TypeData^.ParentInfo;
until TypeInfo=nil;
end;
function ExtractClassName: string;
var
ProcName: string;
p: LongInt;
i: Integer;
begin
Result := '';
if (RemovedProcHeads = nil) or (RemovedProcHeads.Count = 0) then
Exit;
for i := RemovedProcHeads.Count - 1 downto 0 do
begin
ProcName := RemovedProcHeads[i];
p := System.Pos('.',ProcName);
if p < 1 then
RemovedProcHeads.Delete(i)
else
begin
Result := copy(ProcName,1,p-1);
RemovedProcHeads[i] := copy(ProcName, p + 1, length(ProcName));
end;
end;
end;
var
Node: TCodeTreeNode;
Caret: TCodeXYPosition;
AllEmpty: Boolean;
i: Integer;
CurClassName: String;
begin
if (Component = nil) or not LazarusIDE.BeginCodeTools then
Exit;
Node := CodeToolBoss.CurCodeTool.FindClassNodeInInterface(Component.ClassName,
True, False, False);
if (Node = nil) or
not CodeToolBoss.CurCodeTool.CleanPosToCaret(Node.StartPos, Caret) then
Exit;
RemovedProcHeads := nil;
try
if not CodeToolBoss.RemoveEmptyMethods(Source, Caret.X, Caret.Y,
[pcsPublished], AllEmpty,
[phpAddClassName,phpDoNotAddSemicolon,phpWithoutParamList,
phpWithoutBrackets,phpWithoutClassKeyword,phpWithoutSemicolon],
RemovedProcHeads) then
begin
DebugLn(['TUnitInfo.RemoveEmptyMethods failed']);
exit;
end;
if (RemovedProcHeads <> nil) and (RemovedProcHeads.Count > 0) then
begin
// RemovedProcHeads contains a list of classname.procname
// remove the classname from the list
CurClassName := ExtractClassName;
if CurClassName = Component.ClassName then
begin;
PropChanged := False;
CheckEvents(Component, Component);
for i := 0 to Component.ComponentCount - 1 do
CheckEvents(Component, Component.Components[i]);
// update objectinspector
if PropChanged and (GlobalDesignHook.LookupRoot = Component) then
GlobalDesignHook.RefreshPropertyValues;
end;
end;
finally
RemovedProcHeads.Free;
end;
end;
function TUnitInfo.ReadOnly: boolean;
begin
Result:=UserReadOnly or FileReadOnly;