cody: ppu list: uses count and used by count

git-svn-id: trunk@29469 -
This commit is contained in:
mattias 2011-02-11 18:32:32 +00:00
parent 6a17e32f7a
commit 12728e1833
4 changed files with 259 additions and 117 deletions

View File

@ -851,7 +851,7 @@ begin
DirectoryCachePool.OnIterateFPCUnitsFromSet:=@DirectoryCachePoolIterateFPCUnitsFromSet;
DefineTree.DirectoryCachePool:=DirectoryCachePool;
FPCDefinesCache:=TFPCDefinesCache.Create(nil);
PPUCache:=TPPUTools.Create(SourceCache);
PPUCache:=TPPUTools.Create;
FAddInheritedCodeToOverrideMethod:=true;
FAdjustTopLineDueToComment:=true;
FCatchExceptions:=true;

View File

@ -38,30 +38,48 @@ object PPUListDialog: TPPUListDialog
Align = alTop
AutoFillColumns = True
BorderSpacing.Around = 6
ColCount = 3
Columns = <
item
SizePriority = 10
Title.Caption = 'Unit'
Width = 199
Width = 119
end
item
SizePriority = 10
Title.Caption = 'Size of .ppu file'
Width = 199
Width = 119
end
item
SizePriority = 10
Title.Caption = 'Size of .o file'
Width = 201
Width = 119
end
item
SizePriority = 5
Title.Caption = 'Uses'
Width = 119
end
item
SizePriority = 5
Title.Caption = 'Used by'
Width = 123
end>
DefaultColWidth = 150
FixedCols = 0
FixedRows = 2
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goThumbTracking, goColSpanning, goDblClickAutoSize, goSmoothScroll]
TabOrder = 1
OnDblClick = UnitsStringGridDblClick
OnHeaderClick = UnitsStringGridHeaderClick
OnMouseDown = UnitsStringGridMouseDown
OnMouseUp = UnitsStringGridMouseUp
OnSelectCell = UnitsStringGridSelectCell
ColWidths = (
199
199
201
119
119
119
119
123
)
end
object ScopeLabel: TLabel
@ -99,9 +117,9 @@ object PPUListDialog: TPPUListDialog
Height = 162
Top = 0
Width = 593
ActivePage = UnitUsedByTabSheet
ActivePage = UnitUsesTabSheet
Align = alClient
TabIndex = 1
TabIndex = 0
TabOrder = 0
object UnitUsesTabSheet: TTabSheet
Caption = 'UnitUsesTabSheet'
@ -121,6 +139,7 @@ object PPUListDialog: TPPUListDialog
Width = 587
end>
FixedCols = 0
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goThumbTracking, goSmoothScroll]
TabOrder = 0
ColWidths = (
587
@ -142,12 +161,13 @@ object PPUListDialog: TPPUListDialog
Columns = <
item
Title.Caption = 'Unit'
Width = 587
Width = 589
end>
FixedCols = 0
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goThumbTracking, goSmoothScroll]
TabOrder = 0
ColWidths = (
587
589
)
end
end

View File

