cody: unit dependencies: select unit

git-svn-id: trunk@40008 -
This commit is contained in:
mattias 2013-01-28 15:45:25 +00:00
parent 3d48574e08
commit 81c9be1345
3 changed files with 252 additions and 17 deletions

View File

@ -96,6 +96,7 @@ type
private
FFiles: TAVLTree; // tree of TUGUnit sorted for Filename
FStartFiles: TAVLTree; // tree of TUGUnit sorted for Filename
FTargetAll: boolean;
FTargetFiles: TAVLTree; // tree of TUGUnit sorted for Filename
FTargetDirsValid: boolean;
FTargetDirs: string;
@ -113,16 +114,18 @@ type
procedure AddStartUnit(ExpFilename: string);
procedure AddTargetUnit(ExpFilename: string);
function Parse(IgnoreErrors: boolean; out Complete: boolean;
procedure AddSystemUnitAsTarget;
function Parse(IgnoreErrors: boolean; out Completed: boolean;
StopAfterMs: integer = -1): boolean;
function GetUnitsTreeUsingTargets: TAVLTree; // tree of TUGUnit sorted for filename
function GetCodeTreeUsingTargets: TAVLTree; // tree of TCodeBuffer sorted for filename
function UnitCanFindTarget(ExpFilename: string): boolean;
function IsTargetDir(ExpDir: string): boolean;
property FilesTree: TAVLTree read FFiles;
property StartFilesTree: TAVLTree read FStartFiles;
property TargetFilesTree: TAVLTree read FTargetFiles;
property FilesTree: TAVLTree read FFiles; // tree of TUGUnit sorted for Filename
property StartFilesTree: TAVLTree read FStartFiles; // tree of TUGUnit sorted for Filename
property TargetFilesTree: TAVLTree read FTargetFiles; // tree of TUGUnit sorted for Filename
property TargetAll: boolean read FTargetAll write FTargetAll;
end;
function CompareUGUnitFilenames(UGUnit1, UGUnit2: Pointer): integer;
@ -313,7 +316,12 @@ begin
FTargetDirsValid:=false;
end;
function TUsesGraph.Parse(IgnoreErrors: boolean; out Complete: boolean;
procedure TUsesGraph.AddSystemUnitAsTarget;
begin
AddTargetUnit(DirectoryCachePool.FindUnitInUnitSet('','system'));
end;
function TUsesGraph.Parse(IgnoreErrors: boolean; out Completed: boolean;
StopAfterMs: integer): boolean;
procedure AddUses(CurUnit: TUGUnit; UsedFiles: TStrings;
@ -415,7 +423,7 @@ var
CurUnit: TUGUnit;
begin
Result:=false;
Complete:=false;
Completed:=false;
if StopAfterMs>=0 then
StartTime:=Now
else
@ -425,16 +433,16 @@ begin
CurUnit:=TUGUnit(AVLNode.Data);
FStartFiles.Delete(AVLNode);
Include(CurUnit.Flags,ugufReached);
//debugln(['TUsesGraph.Parse Unit=',CurUnit.Filename]);
//debugln(['TUsesGraph.Parse Unit=',CurUnit.Filename,' UnitCanFindTarget=',UnitCanFindTarget(CurUnit.Filename)]);
if UnitCanFindTarget(CurUnit.Filename) then begin
if not ParseUnit(CurUnit) then exit;
ParseUnit(CurUnit);
end;
if (StopAfterMs>=0) and (Abs(Now-StartTime)*86400000>=StopAfterMs) then
exit(true);
end;
Complete:=true;
Completed:=true;
Result:=true;
end;
@ -499,7 +507,7 @@ var
ReachableDir: String;
begin
Result:=true;
if FTargetInFPCSrc then exit; // standard units can always be found
if FTargetInFPCSrc or TargetAll then exit; // standard units can always be found
BaseDir:=ExtractFilePath(ExpFilename);
if IsTargetDir(BaseDir) then exit;
@ -528,11 +536,11 @@ var
p: Integer;
TargetDir: String;
begin
if FTargetFiles.Count=0 then exit(false);
if FTargetFiles.Count=0 then exit(TargetAll);
if not FTargetDirsValid then begin
FTargetDirsValid:=true;
FTargetInFPCSrc:=false;
FTargetInFPCSrc:=TargetAll;
// build list of target directories for quick lookup
AVLNode:=FTargetFiles.FindLowest;
while AVLNode<>nil do begin
@ -561,6 +569,7 @@ begin
end;
Result:=true;
if TargetAll then exit;
if (ExpDir='') and (FTargetDirs[1]=';') then exit;
p:=1;
repeat

View File

@ -1,11 +1,15 @@
object UnitDependenciesDialog: TUnitDependenciesDialog
Left = 215
Left = 235
Height = 390
Top = 224
Top = 232
Width = 486
Caption = 'UnitDependenciesDialog'
ClientHeight = 390
ClientWidth = 486
OnClose = FormClose
OnCreate = FormCreate
OnDestroy = FormDestroy
Position = poScreenCenter
LCLVersion = '1.1'
object BtnPanel: TPanel
Left = 0
@ -34,7 +38,66 @@ object UnitDependenciesDialog: TUnitDependenciesDialog
TabOrder = 0
end
end
object ProgressBar1: TProgressBar
Left = 0
Height = 20
Top = 329
Width = 486
Align = alBottom
TabOrder = 1
end
object CurUnitPanel: TPanel
Left = 0
Height = 329
Top = 0
Width = 155
Align = alLeft
Caption = 'CurUnitPanel'
ClientHeight = 329
ClientWidth = 155
TabOrder = 2
object CurUnitTreeView: TTreeView
AnchorSideLeft.Control = CurUnitTreeFilterEdit
AnchorSideTop.Control = CurUnitTreeFilterEdit
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = CurUnitPanel
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = CurUnitPanel
AnchorSideBottom.Side = asrBottom
Left = 1
Height = 302
Top = 26
Width = 153
Anchors = [akTop, akLeft, akRight, akBottom]
DefaultItemHeight = 18
ReadOnly = True
TabOrder = 0
OnSelectionChanged = CurUnitTreeViewSelectionChanged
Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
end
object CurUnitTreeFilterEdit: TTreeFilterEdit
AnchorSideLeft.Control = CurUnitPanel
AnchorSideTop.Control = CurUnitPanel
AnchorSideRight.Side = asrBottom
Left = 1
Height = 25
Top = 1
Width = 109
ButtonWidth = 23
NumGlyphs = 1
MaxLength = 0
TabOrder = 1
FilteredTreeview = CurUnitTreeView
end
end
object CurUnitSplitter: TSplitter
Left = 155
Height = 329
Top = 0
Width = 5
end
object Timer1: TTimer
OnTimer = Timer1Timer
left = 230
top = 187
end

View File

@ -5,8 +5,10 @@ unit CodyUnitDepWnd;
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
Buttons;
Classes, SysUtils, AVL_Tree, FileUtil, lazutf8classes, LazLogger,
TreeFilterEdit, CTUnitGraph, CodeToolManager, DefineTemplates, Forms,
Controls, Graphics, Dialogs, ExtCtrls, Buttons, ComCtrls, LazIDEIntf,
ProjectIntf, IDEWindowIntf;
type
@ -15,10 +17,34 @@ type
TUnitDependenciesDialog = class(TForm)
BtnPanel: TPanel;
CloseBitBtn: TBitBtn;
CurUnitPanel: TPanel;
CurUnitSplitter: TSplitter;
CurUnitTreeView: TTreeView;
ProgressBar1: TProgressBar;
Timer1: TTimer;
CurUnitTreeFilterEdit: TTreeFilterEdit;
procedure CloseBitBtnClick(Sender: TObject);
procedure CurUnitTreeViewSelectionChanged(Sender: TObject);
procedure FormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
procedure Timer1Timer(Sender: TObject);
private
FCurrentUnit: TUGUnit;
FIdleConnected: boolean;
FUsesGraph: TUsesGraph;
procedure SetCurrentUnit(AValue: TUGUnit);
procedure SetIdleConnected(AValue: boolean);
procedure AddStartAndTargetUnits;
procedure UpdateAll;
procedure UpdateCurUnitTreeView;
function NodeTextToUnit(NodeText: string): TUGUnit;
function UGUnitToNodeText(UGUnit: TUGUnit): string;
public
property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
property UsesGraph: TUsesGraph read FUsesGraph;
property CurrentUnit: TUGUnit read FCurrentUnit write SetCurrentUnit;
end;
var
@ -44,7 +70,144 @@ end;
procedure TUnitDependenciesDialog.CloseBitBtnClick(Sender: TObject);
begin
ModalResult:=mrOk;
ModalResult:=mrCancel;
end;
procedure TUnitDependenciesDialog.CurUnitTreeViewSelectionChanged(
Sender: TObject);
var
CurUnit: TUGUnit;
begin
if CurUnitTreeView.Selected=nil then exit;
CurUnit:=NodeTextToUnit(CurUnitTreeView.Selected.Text);
if CurUnit=nil then exit;
CurrentUnit:=CurUnit;
end;
procedure TUnitDependenciesDialog.FormClose(Sender: TObject;
var CloseAction: TCloseAction);
begin
IDEDialogLayoutList.SaveLayout(Self);
end;
procedure TUnitDependenciesDialog.FormCreate(Sender: TObject);
begin
FUsesGraph:=CodeToolBoss.CreateUsesGraph;
ProgressBar1.Style:=pbstMarquee;
AddStartAndTargetUnits;
IDEDialogLayoutList.ApplyLayout(Self,600,400);
IdleConnected:=true;
end;
procedure TUnitDependenciesDialog.FormDestroy(Sender: TObject);
begin
IdleConnected:=false;
FreeAndNil(FUsesGraph);
end;
procedure TUnitDependenciesDialog.OnIdle(Sender: TObject; var Done: Boolean);
var
Completed: boolean;
begin
UsesGraph.Parse(true,Completed,200);
if Completed then begin
IdleConnected:=false;
ProgressBar1.Visible:=false;
ProgressBar1.Style:=pbstNormal;
Timer1.Enabled:=false;
UpdateAll;
end;
end;
procedure TUnitDependenciesDialog.Timer1Timer(Sender: TObject);
begin
UpdateAll;
end;
procedure TUnitDependenciesDialog.SetIdleConnected(AValue: boolean);
begin
if FIdleConnected=AValue then Exit;
FIdleConnected:=AValue;
if IdleConnected then
Application.AddOnIdleHandler(@OnIdle)
else
Application.RemoveOnIdleHandler(@OnIdle);
end;
procedure TUnitDependenciesDialog.SetCurrentUnit(AValue: TUGUnit);
begin
if FCurrentUnit=AValue then Exit;
FCurrentUnit:=AValue;
end;
procedure TUnitDependenciesDialog.AddStartAndTargetUnits;
var
aProject: TLazProject;
begin
UsesGraph.TargetAll:=true;
// project lpr
aProject:=LazarusIDE.ActiveProject;
if (aProject<>nil) and (aProject.MainFile<>nil) then
UsesGraph.AddStartUnit(aProject.MainFile.Filename);
// ToDo: add all open packages
end;
procedure TUnitDependenciesDialog.UpdateAll;
begin
UpdateCurUnitTreeView;
end;
procedure TUnitDependenciesDialog.UpdateCurUnitTreeView;
var
AVLNode: TAVLTreeNode;
CurUnit: TUGUnit;
sl: TStringListUTF8;
i: Integer;
begin
CurUnitTreeView.BeginUpdate;
sl:=TStringListUTF8.Create;
try
CurUnitTreeView.Items.Clear;
AVLNode:=UsesGraph.FilesTree.FindLowest;
while AVLNode<>nil do begin
CurUnit:=TUGUnit(AVLNode.Data);
sl.Add(UGUnitToNodeText(CurUnit));
AVLNode:=UsesGraph.FilesTree.FindSuccessor(AVLNode);
end;
sl.CustomSort(@CompareStringListItemsUTF8LowerCase);
for i:=0 to sl.Count-1 do begin
CurUnitTreeView.Items.Add(nil,sl[i]);
end;
finally
sl.Free;
CurUnitTreeView.EndUpdate;
end;
end;
function TUnitDependenciesDialog.NodeTextToUnit(NodeText: string): TUGUnit;
var
AVLNode: TAVLTreeNode;
begin
AVLNode:=UsesGraph.FilesTree.FindLowest;
while AVLNode<>nil do begin
Result:=TUGUnit(AVLNode.Data);
if NodeText=UGUnitToNodeText(Result) then exit;
AVLNode:=UsesGraph.FilesTree.FindSuccessor(AVLNode);
end;
Result:=nil;
end;
function TUnitDependenciesDialog.UGUnitToNodeText(UGUnit: TUGUnit): string;
begin
Result:=ExtractFileName(UGUnit.Filename);
end;
{$R *.lfm}