mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-08 00:02:03 +02:00
IDE+codetools: started heuristic to find unused units
git-svn-id: trunk@19281 -
This commit is contained in:
parent
b96aabcd76
commit
26ef5cd496
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -2824,6 +2824,9 @@ ide/unitdependencies.pas svneol=native#text/pascal
|
||||
ide/unitinfodlg.lfm svneol=native#text/plain
|
||||
ide/unitinfodlg.lrs svneol=native#text/plain
|
||||
ide/unitinfodlg.pp svneol=native#text/pascal
|
||||
ide/unusedunitsdlg.lfm svneol=native#text/plain
|
||||
ide/unusedunitsdlg.lrs svneol=native#text/plain
|
||||
ide/unusedunitsdlg.pas svneol=native#text/plain
|
||||
ide/version.inc svneol=native#text/plain
|
||||
ide/versioninfoadditionalinfo.lfm svneol=native#text/plain
|
||||
ide/versioninfoadditionalinfo.lrs svneol=native#text/plain
|
||||
|
@ -488,6 +488,7 @@ type
|
||||
out AllRemoved: boolean;
|
||||
const Attr: TProcHeadAttributes;
|
||||
out RemovedProcHeads: TStrings): boolean;
|
||||
function FindUnusedUnits(Code: TCodeBuffer; Units: TStrings): boolean;
|
||||
|
||||
// custom class completion
|
||||
function InitClassCompletion(Code: TCodeBuffer;
|
||||
@ -3480,6 +3481,21 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.FindUnusedUnits(Code: TCodeBuffer; Units: TStrings
|
||||
): boolean;
|
||||
begin
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn('TCodeToolManager.FindEmptyMethods A ',Code.Filename);
|
||||
{$ENDIF}
|
||||
Result:=false;
|
||||
if not InitCurCodeTool(Code) then exit;
|
||||
try
|
||||
Result:=FCurCodeTool.FindUnusedUnits(Units);
|
||||
except
|
||||
on e: Exception do Result:=HandleException(e);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.InitClassCompletion(Code: TCodeBuffer;
|
||||
const UpperClassName: string; out CodeTool: TCodeTool): boolean;
|
||||
begin
|
||||
|
@ -1752,7 +1752,7 @@ begin
|
||||
UnitNamePos.EndPos-UnitNamePos.StartPos);
|
||||
if UnitInFilePos.StartPos>=1 then begin
|
||||
UnitInFilename:=copy(Src,UnitInFilePos.StartPos+1,
|
||||
UnitInFilePos.EndPos-UnitInFilePos.StartPos-2)
|
||||
UnitInFilePos.EndPos-UnitInFilePos.StartPos-2);
|
||||
end else
|
||||
UnitInFilename:='';
|
||||
NewPos.Code:=FindUnitSource(UnitName,UnitInFilename,true);
|
||||
|
@ -1787,7 +1787,7 @@ begin
|
||||
then
|
||||
RaiseException('[TPascalParserTool.MoveCursorToUsesStart] '
|
||||
+'internal error: invalid UsesNode');
|
||||
// search backwards through the uses section
|
||||
// search through the uses section
|
||||
MoveCursorToCleanPos(UsesNode.StartPos);
|
||||
ReadNextAtom;
|
||||
if (not UpAtomIs('USES')) and (not UpAtomIs('CONTAINS')) then
|
||||
|
@ -118,6 +118,7 @@ type
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
function CommentUnitsInUsesSections(MissingUnits: TStrings;
|
||||
SourceChangeCache: TSourceChangeCache): boolean;
|
||||
function FindUnusedUnits(Units: TStrings): boolean;
|
||||
|
||||
// lazarus resources
|
||||
function FindNextIncludeInInitialization(
|
||||
@ -1327,6 +1328,198 @@ begin
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function TStandardCodeTool.FindUnusedUnits(Units: TStrings): boolean;
|
||||
// returns a list of unitname=flags
|
||||
// flags are a comma separated list of words:
|
||||
// 'implementation': unit is in implementation uses section
|
||||
// 'used': an identifier of the interface is used
|
||||
// 'code': unit has non empty initialization/finalization section
|
||||
var
|
||||
Identifiers: TAVLTree;// all identifiers used in this unit
|
||||
|
||||
procedure RaiseUsesExpected;
|
||||
begin
|
||||
RaiseExceptionFmt(ctsStrExpectedButAtomFound,['"uses"',GetAtom]);
|
||||
end;
|
||||
|
||||
procedure RaiseStrConstExpected;
|
||||
begin
|
||||
RaiseExceptionFmt(ctsStrExpectedButAtomFound,[ctsStringConstant,GetAtom]);
|
||||
end;
|
||||
|
||||
function IsUnitAlreadyChecked(const AnUnitName: string): boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i:=0 to Units.Count-1 do
|
||||
if SysUtils.CompareText(Units.Names[i],AnUnitName)=0 then exit(true);
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
procedure GatherIdentifiers;
|
||||
var
|
||||
Node: TCodeTreeNode;
|
||||
Identifier: PChar;
|
||||
begin
|
||||
if Identifiers<>nil then exit;
|
||||
Identifiers:=TAVLTree.Create(@CompareIdentifierPtrs);
|
||||
Node:=Tree.Root;
|
||||
while Node<>nil do begin
|
||||
if (Node.Desc in [ctnBeginBlock,ctnAsmBlock])
|
||||
or ((Node.FirstChild=nil)
|
||||
and (Node.Desc in [ctnIdentifier,ctnRangedArrayType,ctnOpenArrayType,
|
||||
ctnOfConstType,ctnRecordVariant,ctnProcedureType,ctnRangeType,
|
||||
ctnTypeType,ctnFileType,ctnPointerType,ctnClassOfType,
|
||||
ctnSpecializeParams,ctnGenericParameter,ctnConstant]))
|
||||
then begin
|
||||
MoveCursorToNodeStart(Node);
|
||||
repeat
|
||||
ReadNextAtom;
|
||||
if CurPos.StartPos>=Node.EndPos then break;
|
||||
if IsIdentStartChar[Src[CurPos.StartPos]] then begin
|
||||
Identifier:=@Src[CurPos.StartPos];
|
||||
if Identifiers.Find(Identifier)=nil then begin
|
||||
DebugLn(['GatherIdentifiers ',GetIdentifier(Identifier)]);
|
||||
Identifiers.Add(Identifier);
|
||||
end;
|
||||
end;
|
||||
until false;
|
||||
Node:=Node.NextSkipChilds;
|
||||
end else
|
||||
Node:=Node.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
function InterfaceIsUsed(Tool: TFindDeclarationTool;
|
||||
IntfNode: TCodeTreeNode): boolean;
|
||||
|
||||
function IsIdentifierUsed(StartPos: integer): boolean;
|
||||
begin
|
||||
Result:=Identifiers.Find(@Tool.Src[StartPos])<>nil;
|
||||
end;
|
||||
|
||||
var
|
||||
Node: TCodeTreeNode;
|
||||
begin
|
||||
Result:=true;
|
||||
Node:=IntfNode.FirstChild;
|
||||
while Node<>nil do begin
|
||||
case Node.Desc of
|
||||
ctnEnumIdentifier:
|
||||
if IsIdentifierUsed(Node.StartPos) then exit;
|
||||
end;
|
||||
Node:=Node.Next;
|
||||
end;
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
procedure CheckUnit(Tool: TFindDeclarationTool;
|
||||
out HasCode, UseInterface: boolean);
|
||||
var
|
||||
Node: TCodeTreeNode;
|
||||
Identifier: String;
|
||||
begin
|
||||
GatherIdentifiers;
|
||||
HasCode:=false;
|
||||
UseInterface:=false;
|
||||
// parse used unit
|
||||
Tool.BuildTree(false);
|
||||
Node:=Tool.Tree.Root;
|
||||
while (Node<>nil) do begin
|
||||
case Node.Desc of
|
||||
ctnUnit,ctnPackage,ctnLibrary:
|
||||
begin
|
||||
Identifier:=Tool.ExtractSourceName;
|
||||
if Identifiers.Find(PChar(Identifier))<>nil then
|
||||
UseInterface:=true;
|
||||
end;
|
||||
ctnInterface:
|
||||
if not UseInterface then
|
||||
UseInterface:=InterfaceIsUsed(Tool,Node);
|
||||
ctnInitialization,ctnFinalization,ctnBeginBlock:
|
||||
begin
|
||||
HasCode:=true;
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
Node:=Node.NextBrother;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure CheckUsesSection(UsesNode: TCodeTreeNode; InImplementation: boolean);
|
||||
var
|
||||
UnitNamePos: TAtomPosition;
|
||||
UnitInFilePos: TAtomPosition;
|
||||
UnitName: String;
|
||||
UnitInFilename: String;
|
||||
Tool: TFindDeclarationTool;
|
||||
HasCode: boolean;
|
||||
UseInterface: boolean;
|
||||
Flags: String;
|
||||
begin
|
||||
HasCode:=false;
|
||||
UseInterface:=false;
|
||||
if UsesNode=nil then exit;
|
||||
MoveCursorToNodeStart(UsesNode);
|
||||
ReadNextAtom;
|
||||
if not UpAtomIs('USES') then
|
||||
RaiseUsesExpected;
|
||||
repeat
|
||||
ReadNextAtom; // read name
|
||||
if AtomIsChar(';') then break;
|
||||
AtomIsIdentifier(true);
|
||||
UnitNamePos:=CurPos;
|
||||
ReadNextAtom;
|
||||
if UpAtomIs('IN') then begin
|
||||
ReadNextAtom;
|
||||
if not AtomIsStringConstant then RaiseStrConstExpected;
|
||||
UnitInFilePos:=CurPos;
|
||||
ReadNextAtom;
|
||||
end else
|
||||
UnitInFilePos.StartPos:=-1;
|
||||
UnitName:=copy(Src,UnitNamePos.StartPos,
|
||||
UnitNamePos.EndPos-UnitNamePos.StartPos);
|
||||
if not IsUnitAlreadyChecked(UnitName) then begin
|
||||
if UnitInFilePos.StartPos>=1 then begin
|
||||
UnitInFilename:=copy(Src,UnitInFilePos.StartPos+1,
|
||||
UnitInFilePos.EndPos-UnitInFilePos.StartPos-2);
|
||||
end else
|
||||
UnitInFilename:='';
|
||||
// try to load the used unit
|
||||
DebugLn(['CheckUsesSection ',UnitName,UnitInFilename]);
|
||||
Tool:=FindCodeToolForUsedUnit(UnitName,UnitInFilename,true);
|
||||
// parse the used unit
|
||||
CheckUnit(Tool,HasCode,UseInterface);
|
||||
Flags:='';
|
||||
if InImplementation then
|
||||
Flags:=Flags+',implementation';
|
||||
if HasCode then
|
||||
Flags:=Flags+',code';
|
||||
if UseInterface then
|
||||
Flags:=Flags+',used';
|
||||
DebugLn(['CheckUsesSection ',UnitName,'=',Flags]);
|
||||
Units.Add(UnitName+'='+Flags);
|
||||
end;
|
||||
if AtomIsChar(';') then break;
|
||||
if not AtomIsChar(',') then
|
||||
RaiseExceptionFmt(ctsStrExpectedButAtomFound,[';',GetAtom])
|
||||
until (CurPos.StartPos>SrcLen);
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:=false;
|
||||
DebugLn(['TStandardCodeTool.FindUnusedUnits ']);
|
||||
BuildTree(false);
|
||||
Identifiers:=nil;
|
||||
try
|
||||
CheckUsesSection(FindMainUsesSection,false);
|
||||
CheckUsesSection(FindImplementationUsesSection,true);
|
||||
finally
|
||||
Identifiers.Free;
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function TStandardCodeTool.FindNextIncludeInInitialization(
|
||||
var LinkIndex: integer): TCodeBuffer;
|
||||
// LinkIndex < 0 -> search first
|
||||
|
@ -94,6 +94,7 @@ var
|
||||
ListOfPCodeXYPosition: TFPList;
|
||||
AllEmpty: boolean;
|
||||
begin
|
||||
Result:=mrCancel;
|
||||
ListOfPCodeXYPosition:=TFPList.Create;
|
||||
try
|
||||
// init codetools
|
||||
|
@ -403,6 +403,7 @@ begin
|
||||
ecGotoIncludeDirective: SetResult(VK_UNKNOWN,[],VK_UNKNOWN,[]);
|
||||
ecShowAbstractMethods: SetResult(VK_UNKNOWN,[],VK_UNKNOWN,[]);
|
||||
ecRemoveEmptyMethods: SetResult(VK_UNKNOWN,[],VK_UNKNOWN,[]);
|
||||
ecRemoveUnusedUnits: SetResult(VK_UNKNOWN,[],VK_UNKNOWN,[]);
|
||||
|
||||
// source notebook
|
||||
ecNextEditor: SetResult(VK_TAB, [ssCtrl], VK_UNKNOWN, []);
|
||||
@ -1760,6 +1761,7 @@ begin
|
||||
ecFindBlockStart : Result:= srkmecFindBlockStart;
|
||||
ecShowAbstractMethods : Result:= srkmecShowAbstractMethods;
|
||||
ecRemoveEmptyMethods : Result:= srkmecRemoveEmptyMethods;
|
||||
ecRemoveUnusedUnits : Result:= srkmecRemoveEmptyMethods;
|
||||
|
||||
// project (menu string resource)
|
||||
ecNewProject : Result:= lisMenuNewProject;
|
||||
@ -2220,6 +2222,8 @@ begin
|
||||
ecShowAbstractMethods);
|
||||
AddDefault(C, 'Remove empty methods', srkmecRemoveEmptyMethods,
|
||||
ecRemoveEmptyMethods);
|
||||
AddDefault(C, 'Remove unused units', srkmecRemoveUnusedUnits,
|
||||
ecRemoveUnusedUnits);
|
||||
|
||||
// source notebook - without menu items in the IDE bar
|
||||
C:=Categories[AddCategory('SourceNotebook',srkmCatSrcNoteBook,
|
||||
|
@ -1785,6 +1785,7 @@ resourcestring
|
||||
lisUEDoNotSho = 'Do not show this message again.';
|
||||
uemInsertTodo = 'Insert Todo';
|
||||
lisCodeHelpShowEmptyMethods = 'Show empty methods';
|
||||
lisCodeHelpShowUnusedUnits = 'Show unused units';
|
||||
uemHighlighter = 'Highlighter';
|
||||
uemEncoding = 'Encoding';
|
||||
|
||||
@ -2076,6 +2077,7 @@ resourcestring
|
||||
srkmecFindBlockStart = 'Find block start';
|
||||
srkmecShowAbstractMethods = 'Show abstract methods';
|
||||
srkmecRemoveEmptyMethods = 'Remove empty methods';
|
||||
srkmecRemoveUnusedUnits = 'Remove unused units';
|
||||
|
||||
// run menu
|
||||
srkmecBuild = 'build program/project';
|
||||
|
12
ide/main.pp
12
ide/main.pp
@ -133,8 +133,9 @@ uses
|
||||
ProcessList, InitialSetupDlgs, NewDialog, MakeResStrDlg, ToDoList,
|
||||
DialogProcs, FindReplaceDialog, FindInFilesDlg, CodeExplorer, BuildFileDlg,
|
||||
ProcedureList, ExtractProcDlg, FindRenameIdentifier, AbstractsMethodsDlg,
|
||||
EmptyMethodsDlg, CleanDirDlg, CodeContextForm, AboutFrm, BuildManager,
|
||||
EmptyMethodsDlg, UnusedUnitsDlg, CleanDirDlg, CodeContextForm, AboutFrm,
|
||||
CompatibilityRestrictions, RestrictionBrowser, ProjectWizardDlg, IDECmdLine,
|
||||
BuildManager,
|
||||
// main ide
|
||||
MainBar, MainIntf, MainBase;
|
||||
|
||||
@ -864,6 +865,7 @@ type
|
||||
NewFilename, NewUnitName: string): TModalResult;
|
||||
function DoShowAbstractMethods: TModalResult;
|
||||
function DoRemoveEmptyMethods: TModalResult;
|
||||
function DoRemoveUnusedUnits: TModalResult;
|
||||
function DoInitIdentCompletion(JumpToError: boolean): boolean;
|
||||
function DoShowCodeContext(JumpToError: boolean): boolean;
|
||||
procedure DoCompleteCodeAtCursor;
|
||||
@ -2771,6 +2773,9 @@ begin
|
||||
ecRemoveEmptyMethods:
|
||||
DoRemoveEmptyMethods;
|
||||
|
||||
ecRemoveUnusedUnits:
|
||||
DoRemoveUnusedUnits;
|
||||
|
||||
ecFindBlockOtherEnd:
|
||||
DoGoToPascalBlockOtherEnd;
|
||||
|
||||
@ -12713,6 +12718,11 @@ begin
|
||||
Result:=ShowEmptyMethodsDialog;
|
||||
end;
|
||||
|
||||
function TMainIDE.DoRemoveUnusedUnits: TModalResult;
|
||||
begin
|
||||
Result:=ShowUnusedUnitsDialog;
|
||||
end;
|
||||
|
||||
{-------------------------------------------------------------------------------
|
||||
function TMainIDE.DoInitIdentCompletion(JumpToError: boolean): boolean;
|
||||
-------------------------------------------------------------------------------}
|
||||
|
@ -433,6 +433,7 @@ type
|
||||
procedure RenameIdentifierMenuItemClick(Sender: TObject);
|
||||
procedure ShowAbstractMethodsMenuItemClick(Sender: TObject);
|
||||
procedure ShowEmptyMethodsMenuItemClick(Sender: TObject);
|
||||
procedure ShowUnusedUnitsMenuItemClick(Sender: TObject);
|
||||
procedure RunToClicked(Sender: TObject);
|
||||
procedure ViewCallStackClick(Sender: TObject);
|
||||
procedure AddWatchAtCursor(Sender: TObject);
|
||||
@ -857,6 +858,7 @@ var
|
||||
SrcEditMenuInvertAssignment: TIDEMenuCommand;
|
||||
SrcEditMenuShowAbstractMethods: TIDEMenuCommand;
|
||||
SrcEditMenuShowEmptyMethods: TIDEMenuCommand;
|
||||
SrcEditMenuShowUnusedUnits: TIDEMenuCommand;
|
||||
SrcEditMenuInsertTodo: TIDEMenuCommand;
|
||||
SrcEditMenuMoveEditorLeft: TIDEMenuCommand;
|
||||
SrcEditMenuMoveEditorRight: TIDEMenuCommand;
|
||||
@ -1015,9 +1017,14 @@ begin
|
||||
'ShowAbstractMethods',srkmecShowAbstractMethods);
|
||||
SrcEditMenuShowEmptyMethods:=RegisterIDEMenuCommand(AParent,
|
||||
'ShowEmptyMethods', lisCodeHelpShowEmptyMethods);
|
||||
SrcEditMenuShowUnusedUnits:=RegisterIDEMenuCommand(AParent,
|
||||
'ShowUnusedUnits', lisCodeHelpShowUnusedUnits);
|
||||
{$IFNDEF EnableUnusedUnits}
|
||||
SrcEditMenuShowUnusedUnits.Visible:=false;
|
||||
{$ENDIF}
|
||||
|
||||
SrcEditMenuInsertTodo:=RegisterIDEMenuCommand(SourceEditorMenuRoot,
|
||||
'InsertTodo',uemInsertTodo, nil, nil, nil, 'item_todo');
|
||||
'InsertTodo',uemInsertTodo, nil, nil, nil, 'item_todo');
|
||||
|
||||
// register the Flags section
|
||||
SrcEditSubMenuFlags:=RegisterIDESubMenu(SourceEditorMenuRoot,
|
||||
@ -4383,6 +4390,7 @@ begin
|
||||
SrcEditMenuRenameIdentifier.OnClick:=@RenameIdentifierMenuItemClick;
|
||||
SrcEditMenuShowAbstractMethods.OnClick:=@ShowAbstractMethodsMenuItemClick;
|
||||
SrcEditMenuShowEmptyMethods.OnClick:=@ShowEmptyMethodsMenuItemClick;
|
||||
SrcEditMenuShowUnusedUnits.OnClick:=@ShowUnusedUnitsMenuItemClick;
|
||||
|
||||
SrcEditMenuReadOnly.OnClick:=@ReadOnlyClicked;
|
||||
SrcEditMenuShowLineNumbers.OnClick:=@ToggleLineNumbersClicked;
|
||||
@ -5627,6 +5635,11 @@ begin
|
||||
MainIDEInterface.DoCommand(ecRemoveEmptyMethods);
|
||||
end;
|
||||
|
||||
procedure TSourceNotebook.ShowUnusedUnitsMenuItemClick(Sender: TObject);
|
||||
begin
|
||||
MainIDEInterface.DoCommand(ecRemoveUnusedUnits);
|
||||
end;
|
||||
|
||||
procedure TSourceNotebook.RunToClicked(Sender: TObject);
|
||||
var
|
||||
ASrcEdit: TSourceEditor;
|
||||
|
28
ide/unusedunitsdlg.lfm
Normal file
28
ide/unusedunitsdlg.lfm
Normal file
@ -0,0 +1,28 @@
|
||||
object UnusedUnitsDialog: TUnusedUnitsDialog
|
||||
Left = 375
|
||||
Height = 365
|
||||
Top = 236
|
||||
Width = 340
|
||||
Caption = 'UnusedUnitsDialog'
|
||||
ClientHeight = 365
|
||||
ClientWidth = 340
|
||||
OnCreate = FormCreate
|
||||
LCLVersion = '0.9.27'
|
||||
object ButtonPanel1: TButtonPanel
|
||||
Left = 6
|
||||
Height = 44
|
||||
Top = 315
|
||||
Width = 328
|
||||
TabOrder = 0
|
||||
ShowButtons = [pbOK, pbCancel]
|
||||
end
|
||||
object UnitsTreeView: TTreeView
|
||||
Left = 0
|
||||
Height = 309
|
||||
Top = 0
|
||||
Width = 340
|
||||
Align = alClient
|
||||
DefaultItemHeight = 19
|
||||
TabOrder = 1
|
||||
end
|
||||
end
|
12
ide/unusedunitsdlg.lrs
Normal file
12
ide/unusedunitsdlg.lrs
Normal file
@ -0,0 +1,12 @@
|
||||
{ This is an automatically generated lazarus resource file }
|
||||
|
||||
LazarusResources.Add('TUnusedUnitsDialog','FORMDATA',[
|
||||
'TPF0'#18'TUnusedUnitsDialog'#17'UnusedUnitsDialog'#4'Left'#3'w'#1#6'Height'#3
|
||||
+'m'#1#3'Top'#3#236#0#5'Width'#3'T'#1#7'Caption'#6#17'UnusedUnitsDialog'#12'C'
|
||||
+'lientHeight'#3'm'#1#11'ClientWidth'#3'T'#1#8'OnCreate'#7#10'FormCreate'#10
|
||||
+'LCLVersion'#6#6'0.9.27'#0#12'TButtonPanel'#12'ButtonPanel1'#4'Left'#2#6#6'H'
|
||||
+'eight'#2','#3'Top'#3';'#1#5'Width'#3'H'#1#8'TabOrder'#2#0#11'ShowButtons'#11
|
||||
+#4'pbOK'#8'pbCancel'#0#0#0#9'TTreeView'#13'UnitsTreeView'#4'Left'#2#0#6'Heig'
|
||||
+'ht'#3'5'#1#3'Top'#2#0#5'Width'#3'T'#1#5'Align'#7#8'alClient'#17'DefaultItem'
|
||||
+'Height'#2#19#8'TabOrder'#2#1#0#0#0
|
||||
]);
|
112
ide/unusedunitsdlg.pas
Normal file
112
ide/unusedunitsdlg.pas
Normal file
@ -0,0 +1,112 @@
|
||||
{
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
Author: Mattias Gaertner
|
||||
|
||||
Abstract:
|
||||
A dialog showing the unused units of the current unit
|
||||
(at cursor in source editor).
|
||||
With the ability to remove them automatically.
|
||||
}
|
||||
unit UnusedUnitsDlg;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, LCLProc,FileUtil, LResources, Forms, Controls, Graphics,
|
||||
Dialogs, ButtonPanel, ComCtrls,
|
||||
SrcEditorIntf, LazIDEIntf,
|
||||
CodeCache, CodeToolManager,
|
||||
LazarusIDEStrConsts;
|
||||
|
||||
type
|
||||
|
||||
{ TUnusedUnitsDialog }
|
||||
|
||||
TUnusedUnitsDialog = class(TForm)
|
||||
ButtonPanel1: TButtonPanel;
|
||||
UnitsTreeView: TTreeView;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure OkClick(Sender: TObject);
|
||||
private
|
||||
{ private declarations }
|
||||
public
|
||||
{ public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
UnusedUnitsDialog: TUnusedUnitsDialog;
|
||||
|
||||
function ShowUnusedUnitsDialog: TModalResult;
|
||||
|
||||
implementation
|
||||
|
||||
function ShowUnusedUnitsDialog: TModalResult;
|
||||
var
|
||||
SrcEdit: TSourceEditorInterface;
|
||||
Code: TCodeBuffer;
|
||||
Units: TStringList;
|
||||
begin
|
||||
Result:=mrOk;
|
||||
if not LazarusIDE.BeginCodeTools then exit;
|
||||
|
||||
// get cursor position
|
||||
SrcEdit:=SourceEditorWindow.ActiveEditor;
|
||||
if SrcEdit=nil then exit;
|
||||
Code:=TCodeBuffer(SrcEdit.CodeToolsBuffer);
|
||||
if Code=nil then exit;
|
||||
|
||||
Units:=TStringList.Create;
|
||||
try
|
||||
if not CodeToolBoss.FindUnusedUnits(Code,Units) then begin
|
||||
DebugLn(['ShowUnusedUnitsDialog CodeToolBoss.FindUnusedUnits failed']);
|
||||
LazarusIDE.DoJumpToCodeToolBossError;
|
||||
exit(mrCancel);
|
||||
end;
|
||||
|
||||
|
||||
finally
|
||||
Units.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TUnusedUnitsDialog }
|
||||
|
||||
procedure TUnusedUnitsDialog.FormCreate(Sender: TObject);
|
||||
begin
|
||||
Caption:='Unused units';
|
||||
|
||||
ButtonPanel1.OKButton.Caption:='Remove selected units';
|
||||
ButtonPanel1.OKButton.OnClick:=@OkClick;
|
||||
ButtonPanel1.CancelButton.Caption:='Cancel';
|
||||
end;
|
||||
|
||||
procedure TUnusedUnitsDialog.OkClick(Sender: TObject);
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$I unusedunitsdlg.lrs}
|
||||
|
||||
end.
|
||||
|
@ -139,6 +139,7 @@ const
|
||||
ecShowCodeContext = ecFirstLazarus + 118;
|
||||
ecShowAbstractMethods = ecFirstLazarus + 119;
|
||||
ecRemoveEmptyMethods = ecFirstLazarus + 120;
|
||||
ecRemoveUnusedUnits = ecFirstLazarus + 121;
|
||||
|
||||
// file menu
|
||||
ecNew = ecFirstLazarus + 201;
|
||||
|
Loading…
Reference in New Issue
Block a user