@ -37,11 +37,24 @@ uses
IDECommands, MenuIntf, ProjectIntf, LazIDEIntf, IDEDialogs, IDEWindowIntf,
// codetools
BasicCodeTools, FileProcs, CodyStrConsts, CodeToolManager, CodeCache,
PPUCodeTools;
PPUParser, PPUCodeTools;
const
PPUFileNotFound = ' ';
type
TPPUListSort = (
plsName,
plsNameReverse,
plsOSizeDescending,
plsOSizeAscending,
plsPPUSizeDescending,
plsPPUSizeAscending,
plsUsesCountDescending,
plsUsesCountAscending,
plsUsedByCountDescending,
plsUsedByCountAscending
);
TPPUListType = (
pltUsedBy,
pltUses
@ -60,6 +73,8 @@ type
UsesUnits: TStrings; // =nil means uses section not yet scanned
UsedByUnits: TStrings;
destructor Destroy; override;
function UsesCount: integer;
function UsedByCount: integer;
end;
{ TPPUListDialog }
@ -78,6 +93,13 @@ type
procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure UnitsStringGridDblClick(Sender: TObject);
procedure UnitsStringGridHeaderClick(Sender: TObject; IsColumn: Boolean;
Index: Integer);
procedure UnitsStringGridMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure UnitsStringGridMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure UnitsStringGridSelectCell(Sender: TObject; {%H-}aCol, aRow: Integer;
var {%H-}CanSelect: Boolean);
private
@ -85,6 +107,7 @@ type
FIdleConnected: boolean;
FSearchingItems: TAvgLvlTree; // tree of TPPUListItem sorted for TheUnitName
FItems: TAvgLvlTree; // tree of TPPUListItem sorted for TheUnitName
FSort: array[1..3] of TPPUListSort;
procedure SetProject(const AValue: TLazProject);
procedure SetIdleConnected(const AValue: boolean);
procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
@ -169,13 +192,32 @@ begin
inherited Destroy;
end;
function TPPUListItem.UsesCount: integer;
begin
if UsesUnits=nil then
Result:=0
else
Result:=UsesUnits.Count;
end;
function TPPUListItem.UsedByCount: integer;
begin
if UsedByUnits=nil then
Result:=0
else
Result:=UsedByUnits.Count;
end;
{ TPPUListDialog }
procedure TPPUListDialog.FormCreate(Sender: TObject);
begin
IdleConnected:=false;
FSearchingItems:=TAvgLvlTree.Create(@ComparePPUListItems);
FItems:=TAvgLvlTree.Create(@ComparePPUListItems);
FSort[1]:=plsOSizeDescending;
FSort[2]:=plsName;
FSort[3]:=plsPPUSizeDescending;
UnitUsesTabSheet.Caption:=crsUses;
UnitUsedByTabSheet.Caption:=crsUsedBy;
UnitPageControl.PageIndex:=0;
@ -190,6 +232,36 @@ begin
FreeAndNil(FItems);
end;
procedure TPPUListDialog.UnitsStringGridDblClick(Sender: TObject);
begin
end;
procedure TPPUListDialog.UnitsStringGridHeaderClick(Sender: TObject;
IsColumn: Boolean; Index: Integer);
begin
end;
procedure TPPUListDialog.UnitsStringGridMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Col: Longint;
Row: Longint;
begin
UnitsStringGrid.MouseToCell(X,Y,Col,Row);
if (Row<=1) and (Shift=[ssLeft,ssDouble]) then begin
// double left click => sort
end;
end;
procedure TPPUListDialog.UnitsStringGridMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
end;
procedure TPPUListDialog.UnitsStringGridSelectCell(Sender: TObject; aCol,
aRow: Integer; var CanSelect: Boolean);
var
@ -294,6 +366,8 @@ begin
Grid.Cells[0,0]:='Unit';
Grid.Cells[1, 0]:=crsSizeOfPpuFile;
Grid.Cells[2, 0]:=crsSizeOfOFile;
Grid.Cells[3, 0]:=crsUses;
Grid.Cells[4, 0]:=crsUsedBy;
SortedItems:=TAvgLvlTree.CreateObjectCompare(@CompareUnits);
@ -317,6 +391,8 @@ begin
Grid.Cells[0,1]:=crsTotal;
Grid.Cells[1,1]:=SizeToStr(TotalPPUBytes,1.0);
Grid.Cells[2,1]:=SizeToStr(TotalOBytes,1.0);
Grid.Cells[3,1]:='';
Grid.Cells[4,1]:='';
// fill grid
Row:=2;
@ -345,6 +421,12 @@ begin
s:=SizeToStr(Item.OFileSize,double(Item.OFileSize)/TotalOBytes);
Grid.Cells[2,Row]:=s;
// uses
Grid.Cells[3,Row]:=IntToStr(Item.UsesCount);
// used by
Grid.Cells[4,Row]:=IntToStr(Item.UsedByCount);
inc(Row);
Node:=SortedItems.FindSuccessor(Node);
end;
@ -393,19 +475,57 @@ end;
function TPPUListDialog.CompareUnits(Tree: TAvgLvlTree; Data1, Data2: Pointer
): integer;
function CompareInt(const a,b: int64; Reverse: boolean): integer;
begin
if a=b then exit(0);
if (a>b) xor Reverse then
Result:=-1
else
Result:=1;
end;
var
Item1: TPPUListItem absolute Data1;
Item2: TPPUListItem absolute Data2;
Size1: Int64;
Size2: Int64;
i: Integer;
begin
// compare size of .o file
Size1:=Max(0,Item1.OFileSize);
Size2:=Max(0,Item2.OFileSize);
if Size1>Size2 then exit(-1)
else if Size1<Size2 then exit(1);
// compare unit name
Result:=-SysUtils.CompareText(Item1.TheUnitName,Item2.TheUnitName);
Result:=0;
for i:=low(FSort) to High(FSort) do begin
case FSort[i] of
plsName,plsNameReverse:
begin
Result:=SysUtils.CompareText(Item1.TheUnitName,Item2.TheUnitName);
if FSort[i]=plsName then
Result:=-Result;
if Result<>0 then exit;
end;
plsOSizeAscending,plsOSizeDescending:
begin
Result:=CompareInt(Max(0,Item1.OFileSize),Max(0,Item2.OFileSize),
FSort[i]=plsOSizeAscending);
if Result<>0 then exit;
end;
plsPPUSizeAscending,plsPPUSizeDescending:
begin
Result:=CompareInt(Max(0,Item1.PPUFileSize),Max(0,Item2.PPUFileSize),
FSort[i]=plsPPUSizeAscending);
if Result<>0 then exit;
end;
plsUsesCountAscending,plsUsesCountDescending:
begin
Result:=CompareInt(Item1.UsesCount,Item2.UsesCount,
FSort[i]=plsUsesCountDescending);
if Result<>0 then exit;
end;
plsUsedByCountAscending,plsUsedByCountDescending:
begin
Result:=CompareInt(Item1.UsedByCount,Item2.UsedByCount,
FSort[i]=plsUsedByCountDescending);
if Result<>0 then exit;
end;
end;
end;
end;
procedure TPPUListDialog.FillUnitsInfo(AnUnitName: string);
@ -506,14 +626,15 @@ begin
Item.UsesUnits:=TStringList.Create;
if Item.UsedByUnits=nil then
Item.UsedByUnits:=TStringList.Create;
//debugln(['TPPUListDialog.OnIdle search used units of ',AnUnitName]);
debugln(['TPPUListDialog.OnIdle search used units of ',AnUnitName]);
// scan for used units
Scanned:=false;
if Item.PPUFile<>PPUFileNotFound then begin
//debugln(['TPPUListDialog.OnIdle search used units of ppu "',Item.PPUFile,'" ...']);
PPUTool:=CodeToolBoss.PPUCache.LoadFile(Item.PPUFile,true,false);
debugln(['TPPUListDialog.OnIdle search used units of ppu "',Item.PPUFile,'" ...']);
PPUTool:=CodeToolBoss.PPUCache.LoadFile(Item.PPUFile,
[ppInterfaceHeader,ppImplementationHeader]);
if (PPUTool<>nil) and (PPUTool.ErrorMsg='') then begin
//debugln(['TPPUListDialog.OnIdle parsed ppu "',Item.PPUFile,'"']);
debugln(['TPPUListDialog.OnIdle parsed ppu "',Item.PPUFile,'"']);
MainUsesSection:=nil;
ImplementationUsesSection:=nil;
try
@ -526,6 +647,8 @@ begin
MainUsesSection.Free;
ImplementationUsesSection.Free;
end;
end else begin
debugln(['TPPUListDialog.OnIdle failed loading ',Item.PPUFile]);
end;
end;
if (not Scanned) and (Item.SrcFile<>'') then begin

View File

@ -39,11 +39,16 @@ type
TPPUTool = class
public
PPU: TPPU;
Code: TCodeBuffer;
CodeChangeStep: integer;
Filename: string;
LoadDate: longint;
LoadedParts: TPPUParts;
ErrorMsg: string;
constructor Create(aCode: TCodeBuffer);
constructor Create(aFilename: string);
destructor Destroy; override;
function FileDateOnDisk: longint;
function NeedsUpdate(const Parts: TPPUParts = PPUPartsAll): boolean;
function Load(const Parts: TPPUParts = PPUPartsAll): boolean;
procedure Clear;
end;
{ TPPUTools }
@ -51,43 +56,39 @@ type
TPPUTools = class
private
fItems: TAVLTree; // tree of TPPUTool sorted for Code
FSourceCache: TCodeCache;
public
constructor Create(SrcCache: TCodeCache);
constructor Create;
destructor Destroy; override;
procedure ClearCaches;
property SourceCache: TCodeCache read FSourceCache;
function FindFile(Code: TCodeBuffer): TPPUTool;
function FindFile(const ExpandedFilename: string): TPPUTool;
function LoadFile(const ExpandedFilename: string;
UpdateFromDisk, Revert: boolean): TPPUTool;
function FindFile(const NormalizedFilename: string): TPPUTool;
function LoadFile(const NormalizedFilename: string;
const Parts: TPPUParts = PPUPartsAll): TPPUTool;
// uses section
procedure GetMainUsesSectionNames(Code: TCodeBuffer; var List: TStrings);
procedure GetImplementationUsesSectionNames(Code: TCodeBuffer; var List: TStrings);
function GetMainUsesSectionNames(NormalizedFilename: string; var List: TStrings): boolean;
function GetImplementationUsesSectionNames(NormalizedFilename: string; var List: TStrings): boolean;
end;
function ComparePPUTools(Tool1, Tool2: Pointer): integer;
function CompareCodeWithPPUTool(Code, Tool: Pointer): integer;
function CompareFilenameWithPPUTool(Filename, Tool: Pointer): integer;
implementation
function ComparePPUTools(Tool1, Tool2: Pointer): integer;
begin
Result:=ComparePointers(TPPUTool(Tool1).Code,TPPUTool(Tool2).Code);
Result:=CompareFilenames(TPPUTool(Tool1).Filename,TPPUTool(Tool2).Filename);
end;
function CompareCodeWithPPUTool(Code, Tool: Pointer): integer;
function CompareFilenameWithPPUTool(Filename, Tool: Pointer): integer;
begin
Result:=ComparePointers(Code,TPPUTool(Tool).Code);
Result:=CompareFilenames(AnsiString(Filename),TPPUTool(Tool).Filename);
end;
{ TPPUTools }
constructor TPPUTools.Create(SrcCache: TCodeCache);
constructor TPPUTools.Create;
begin
FSourceCache:=SrcCache;
fItems:=TAVLTree.Create(@ComparePPUTools);
end;
@ -95,7 +96,6 @@ destructor TPPUTools.Destroy;
begin
fItems.FreeAndClear;
FreeAndNil(fItems);
FSourceCache:=nil;
inherited Destroy;
end;
@ -113,99 +113,63 @@ begin
end;
end;
function TPPUTools.FindFile(Code: TCodeBuffer): TPPUTool;
function TPPUTools.FindFile(const NormalizedFilename: string): TPPUTool;
var
Node: TAVLTreeNode;
begin
Result:=nil;
if Code=nil then exit;
Node:=fItems.FindKey(Code,@CompareCodeWithPPUTool);
Node:=fItems.FindKey(Pointer(NormalizedFilename),@CompareFilenameWithPPUTool);
if Node<>nil then
Result:=TPPUTool(Node.Data);
end;
function TPPUTools.FindFile(const ExpandedFilename: string): TPPUTool;
var
Code: TCodeBuffer;
begin
Code:=SourceCache.FindFile(ExpandedFilename);
if Code<>nil then
Result:=FindFile(Code)
Result:=TPPUTool(Node.Data)
else
Result:=nil;
end;
function TPPUTools.LoadFile(const ExpandedFilename: string; UpdateFromDisk,
Revert: boolean): TPPUTool;
function TPPUTools.LoadFile(const NormalizedFilename: string;
const Parts: TPPUParts): TPPUTool;
var
Code: TCodeBuffer;
ss: TStringStream;
Tool: TPPUTool;
begin
Result:=FindFile(ExpandedFilename);
if (not UpdateFromDisk) and (not Revert) then begin
// no update needed
if Result<>nil then exit;
Code:=SourceCache.FindFile(ExpandedFilename);
if (Code=nil) or Code.IsDeleted then exit(nil);
end;
// load file
Code:=SourceCache.LoadFile(ExpandedFilename);
if Code=nil then exit(nil);
if Revert then begin
if not Code.Revert then
exit(nil);
end else if UpdateFromDisk and Code.AutoRevertFromDisk
and Code.FileNeedsUpdate then begin
//debugln(['TPPUTools.LoadFile ',ExpandedFilename,' AutoRevert=',Result.AutoRevertFromDisk,' Modified=',Result.Modified,' NeedLoad=',Result.FileNeedsUpdate]);
Code.Reload;
end;
// check if tool needs update
if Result=nil then begin
Result:=TPPUTool.Create(Code);
fItems.Add(Result);
end;
Result.Code:=Code;
if (Result.PPU<>nil) and (Result.CodeChangeStep=Code.ChangeStep) then
exit;
//debugln(['TPPUTools.LoadFile parsing ppu ',Code.Filename,' ...']);
Result.ErrorMsg:='';
if Result.PPU=nil then
Result.PPU:=TPPU.Create;
ss:=TStringStream.Create(Code.Source);
try
try
Result.PPU.LoadFromStream(ss);
except
on E: Exception do begin
Result.ErrorMsg:=E.Message;
debugln(['TPPUTools.LoadFile ',Code.Filename,' ERROR: ', Result.ErrorMsg]);
end;
end;
finally
ss.Free;
Result:=nil;
if Parts=[] then exit;
Tool:=FindFile(NormalizedFilename);
if Tool=nil then begin
Tool:=TPPUTool.Create(NormalizedFilename);
fItems.Add(Tool);
end;
if not Tool.NeedsUpdate(Parts) then exit;
if not Tool.Load(Parts) then exit;
Result:=Tool;
end;
procedure TPPUTools.GetMainUsesSectionNames(Code: TCodeBuffer;
var List: TStrings);
function TPPUTools.GetMainUsesSectionNames(NormalizedFilename: string;
var List: TStrings): boolean;
var
Tool: TPPUTool;
begin
Result:=false;
Tool:=LoadFile(NormalizedFilename,[ppInterfaceHeader]);
if Tool=nil then exit;
Tool.PPU.GetMainUsesSectionNames(List);
Result:=true;
end;
procedure TPPUTools.GetImplementationUsesSectionNames(Code: TCodeBuffer;
var List: TStrings);
function TPPUTools.GetImplementationUsesSectionNames(
NormalizedFilename: string; var List: TStrings): boolean;
var
Tool: TPPUTool;
begin
Result:=false;
Tool:=LoadFile(NormalizedFilename,[ppImplementationHeader]);
if Tool=nil then exit;
Tool.PPU.GetImplementationUsesSectionNames(List);
Result:=true;
end;
{ TPPUTool }
constructor TPPUTool.Create(aCode: TCodeBuffer);
constructor TPPUTool.Create(aFilename: string);
begin
Code:=aCode;
CodeChangeStep:=Code.ChangeStep;
Filename:=aFilename;
end;
destructor TPPUTool.Destroy;
@ -214,5 +178,40 @@ begin
inherited Destroy;
end;
function TPPUTool.FileDateOnDisk: longint;
begin
Result:=FileAgeCached(Filename);
end;
function TPPUTool.NeedsUpdate(const Parts: TPPUParts): boolean;
begin
Result:=(Parts-LoadedParts<>[]) or (FileDateOnDisk<>LoadDate);
end;
function TPPUTool.Load(const Parts: TPPUParts): boolean;
begin
Result:=false;
ErrorMsg:='';
if PPU=nil then
PPU:=TPPU.Create;
try
LoadDate:=FileDateOnDisk;
LoadedParts:=Parts;
PPU.LoadFromFile(Filename,Parts);
Result:=true;
except
on E: Exception do begin
ErrorMsg:=E.Message;
debugln(['TPPUTool.Load ',Filename,' ERROR: ',ErrorMsg]);
end;
end;
end;
procedure TPPUTool.Clear;
begin
FreeAndNil(PPU);
LoadedParts:=[];
end;
end.