/ide/codebrowser.pas

http://github.com/graemeg/lazarus · Pascal · 3356 lines · 2875 code · 280 blank · 201 comment · 398 complexity · e2cb45deae453ab5eab4e6f5b1f1ff4f MD5 · raw file

Large files are truncated click here to view the full file

  1. {
  2. ***************************************************************************
  3. * *
  4. * This source is free software; you can redistribute it and/or modify *
  5. * it under the terms of the GNU General Public License as published by *
  6. * the Free Software Foundation; either version 2 of the License, or *
  7. * (at your option) any later version. *
  8. * *
  9. * This code is distributed in the hope that it will be useful, but *
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  12. * General Public License for more details. *
  13. * *
  14. * A copy of the GNU General Public License is available on the World *
  15. * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
  16. * obtain it by writing to the Free Software Foundation, *
  17. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. * *
  19. ***************************************************************************
  20. Author: Mattias Gaertner
  21. Abstract:
  22. Browser for packages, classes, methods, functions.
  23. Scope:
  24. Browse units of IDE, or a project or a package.
  25. Browse with required packages or without.
  26. Sort:
  27. Owner, unit, class, visibility, type (procedure, var, const, ...), identifier
  28. Notes:
  29. The codetools provides TCodeTree of every unit.
  30. ToDo:
  31. - pause
  32. - scan recently used packages
  33. - scan packages in global links
  34. }
  35. unit CodeBrowser;
  36. {$mode objfpc}{$H+}
  37. {off $DEFINE VerboseCodeBrowser}
  38. interface
  39. uses
  40. // RTL + FCL + LCL
  41. Classes, SysUtils, types, AVL_Tree,
  42. LCLProc, LResources, Forms, Controls, Graphics, Dialogs, Clipbrd, StdCtrls,
  43. ExtCtrls, ComCtrls, Buttons, Menus, HelpIntfs, LCLIntf,
  44. // CodeTools
  45. BasicCodeTools, DefineTemplates, CodeTree, CodeCache,
  46. CodeToolsStructs, CodeToolManager, PascalParserTool, LinkScanner, FileProcs,
  47. CodeIndex, StdCodeTools, SourceLog, CustomCodeTool,
  48. // LazUtils
  49. LazFileUtils, LazUtilities,
  50. // IDEIntf
  51. IDEWindowIntf, SrcEditorIntf, IDEMsgIntf, IDEDialogs, LazConfigStorage,
  52. IDEHelpIntf, PackageIntf, IDECommands, LazIDEIntf,
  53. IDEExternToolIntf,
  54. // IDE
  55. Project, DialogProcs, PackageSystem, PackageDefs, LazarusIDEStrConsts,
  56. IDEOptionDefs, etFPCMsgParser, BasePkgManager, EnvironmentOpts;
  57. type
  58. TCodeBrowserLevel = (
  59. cblPackages,
  60. cblUnits,
  61. cblIdentifiers
  62. );
  63. TCodeBrowserTextFilter = (
  64. cbtfBegins,
  65. cbtfContains
  66. );
  67. const
  68. CodeBrowserLevelNames: array[TCodeBrowserLevel] of string = (
  69. 'Packages',
  70. 'Units',
  71. 'Identifiers'
  72. );
  73. CodeBrowserTextFilterNames: array[TCodeBrowserTextFilter] of string = (
  74. 'Begins',
  75. 'Contains'
  76. );
  77. CodeBrowserIDEName = ' '+'Lazarus IDE';// Note: space is needed to avoid name clashing
  78. CodeBrowserProjectName = ' '+'Project';
  79. CodeBrowserHidden = ' ';
  80. CodeBrowserMaxTVIdentifiers = 5000; // the maximum amount of identifiers shown in the treeview
  81. type
  82. { TCodeBrowserViewOptions }
  83. TCodeBrowserViewOptions = class
  84. private
  85. FChangeStamp: integer;
  86. FModified: boolean;
  87. FScope: string;
  88. FLevels: TStrings;
  89. FShowEmptyNodes: boolean;
  90. FShowPrivate: boolean;
  91. FShowProtected: boolean;
  92. FStoreWithRequiredPackages: boolean;
  93. FWithRequiredPackages: boolean;
  94. FLevelFilterText: array[TCodeBrowserLevel] of string;
  95. FLevelFilterType: array[TCodeBrowserLevel] of TCodeBrowserTextFilter;
  96. function GetLevelFilterText(Level: TCodeBrowserLevel): string;
  97. function GetLevelFilterType(Level: TCodeBrowserLevel): TCodeBrowserTextFilter;
  98. procedure SetLevelFilterText(Level: TCodeBrowserLevel; const AValue: string);
  99. procedure SetLevelFilterType(Level: TCodeBrowserLevel;
  100. const AValue: TCodeBrowserTextFilter);
  101. procedure SetModified(const AValue: boolean);
  102. procedure SetScope(const AValue: string);
  103. procedure SetLevels(const AValue: TStrings);
  104. procedure SetShowEmptyNodes(const AValue: boolean);
  105. procedure SetShowPrivate(const AValue: boolean);
  106. procedure SetShowProtected(const AValue: boolean);
  107. procedure SetStoreWithRequiredPackages(const AValue: boolean);
  108. procedure SetWithRequiredPackages(const AValue: boolean);
  109. procedure IncreaseChangeStamp;
  110. public
  111. constructor Create;
  112. destructor Destroy; override;
  113. procedure Clear;
  114. procedure LoadFromConfig(ConfigStore: TConfigStorage; const Path: string);
  115. procedure SaveToConfig(ConfigStore: TConfigStorage; const Path: string);
  116. function HasLevel(Level: TCodeBrowserLevel): boolean;
  117. public
  118. property Scope: string read FScope write SetScope;
  119. property WithRequiredPackages: boolean read FWithRequiredPackages write SetWithRequiredPackages;
  120. property StoreWithRequiredPackages: boolean read FStoreWithRequiredPackages write SetStoreWithRequiredPackages;
  121. property Levels: TStrings read FLevels write SetLevels;
  122. property ShowPrivate: boolean read FShowPrivate write SetShowPrivate;
  123. property ShowProtected: boolean read FShowProtected write SetShowProtected;
  124. property ShowEmptyNodes: boolean read FShowEmptyNodes write SetShowEmptyNodes;
  125. property LevelFilterText[Level: TCodeBrowserLevel]: string read GetLevelFilterText write SetLevelFilterText;
  126. property LevelFilterType[Level: TCodeBrowserLevel]: TCodeBrowserTextFilter read GetLevelFilterType write SetLevelFilterType;
  127. property Modified: boolean read FModified write SetModified;
  128. property ChangeStamp: integer read FChangeStamp;
  129. end;
  130. TCodeBrowserWorkStage = (
  131. cbwsGetScopeOptions,
  132. cbwsGatherPackages,
  133. cbwsFreeUnusedPackages,
  134. cbwsAddNewPackages,
  135. cbwsGatherFiles,
  136. cbwsGatherOutdatedFiles,
  137. cbwsUpdateUnits,
  138. cbwsGetViewOptions,
  139. cbwsUpdateTreeView,
  140. cbwsFinished
  141. );
  142. TExpandableNodeType = (
  143. entPackage,
  144. entUnit,
  145. entClass
  146. );
  147. TCopyNodeType = (
  148. cntIdentifier,
  149. cntDescription
  150. );
  151. { TCodeBrowserView }
  152. TCodeBrowserView = class(TForm)
  153. AllClassesSeparatorMenuItem: TMenuItem;
  154. AllPackagesSeparatorMenuItem: TMenuItem;
  155. AllUnitsSeparatorMenuItem: TMenuItem;
  156. BrowseTreeView: TTreeView;
  157. UseIdentifierInCurUnitMenuItem: TMenuItem;
  158. UseUnitInCurUnitMenuItem: TMenuItem;
  159. RescanButton: TButton;
  160. IdleTimer1: TIdleTimer;
  161. UsePkgInProjectMenuItem: TMenuItem;
  162. UsePkgInCurUnitMenuItem: TMenuItem;
  163. UseSeparatorMenuItem: TMenuItem;
  164. ShowEmptyNodesCheckBox: TCheckBox;
  165. CollapseAllClassesMenuItem: TMenuItem;
  166. CollapseAllPackagesMenuItem: TMenuItem;
  167. CollapseAllUnitsMenuItem: TMenuItem;
  168. CopyDescriptionMenuItem: TMenuItem;
  169. CopyIdentifierMenuItem: TMenuItem;
  170. CopySeparatorMenuItem: TMenuItem;
  171. ExpandAllClassesMenuItem: TMenuItem;
  172. ExpandAllPackagesMenuItem: TMenuItem;
  173. ExpandAllUnitsMenuItem: TMenuItem;
  174. ExportMenuItem: TMenuItem;
  175. IdentifierFilterBeginsSpeedButton: TSpeedButton;
  176. IdentifierFilterContainsSpeedButton: TSpeedButton;
  177. IdentifierFilterEdit: TEdit;
  178. ImageList1: TImageList;
  179. LevelsGroupBox: TGroupBox;
  180. OpenMenuItem: TMenuItem;
  181. OptionsGroupBox: TGroupBox;
  182. PackageFilterBeginsSpeedButton: TSpeedButton;
  183. PackageFilterContainsSpeedButton: TSpeedButton;
  184. PackageFilterEdit: TEdit;
  185. PopupMenu1: TPopupMenu;
  186. ProgressBar1: TProgressBar;
  187. ScopeComboBox: TComboBox;
  188. ScopeGroupBox: TGroupBox;
  189. ScopeWithRequiredPackagesCheckBox: TCheckBox;
  190. ShowIdentifiersCheckBox: TCheckBox;
  191. ShowPackagesCheckBox: TCheckBox;
  192. ShowPrivateCheckBox: TCheckBox;
  193. ShowProtectedCheckBox: TCheckBox;
  194. ShowUnitsCheckBox: TCheckBox;
  195. StatusBar1: TStatusBar;
  196. UnitFilterBeginsSpeedButton: TSpeedButton;
  197. UnitFilterContainsSpeedButton: TSpeedButton;
  198. UnitFilterEdit: TEdit;
  199. procedure BrowseTreeViewMouseMove(Sender: TObject; {%H-}Shift: TShiftState; {%H-}X,
  200. {%H-}Y: Integer);
  201. procedure FormDeactivate(Sender: TObject);
  202. procedure UseIdentifierInCurUnitMenuItemClick(Sender: TObject);
  203. procedure UsePkgInCurUnitMenuItemClick(Sender: TObject);
  204. procedure UsePkgInProjectMenuItemClick(Sender: TObject);
  205. procedure UseUnitInCurUnitMenuItemClick(Sender: TObject);
  206. procedure BrowseTreeViewMouseDown(Sender: TOBject; {%H-}Button: TMouseButton;
  207. Shift: TShiftState; X, Y: Integer);
  208. procedure BrowseTreeViewShowHint(Sender: TObject; HintInfo: PHintInfo);
  209. procedure CollapseAllPackagesMenuItemClick(Sender: TObject);
  210. procedure CollapseAllUnitsMenuItemClick(Sender: TObject);
  211. procedure CollapseAllClassesMenuItemClick(Sender: TObject);
  212. procedure CopyDescriptionMenuItemClick(Sender: TObject);
  213. procedure CopyIdentifierMenuItemClick(Sender: TObject);
  214. procedure ExpandAllClassesMenuItemClick(Sender: TObject);
  215. procedure ExpandAllPackagesMenuItemClick(Sender: TObject);
  216. procedure ExpandAllUnitsMenuItemClick(Sender: TObject);
  217. procedure ExportMenuItemClick(Sender: TObject);
  218. procedure FormCreate(Sender: TObject);
  219. procedure FormDestroy(Sender: TObject);
  220. procedure IdleTimer1Timer(Sender: TObject);
  221. procedure PackageFilterEditChange(Sender: TObject);
  222. procedure PackageFilterEditEditingDone(Sender: TObject);
  223. procedure PopupMenu1Popup(Sender: TObject);
  224. procedure RescanButtonClick(Sender: TObject);
  225. procedure ScopeComboBoxChange(Sender: TObject);
  226. procedure ScopeWithRequiredPackagesCheckBoxChange(Sender: TObject);
  227. procedure OnIdle(Sender: TObject; var Done: Boolean);
  228. procedure OpenMenuItemClick(Sender: TObject);
  229. procedure ShowIdentifiersCheckBoxChange(Sender: TObject);
  230. procedure ShowPackagesCheckBoxChange(Sender: TObject);
  231. procedure ShowPrivateCheckBoxChange(Sender: TObject);
  232. procedure ShowUnitsCheckBoxChange(Sender: TObject);
  233. private
  234. FHintManager: THintWindowManager;
  235. FIDEDescription: string;
  236. FIdleConnected: boolean;
  237. FOptions: TCodeBrowserViewOptions;
  238. FOptionsChangeStamp: integer;
  239. FProjectDescription: string;
  240. FParserRoot: TCodeBrowserUnitList;
  241. FScannedBytes: PtrInt;
  242. FScannedIdentifiers: PtrInt;
  243. FScannedLines: PtrInt;
  244. FScannedPackages: integer;
  245. FScannedUnits: integer;
  246. FUpdateNeeded: boolean;
  247. FViewRoot: TCodeBrowserUnitList;
  248. FVisibleIdentifiers: PtrInt;
  249. FVisiblePackages: integer;
  250. FVisibleUnits: integer;
  251. FWorkingParserRoot: TCodeBrowserUnitList;
  252. fUpdateCount: integer;
  253. fStage: TCodeBrowserWorkStage;
  254. fOutdatedFiles: TAVLTree;// tree of TCodeBrowserUnit
  255. fLastStatusBarUpdate: TDateTime;
  256. ImgIDDefault: integer;
  257. ImgIDProgramCode: Integer;
  258. ImgIDUnitCode: Integer;
  259. ImgIDInterfaceSection: Integer;
  260. ImgIDImplementation: Integer;
  261. ImgIDInitialization: Integer;
  262. ImgIDFinalization: Integer;
  263. ImgIDTypeSection: Integer;
  264. ImgIDType: Integer;
  265. ImgIDVarSection: Integer;
  266. ImgIDVariable: Integer;
  267. ImgIDConstSection: Integer;
  268. ImgIDConst: Integer;
  269. ImgIDClass: Integer;
  270. ImgIDProc: Integer;
  271. ImgIDProperty: Integer;
  272. ImgIDPackage: Integer;
  273. ImgIDProject: Integer;
  274. procedure LoadOptions;
  275. procedure LoadLevelsGroupBox;
  276. procedure LoadFilterGroupbox;
  277. procedure FillScopeComboBox;
  278. procedure SetIdleConnected(AValue: boolean);
  279. procedure SetScannedBytes(const AValue: PtrInt);
  280. procedure SetScannedIdentifiers(const AValue: PtrInt);
  281. procedure SetScannedLines(const AValue: PtrInt);
  282. procedure SetScannedPackages(const AValue: integer);
  283. procedure SetScannedUnits(const AValue: integer);
  284. procedure SetUpdateNeeded(const AValue: boolean);
  285. procedure SetVisibleIdentifiers(const AValue: PtrInt);
  286. procedure SetVisiblePackages(const AValue: integer);
  287. procedure SetVisibleUnits(const AValue: integer);
  288. procedure Work(var Done: Boolean);
  289. procedure WorkGetScopeOptions;
  290. procedure WorkGatherPackages;
  291. procedure WorkFreeUnusedPackages;
  292. procedure WorkAddNewUnitLists;
  293. procedure WorkGatherFileLists;
  294. procedure WorkUpdateFileList(List: TCodeBrowserUnitList);
  295. procedure WorkGatherOutdatedFiles;
  296. procedure WorkUpdateUnits;
  297. procedure WorkUpdateUnit(AnUnit: TCodeBrowserUnit);
  298. procedure WorkGetViewOptions;
  299. procedure WorkUpdateTreeView;
  300. procedure FreeUnitList(List: TCodeBrowserUnitList);
  301. procedure UpdateStatusBar(Lazy: boolean);
  302. procedure RemoveUnit(AnUnit: TCodeBrowserUnit);
  303. function CountIdentifiers(Tool: TCodeTool): integer;
  304. procedure UpdateTreeView;
  305. procedure ClearTreeView;
  306. procedure InitTreeView;
  307. function ListOwnerToText(const ListOwner: string): string;
  308. procedure InitImageList;
  309. function GetNodeImage(CodeNode: TObject): integer;
  310. function GetTVNodeHint(TVNode: TTreeNode): string;
  311. function GetCodeHelp(TVNode: TTreeNode; out BaseURL, HTMLHint: string): boolean;
  312. procedure ExpandCollapseAllNodesInTreeView(NodeType: TExpandableNodeType;
  313. Expand: boolean);
  314. procedure CopyNode(TVNode: TTreeNode; NodeType: TCopyNodeType);
  315. function GetCodeTool(AnUnit: TCodeBrowserUnit): TStandardCodeTool;
  316. procedure GetNodeIdentifier(Tool: TStandardCodeTool;
  317. CTNode: TCodeTreeNode; out Identifier: string);
  318. procedure GetNodeDescription(Tool: TStandardCodeTool;
  319. CTNode: TCodeTreeNode; Identifier: string; out Description: string);
  320. function GetSelectedUnit: TCodeBrowserUnit;
  321. function GetSelectedPackage: TLazPackage;
  322. function GetCurUnitInSrcEditor(out FileOwner: TObject;
  323. out UnitCode: TCodeBuffer): boolean;
  324. function GetCurPackageInSrcEditor: TLazPackage;
  325. procedure OpenTVNode(TVNode: TTreeNode);
  326. procedure UseUnitInSrcEditor(InsertIdentifier: boolean);
  327. procedure CloseHintWindow;
  328. public
  329. procedure BeginUpdate;
  330. procedure EndUpdate;
  331. function ExportTree: TModalResult;
  332. function ExportTreeAsText(Filename: string): TModalResult;
  333. function GetScopeToCurUnitOwner(UseFCLAsDefault: boolean): string;
  334. function SetScopeToCurUnitOwner(UseFCLAsDefault,
  335. WithRequiredPackages: boolean): boolean;
  336. procedure SetFilterToSimpleIdentifier(Identifier: string);
  337. procedure InvalidateStage(AStage: TCodeBrowserWorkStage);
  338. public
  339. property ParserRoot: TCodeBrowserUnitList read FParserRoot;
  340. property WorkingParserRoot: TCodeBrowserUnitList read FWorkingParserRoot;
  341. property ViewRoot: TCodeBrowserUnitList read FViewRoot;
  342. property Options: TCodeBrowserViewOptions read FOptions;
  343. property IDEDescription: string read FIDEDescription;
  344. property ProjectDescription: string read FProjectDescription;
  345. property ScannedPackages: integer read FScannedPackages write SetScannedPackages;
  346. property ScannedUnits: integer read FScannedUnits write SetScannedUnits;
  347. property ScannedLines: PtrInt read FScannedLines write SetScannedLines;
  348. property ScannedBytes: PtrInt read FScannedBytes write SetScannedBytes;
  349. property ScannedIdentifiers: PtrInt read FScannedIdentifiers write SetScannedIdentifiers;
  350. property VisiblePackages: integer read FVisiblePackages write SetVisiblePackages;
  351. property VisibleUnits: integer read FVisibleUnits write SetVisibleUnits;
  352. property VisibleIdentifiers: PtrInt read FVisibleIdentifiers write SetVisibleIdentifiers;
  353. property UpdateNeeded: boolean read FUpdateNeeded write SetUpdateNeeded;
  354. property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
  355. end;
  356. type
  357. { TQuickFixIdentifierNotFound_Search }
  358. TQuickFixIdentifierNotFound_Search = class(TMsgQuickFix)
  359. public
  360. function IsApplicable(Msg: TMessageLine; out Identifier: string): boolean;
  361. procedure CreateMenuItems(Fixes: TMsgQuickFixes); override;
  362. procedure QuickFix({%H-}Fixes: TMsgQuickFixes; Msg: TMessageLine); override;
  363. end;
  364. var
  365. CodeBrowserView: TCodeBrowserView = nil;
  366. function StringToCodeBrowserTextFilter(const s: string): TCodeBrowserTextFilter;
  367. procedure InitCodeBrowserQuickFixItems;
  368. procedure CreateCodeBrowser(DisableAutoSizing: boolean);
  369. procedure ShowCodeBrowser(const Identifier: string);
  370. implementation
  371. {$R *.lfm}
  372. const
  373. ProgressGetScopeStart=0;
  374. ProgressGetScopeSize=10;
  375. ProgressGatherPackagesStart=ProgressGetScopeStart+ProgressGetScopeSize;
  376. ProgressGatherPackagesSize=30;
  377. ProgressFreeUnusedPkgStart=ProgressGatherPackagesStart+ProgressGatherPackagesSize;
  378. ProgressFreeUnusedPkgSize=100;
  379. ProgressAddNewUnitListsStart=ProgressFreeUnusedPkgStart+ProgressFreeUnusedPkgSize;
  380. ProgressAddNewUnitListsSize=300;
  381. ProgressGatherFileListsStart=ProgressAddNewUnitListsStart+ProgressAddNewUnitListsSize;
  382. ProgressGatherFileListsSize=300;
  383. ProgressGatherOutdatedFilesStart=ProgressGatherFileListsStart+ProgressGatherFileListsSize;
  384. ProgressGatherOutdatedFilesSize=300;
  385. ProgressUpdateUnitsStart=ProgressGatherOutdatedFilesStart+ProgressGatherOutdatedFilesSize;
  386. ProgressUpdateUnitsSize=3000;
  387. ProgressGetViewOptionsStart=ProgressUpdateUnitsStart+ProgressUpdateUnitsSize;
  388. ProgressGetViewOptionsSize=10;
  389. ProgressUpdateTreeViewStart=ProgressGetViewOptionsStart+ProgressGetViewOptionsSize;
  390. ProgressUpdateTreeViewSize=1000;
  391. ProgressTotal=ProgressUpdateTreeViewStart+ProgressUpdateTreeViewSize;
  392. const
  393. ProcDescFlags = [phpWithStart,phpWithParameterNames,
  394. phpWithVarModifiers,phpWithResultType,phpWithoutSemicolon];
  395. ProcIdentifierFlags = [phpWithoutClassKeyword,phpWithParameterNames,
  396. phpWithoutSemicolon];
  397. PropDescFlags = [phpWithoutClassKeyword,phpWithParameterNames,
  398. phpWithVarModifiers,phpWithResultType];
  399. function StringToCodeBrowserTextFilter(const s: string): TCodeBrowserTextFilter;
  400. begin
  401. for Result:=Low(TCodeBrowserTextFilter) to High(TCodeBrowserTextFilter) do
  402. if SysUtils.CompareText(CodeBrowserTextFilterNames[Result],s)=0 then exit;
  403. Result:=cbtfBegins;
  404. end;
  405. procedure InitCodeBrowserQuickFixItems;
  406. begin
  407. RegisterIDEMsgQuickFix(TQuickFixIdentifierNotFound_Search.Create);
  408. end;
  409. procedure CreateCodeBrowser(DisableAutoSizing: boolean);
  410. begin
  411. if CodeBrowserView=nil then
  412. IDEWindowCreators.CreateForm(CodeBrowserView,TCodeBrowserView,
  413. DisableAutoSizing,LazarusIDE.OwningComponent)
  414. else if DisableAutoSizing then
  415. CodeBrowserView.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('CreateCodeBrowser'){$ENDIF};
  416. end;
  417. procedure ShowCodeBrowser(const Identifier: string);
  418. begin
  419. IDEWindowCreators.ShowForm(NonModalIDEWindowNames[nmiwCodeBrowser],true);
  420. CodeBrowserView.SetScopeToCurUnitOwner(true,true);
  421. CodeBrowserView.SetFilterToSimpleIdentifier(Identifier);
  422. end;
  423. { TCodeBrowserView }
  424. procedure TCodeBrowserView.FormCreate(Sender: TObject);
  425. begin
  426. FHintManager:=THintWindowManager.Create;
  427. FOptions:=TCodeBrowserViewOptions.Create;
  428. FIDEDescription:=lisLazarusIDE;
  429. FProjectDescription:=dlgProject;
  430. Name:=NonModalIDEWindowNames[nmiwCodeBrowser];
  431. Caption:=lisCodeBrowser;
  432. ScopeGroupBox.Caption:=dlgSearchScope;
  433. ScopeWithRequiredPackagesCheckBox.Caption:=lisWithRequiredPackages;
  434. RescanButton.Caption:=lisRescan;
  435. LevelsGroupBox.Caption:=lisLevels;
  436. ShowPackagesCheckBox.Caption:=lisShowPackages;
  437. ShowUnitsCheckBox.Caption:=lisShowUnits;
  438. ShowIdentifiersCheckBox.Caption:=lisShowIdentifiers;
  439. OptionsGroupBox.Caption:=lisFilter;
  440. ShowPrivateCheckBox.Caption:=lisPrivate;
  441. ShowProtectedCheckBox.Caption:=lisProtected;
  442. ShowEmptyNodesCheckBox.Caption:=lisShowEmptyUnitsPackages;
  443. ExpandAllPackagesMenuItem.Caption:=lisExpandAllPackages;
  444. CollapseAllPackagesMenuItem.Caption:=lisCollapseAllPackages;
  445. ExpandAllUnitsMenuItem.Caption:=lisExpandAllUnits;
  446. CollapseAllUnitsMenuItem.Caption:=lisCollapseAllUnits;
  447. ExpandAllClassesMenuItem.Caption:=lisExpandAllClasses;
  448. CollapseAllClassesMenuItem.Caption:=lisCollapseAllClasses;
  449. ExportMenuItem.Caption:=lisDlgExport;
  450. OpenMenuItem.Caption:=lisOpen;
  451. // UsePkgInProjectMenuItem.Caption: see PopupMenu1Popup
  452. // UsePkgInCurUnitMenuItem.Caption: see PopupMenu1Popup
  453. // UseUnitInCurUnitMenuItem.Caption: see PopupMenu1Popup
  454. PackageFilterBeginsSpeedButton.Caption:=lisBegins;
  455. PackageFilterBeginsSpeedButton.Hint:=lisPackageNameBeginsWith;
  456. PackageFilterContainsSpeedButton.Caption:=lisContains;
  457. PackageFilterContainsSpeedButton.Hint:=lisPackageNameContains;
  458. UnitFilterBeginsSpeedButton.Caption:=lisBegins;
  459. UnitFilterBeginsSpeedButton.Hint:=lisUnitNameBeginsWith;
  460. UnitFilterContainsSpeedButton.Caption:=lisContains;
  461. UnitFilterContainsSpeedButton.Hint:=lisUnitNameContains;
  462. IdentifierFilterBeginsSpeedButton.Caption:=lisBegins;
  463. IdentifierFilterBeginsSpeedButton.Hint:=lisIdentifierBeginsWith;
  464. IdentifierFilterContainsSpeedButton.Caption:=lisContains;
  465. IdentifierFilterContainsSpeedButton.Hint:=lisIdentifierContains;
  466. ProgressBar1.Max:=ProgressTotal;
  467. InitImageList;
  468. LoadOptions;
  469. FillScopeComboBox;
  470. ScopeComboBox.ItemIndex:=0;
  471. IdleConnected:=true;
  472. end;
  473. procedure TCodeBrowserView.FormDestroy(Sender: TObject);
  474. begin
  475. IdleConnected:=false;
  476. ClearTreeView;
  477. FreeAndNil(fOutdatedFiles);
  478. FreeAndNil(FViewRoot);
  479. FreeAndNil(FParserRoot);
  480. FreeAndNil(FWorkingParserRoot);
  481. FreeAndNil(FOptions);
  482. FreeAndNil(FHintManager);
  483. IdleConnected:=false;
  484. end;
  485. procedure TCodeBrowserView.IdleTimer1Timer(Sender: TObject);
  486. begin
  487. InvalidateStage(cbwsGetViewOptions);
  488. IdleTimer1.Enabled:=false;
  489. end;
  490. procedure TCodeBrowserView.PackageFilterEditChange(Sender: TObject);
  491. begin
  492. IdleTimer1.Enabled:=true;
  493. end;
  494. procedure TCodeBrowserView.PackageFilterEditEditingDone(Sender: TObject);
  495. begin
  496. InvalidateStage(cbwsGetViewOptions);
  497. end;
  498. procedure TCodeBrowserView.PopupMenu1Popup(Sender: TObject);
  499. var
  500. TVNode: TTreeNode;
  501. Node: TObject;
  502. Identifier: String;
  503. UnitList: TCodeBrowserUnitList;
  504. EnableUsePkgInProject: Boolean;
  505. APackage: TLazPackage;
  506. EnableUsePkgInCurUnit: Boolean;
  507. TargetPackage: TLazPackage;
  508. EnableUseUnitInCurUnit: Boolean;
  509. CurUnit: TCodeBrowserUnit;
  510. SrcEditUnitOwner: TObject;
  511. SrcEditUnitCode: TCodeBuffer;
  512. CurUnitName: String;
  513. SrcEditUnitName: String;
  514. CBNode: TCodeBrowserNode;
  515. EnableUseIdentifierInCurUnit: Boolean;
  516. SrcEdit: TSourceEditorInterface;
  517. begin
  518. ExpandAllPackagesMenuItem.Visible:=Options.HasLevel(cblPackages);
  519. CollapseAllPackagesMenuItem.Visible:=ExpandAllPackagesMenuItem.Visible;
  520. AllPackagesSeparatorMenuItem.Visible:=ExpandAllPackagesMenuItem.Visible;
  521. ExpandAllUnitsMenuItem.Visible:=Options.HasLevel(cblUnits);
  522. CollapseAllUnitsMenuItem.Visible:=ExpandAllUnitsMenuItem.Visible;
  523. AllUnitsSeparatorMenuItem.Visible:=ExpandAllUnitsMenuItem.Visible;
  524. ExpandAllClassesMenuItem.Visible:=Options.HasLevel(cblIdentifiers);
  525. CollapseAllClassesMenuItem.Visible:=ExpandAllClassesMenuItem.Visible;
  526. AllClassesSeparatorMenuItem.Visible:=ExpandAllClassesMenuItem.Visible;
  527. TVNode:=BrowseTreeView.Selected;
  528. Node:=nil;
  529. if TVNode<>nil then
  530. Node:=TObject(TVNode.Data);
  531. EnableUsePkgInProject:=false;
  532. EnableUsePkgInCurUnit:=false;
  533. EnableUseUnitInCurUnit:=false;
  534. EnableUseIdentifierInCurUnit:=false;
  535. if Node<>nil then begin
  536. Identifier:='';
  537. APackage:=nil;
  538. UnitList:=nil;
  539. CurUnit:=nil;
  540. TargetPackage:=nil;
  541. if Node is TCodeBrowserNode then begin
  542. Identifier:=TCodeBrowserNode(Node).Identifier;
  543. CBNode:=TCodeBrowserNode(Node);
  544. CurUnit:=CBNode.CBUnit;
  545. if CurUnit<>nil then
  546. UnitList:=CurUnit.UnitList;
  547. end else if Node is TCodeBrowserUnit then begin
  548. CurUnit:=TCodeBrowserUnit(Node);
  549. UnitList:=CurUnit.UnitList;
  550. end else if Node is TCodeBrowserUnitList then begin
  551. UnitList:=TCodeBrowserUnitList(Node);
  552. end;
  553. if UnitList<>nil then begin
  554. if UnitList.Owner=CodeBrowserProjectName then begin
  555. // project
  556. end else if UnitList.Owner=CodeBrowserIDEName then begin
  557. // IDE
  558. end else if UnitList.Owner=CodeBrowserHidden then begin
  559. // nothing
  560. end else begin
  561. // package
  562. APackage:=PackageGraph.FindPackageWithName(UnitList.Owner,nil);
  563. if APackage<>nil then begin
  564. // check if package can be added to project
  565. if Project1.FindDependencyByName(APackage.Name)=nil then begin
  566. EnableUsePkgInProject:=true;
  567. UsePkgInProjectMenuItem.Caption:=Format(lisUsePackageInProject, [
  568. APackage.Name]);
  569. end;
  570. // check if package can be added to package of src editor unit
  571. TargetPackage:=GetCurPackageInSrcEditor;
  572. if (TargetPackage<>nil)
  573. and (SysUtils.CompareText(TargetPackage.Name,APackage.Name)<>0)
  574. and (TargetPackage.FindDependencyByName(APackage.Name)=nil) then begin
  575. EnableUsePkgInCurUnit:=true;
  576. UsePkgInCurUnitMenuItem.Caption:=Format(
  577. lisUsePackageInPackage, [APackage.Name,
  578. TargetPackage.Name]);
  579. end;
  580. // check if unit can be added to project/package
  581. GetCurUnitInSrcEditor(SrcEditUnitOwner,SrcEditUnitCode);
  582. if (CurUnit<>nil) and (SrcEditUnitOwner<>nil) then begin
  583. CurUnitName:=ExtractFileNameOnly(CurUnit.Filename);
  584. SrcEditUnitName:=ExtractFileNameOnly(SrcEditUnitCode.Filename);
  585. if SysUtils.CompareText(CurUnitName,SrcEditUnitName)<>0 then begin
  586. EnableUseUnitInCurUnit:=true;
  587. UseUnitInCurUnitMenuItem.Caption:=
  588. Format(lisUseUnitInUnit, [CurUnitName, SrcEditUnitName]);
  589. if (Node is TCodeBrowserNode) and (Identifier<>'') then begin
  590. EnableUseIdentifierInCurUnit:=true;
  591. SrcEdit:=SourceEditorManagerIntf.ActiveEditor;
  592. UseIdentifierInCurUnitMenuItem.Caption:=
  593. Format(lisUseIdentifierInAt, [Identifier, ExtractFilename(
  594. SrcEdit.FileName), dbgs(SrcEdit.CursorScreenXY)]);
  595. end;
  596. end;
  597. end;
  598. end;
  599. end;
  600. end;
  601. OpenMenuItem.Visible:=true;
  602. CopyDescriptionMenuItem.Caption:=lisCopyDescription;
  603. CopyIdentifierMenuItem.Caption:=Format(lisCopyIdentifier, [Identifier]);
  604. CopyDescriptionMenuItem.Visible:=true;
  605. CopyIdentifierMenuItem.Visible:=Identifier<>'';
  606. CopySeparatorMenuItem.Visible:=true;
  607. UseUnitInCurUnitMenuItem.Enabled:=EnableUseUnitInCurUnit;
  608. UseUnitInCurUnitMenuItem.Visible:=true;
  609. if not EnableUseUnitInCurUnit then
  610. UseUnitInCurUnitMenuItem.Caption:=lisPkgMangUseUnit;
  611. UseIdentifierInCurUnitMenuItem.Enabled:=EnableUseIdentifierInCurUnit;
  612. UseIdentifierInCurUnitMenuItem.Visible:=true;
  613. if not EnableUseIdentifierInCurUnit then
  614. UseIdentifierInCurUnitMenuItem.Caption:=lisUseIdentifier;
  615. UsePkgInProjectMenuItem.Enabled:=EnableUsePkgInProject;
  616. UsePkgInProjectMenuItem.Visible:=true;
  617. if not EnableUsePkgInProject then
  618. UsePkgInProjectMenuItem.Caption:=lisUsePackageInProject2;
  619. UsePkgInCurUnitMenuItem.Enabled:=EnableUsePkgInCurUnit;
  620. UsePkgInCurUnitMenuItem.Visible:=true;
  621. if not EnableUsePkgInCurUnit then
  622. UsePkgInCurUnitMenuItem.Caption:=lisUsePackageInPackage2;
  623. end else begin
  624. OpenMenuItem.Visible:=false;
  625. CopyDescriptionMenuItem.Visible:=false;
  626. CopyIdentifierMenuItem.Visible:=false;
  627. CopySeparatorMenuItem.Visible:=false;
  628. UseUnitInCurUnitMenuItem.Visible:=false;
  629. UseIdentifierInCurUnitMenuItem.Visible:=false;
  630. UsePkgInProjectMenuItem.Visible:=false;
  631. UsePkgInCurUnitMenuItem.Visible:=false;
  632. UseSeparatorMenuItem.Visible:=false;
  633. end;
  634. end;
  635. procedure TCodeBrowserView.RescanButtonClick(Sender: TObject);
  636. begin
  637. UpdateNeeded:=true;
  638. InvalidateStage(cbwsGetScopeOptions);
  639. end;
  640. procedure TCodeBrowserView.ScopeComboBoxChange(Sender: TObject);
  641. begin
  642. InvalidateStage(cbwsGetScopeOptions);
  643. end;
  644. procedure TCodeBrowserView.ScopeWithRequiredPackagesCheckBoxChange(Sender: TObject);
  645. begin
  646. InvalidateStage(cbwsGetScopeOptions);
  647. end;
  648. procedure TCodeBrowserView.OnIdle(Sender: TObject; var Done: Boolean);
  649. begin
  650. if (Screen.GetCurrentModalForm<>nil) then exit;
  651. Work(Done);
  652. end;
  653. procedure TCodeBrowserView.OpenMenuItemClick(Sender: TObject);
  654. begin
  655. OpenTVNode(BrowseTreeView.Selected);
  656. end;
  657. procedure TCodeBrowserView.ShowIdentifiersCheckBoxChange(Sender: TObject);
  658. begin
  659. InvalidateStage(cbwsGetViewOptions);
  660. end;
  661. procedure TCodeBrowserView.ShowPackagesCheckBoxChange(Sender: TObject);
  662. begin
  663. //DebugLn(['TCodeBrowserView.ShowPackagesCheckBoxChange ']);
  664. InvalidateStage(cbwsGetViewOptions);
  665. end;
  666. procedure TCodeBrowserView.ShowPrivateCheckBoxChange(Sender: TObject);
  667. begin
  668. InvalidateStage(cbwsGetViewOptions);
  669. end;
  670. procedure TCodeBrowserView.ShowUnitsCheckBoxChange(Sender: TObject);
  671. begin
  672. InvalidateStage(cbwsGetViewOptions);
  673. end;
  674. procedure TCodeBrowserView.LoadOptions;
  675. begin
  676. BeginUpdate;
  677. ScopeWithRequiredPackagesCheckBox.Checked:=Options.WithRequiredPackages;
  678. ScopeComboBox.Text:=Options.Scope;
  679. LoadLevelsGroupBox;
  680. LoadFilterGroupbox;
  681. EndUpdate;
  682. end;
  683. procedure TCodeBrowserView.LoadLevelsGroupBox;
  684. begin
  685. ShowPackagesCheckBox.Checked:=Options.HasLevel(cblPackages);
  686. ShowUnitsCheckBox.Checked:=Options.HasLevel(cblUnits);
  687. ShowIdentifiersCheckBox.Checked:=Options.HasLevel(cblIdentifiers);
  688. end;
  689. procedure TCodeBrowserView.LoadFilterGroupbox;
  690. begin
  691. ShowPrivateCheckBox.Checked:=Options.ShowPrivate;
  692. ShowProtectedCheckBox.Checked:=Options.ShowProtected;
  693. ShowEmptyNodesCheckBox.Checked:=Options.ShowEmptyNodes;
  694. PackageFilterEdit.Text:=Options.LevelFilterText[cblPackages];
  695. case Options.LevelFilterType[cblPackages] of
  696. cbtfBegins: PackageFilterBeginsSpeedButton.Down:=true;
  697. cbtfContains: PackageFilterContainsSpeedButton.Down:=true;
  698. end;
  699. UnitFilterEdit.Text:=Options.LevelFilterText[cblUnits];
  700. case Options.LevelFilterType[cblUnits] of
  701. cbtfBegins: UnitFilterBeginsSpeedButton.Down:=true;
  702. cbtfContains: UnitFilterContainsSpeedButton.Down:=true;
  703. end;
  704. IdentifierFilterEdit.Text:=Options.LevelFilterText[cblIdentifiers];
  705. case Options.LevelFilterType[cblIdentifiers] of
  706. cbtfBegins: IdentifierFilterBeginsSpeedButton.Down:=true;
  707. cbtfContains: IdentifierFilterContainsSpeedButton.Down:=true;
  708. end;
  709. end;
  710. procedure TCodeBrowserView.FillScopeComboBox;
  711. var
  712. sl: TStringList;
  713. i: Integer;
  714. begin
  715. if ScopeComboBox.Items.Count=0 then begin
  716. sl:=TStringList.Create;
  717. try
  718. if PackageGraph<>nil then begin
  719. for i:=0 to PackageGraph.Count-1 do
  720. sl.Add(PackageGraph.Packages[i].Name);
  721. end;
  722. sl.Sort;
  723. sl.Insert(0,IDEDescription);
  724. sl.Insert(1,ProjectDescription);
  725. ScopeComboBox.Items.Assign(sl);
  726. finally
  727. sl.Free;
  728. end;
  729. end;
  730. end;
  731. procedure TCodeBrowserView.SetIdleConnected(AValue: boolean);
  732. begin
  733. if csDestroying in ComponentState then AValue:=false;
  734. if FIdleConnected=AValue then Exit;
  735. FIdleConnected:=AValue;
  736. if IdleConnected then
  737. Application.AddOnIdleHandler(@OnIdle)
  738. else
  739. Application.RemoveOnIdleHandler(@OnIdle);
  740. end;
  741. procedure TCodeBrowserView.InitImageList;
  742. begin
  743. ImgIDDefault := Imagelist1.AddResourceName(HInstance, 'ce_default');
  744. ImgIDProgramCode := Imagelist1.AddResourceName(HInstance, 'ce_program');
  745. ImgIDUnitCode := Imagelist1.AddResourceName(HInstance, 'ce_unit');
  746. ImgIDInterfaceSection := Imagelist1.AddResourceName(HInstance, 'ce_interface');
  747. ImgIDImplementation := Imagelist1.AddResourceName(HInstance, 'ce_implementation');
  748. ImgIDInitialization := Imagelist1.AddResourceName(HInstance, 'ce_initialization');
  749. ImgIDFinalization := Imagelist1.AddResourceName(HInstance, 'ce_finalization');
  750. ImgIDTypeSection := Imagelist1.AddResourceName(HInstance, 'ce_type');
  751. ImgIDType := Imagelist1.AddResourceName(HInstance, 'ce_type');
  752. ImgIDVarSection := Imagelist1.AddResourceName(HInstance, 'ce_variable');
  753. ImgIDVariable := Imagelist1.AddResourceName(HInstance, 'ce_variable');
  754. ImgIDConstSection := Imagelist1.AddResourceName(HInstance, 'ce_const');
  755. ImgIDConst := Imagelist1.AddResourceName(HInstance, 'ce_const');
  756. ImgIDClass := Imagelist1.AddResourceName(HInstance, 'ce_class');
  757. ImgIDProc := Imagelist1.AddResourceName(HInstance, 'ce_procedure');
  758. ImgIDProperty := Imagelist1.AddResourceName(HInstance, 'ce_property');
  759. ImgIDPackage := Imagelist1.AddResourceName(HInstance, 'item_package');
  760. ImgIDProject := Imagelist1.AddResourceName(HInstance, 'item_project');
  761. end;
  762. procedure TCodeBrowserView.SetScannedBytes(const AValue: PtrInt);
  763. begin
  764. if FScannedBytes=AValue then exit;
  765. FScannedBytes:=AValue;
  766. end;
  767. procedure TCodeBrowserView.SetScannedIdentifiers(const AValue: PtrInt);
  768. begin
  769. if FScannedIdentifiers=AValue then exit;
  770. FScannedIdentifiers:=AValue;
  771. end;
  772. procedure TCodeBrowserView.SetScannedLines(const AValue: PtrInt);
  773. begin
  774. if FScannedLines=AValue then exit;
  775. FScannedLines:=AValue;
  776. end;
  777. procedure TCodeBrowserView.SetScannedPackages(const AValue: integer);
  778. begin
  779. if FScannedPackages=AValue then exit;
  780. FScannedPackages:=AValue;
  781. end;
  782. procedure TCodeBrowserView.SetScannedUnits(const AValue: integer);
  783. begin
  784. if FScannedUnits=AValue then exit;
  785. FScannedUnits:=AValue;
  786. end;
  787. procedure TCodeBrowserView.SetUpdateNeeded(const AValue: boolean);
  788. procedure InvalidateFileList(StartList: TCodeBrowserUnitList);
  789. var
  790. APackage: TCodeBrowserUnitList;
  791. Node: TAVLTreeNode;
  792. begin
  793. if StartList=nil then exit;
  794. StartList.UnitsValid:=false;
  795. if (StartList.UnitLists=nil) then exit;
  796. Node:=StartList.UnitLists.FindLowest;
  797. while Node<>nil do begin
  798. APackage:=TCodeBrowserUnitList(Node.Data);
  799. InvalidateFileList(APackage);
  800. Node:=StartList.UnitLists.FindSuccessor(Node);
  801. end;
  802. end;
  803. begin
  804. if FUpdateNeeded=AValue then exit;
  805. FUpdateNeeded:=AValue;
  806. if FUpdateNeeded then begin
  807. InvalidateFileList(FParserRoot);
  808. InvalidateFileList(FWorkingParserRoot);
  809. InvalidateStage(cbwsGetScopeOptions);
  810. end;
  811. end;
  812. procedure TCodeBrowserView.SetVisibleIdentifiers(const AValue: PtrInt);
  813. begin
  814. if FVisibleIdentifiers=AValue then exit;
  815. FVisibleIdentifiers:=AValue;
  816. end;
  817. procedure TCodeBrowserView.SetVisiblePackages(const AValue: integer);
  818. begin
  819. if FVisiblePackages=AValue then exit;
  820. FVisiblePackages:=AValue;
  821. end;
  822. procedure TCodeBrowserView.SetVisibleUnits(const AValue: integer);
  823. begin
  824. if FVisibleUnits=AValue then exit;
  825. FVisibleUnits:=AValue;
  826. end;
  827. procedure TCodeBrowserView.UseUnitInSrcEditor(InsertIdentifier: boolean);
  828. var
  829. // temporary data, that can be freed on next idle
  830. SelectedUnit: TCodeBrowserUnit;
  831. TVNode: TTreeNode;
  832. Node: TObject;
  833. IdentifierNode: TCodeBrowserNode;
  834. // normal vars
  835. SelectedUnitName: String;
  836. SelectedCode: TCodeBuffer;
  837. List: TFPList;
  838. SelectedOwner: TObject;
  839. APackage: TLazPackage;
  840. TargetCode: TCodeBuffer;
  841. TargetOwner: TObject;
  842. SrcEdit: TSourceEditorInterface;
  843. Code: TCodeBuffer;
  844. CodeMarker: TSourceLogMarker;
  845. Identifier: String;
  846. SelectedUnitFilename: String;
  847. IdentStart: integer;
  848. IdentEnd: integer;
  849. InsertStartPos: TPoint;
  850. InsertEndPos: TPoint;
  851. begin
  852. TVNode:=BrowseTreeView.Selected;
  853. if TVNode=nil then exit;
  854. Node:=TObject(TVNode.Data);
  855. IdentifierNode:=nil;
  856. SelectedUnit:=nil;
  857. if Node is TCodeBrowserNode then begin
  858. IdentifierNode:=TCodeBrowserNode(Node);
  859. Identifier:=IdentifierNode.Identifier;
  860. SelectedUnit:=IdentifierNode.CBUnit;
  861. end else if Node is TCodeBrowserUnit then begin
  862. SelectedUnit:=TCodeBrowserUnit(Node);
  863. end else
  864. exit;
  865. if (SelectedUnit=nil) then exit;
  866. SelectedUnitFilename:=SelectedUnit.Filename;
  867. if InsertIdentifier then begin
  868. if (IdentifierNode=nil) or (Identifier='') then exit;
  869. end;
  870. if SelectedUnit.UnitList=nil then begin
  871. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor not implemented: '
  872. +'SelectedUnit.UnitList=nil']);
  873. IDEMessageDialog('Implement me',
  874. 'TCodeBrowserView.UseUnitInSrcEditor not implemented: '
  875. +'SelectedUnit.UnitList=nil',
  876. mtInformation, [mbOk]);
  877. exit;
  878. end;
  879. SelectedOwner:=nil;
  880. if SelectedUnit.UnitList.Owner=CodeBrowserProjectName then begin
  881. // project
  882. SelectedOwner:=Project1;
  883. end else if SelectedUnit.UnitList.Owner=CodeBrowserIDEName then begin
  884. // IDE can not be added as dependency
  885. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor IDE can not be '
  886. +'added as dependency']);
  887. exit;
  888. end else if SelectedUnit.UnitList.Owner=CodeBrowserHidden then begin
  889. // nothing
  890. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor hidden unitlist']
  891. );
  892. exit;
  893. end else begin
  894. // package
  895. APackage:=PackageGraph.FindPackageWithName(SelectedUnit.UnitList.Owner,nil);
  896. if APackage=nil then begin
  897. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor package not '
  898. +'found: ', SelectedUnit.UnitList.Owner]);
  899. exit;
  900. end;
  901. SelectedOwner:=APackage;
  902. end;
  903. // get target unit
  904. if not GetCurUnitInSrcEditor(TargetOwner, TargetCode) then exit;
  905. if (not (TargetOwner is TProject))
  906. and (not (TargetOwner is TLazPackage)) then begin
  907. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor not implemented: '
  908. +'TargetOwner=', DbgSName(TargetOwner)]);
  909. IDEMessageDialog('Implement me',
  910. 'TCodeBrowserView.UseUnitInSrcEditor not implemented: '
  911. +'TargetOwner='+DbgSName(TargetOwner),
  912. mtInformation, [mbOk]);
  913. exit;
  914. end;
  915. if (SelectedOwner is TProject) and (TargetOwner<>SelectedOwner) then begin
  916. // unit of project can not be used by other packages/projects
  917. IDEMessageDialog(lisImpossible,
  918. lisAProjectUnitCanNotBeUsedByOtherPackagesProjects,
  919. mtError, [mbCancel]);
  920. exit;
  921. end;
  922. // safety first: clear the references, they will become invalid on next idle
  923. SelectedUnit:=nil;
  924. IdentifierNode:=nil;
  925. Node:=nil;
  926. TVNode:=nil;
  927. List:=TFPList.Create;
  928. CodeMarker:=nil;
  929. try
  930. SrcEdit:=SourceEditorManagerIntf.ActiveEditor;
  931. if SrcEdit=nil then exit;
  932. InsertStartPos:=SrcEdit.CursorTextXY;
  933. Code:=TCodeBuffer(SrcEdit.CodeToolsBuffer);
  934. CodeMarker:=Code.AddMarkerXY(InsertStartPos.Y,InsertStartPos.X,Self);
  935. List.Add(TargetOwner);
  936. if (SelectedOwner is TLazPackage) then begin
  937. // add package to TargetOwner
  938. APackage:=TLazPackage(SelectedOwner);
  939. if PkgBoss.AddDependencyToOwners(List, APackage)<>mrOk then begin
  940. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor PkgBoss.'
  941. +'AddDependencyToOwners failed']);
  942. exit;
  943. end;
  944. end;
  945. // get nice unit name
  946. LazarusIDE.SaveSourceEditorChangesToCodeCache(nil);
  947. SelectedCode:=CodeToolBoss.LoadFile(SelectedUnitFilename, true, false);
  948. if SelectedCode=nil then begin
  949. debugln(['TCodeBrowserView.UseUnitInSrcEditor failed to load SelectedUnitFilename=',SelectedUnitFilename]);
  950. exit;
  951. end;
  952. SelectedUnitName:=CodeToolBoss.GetSourceName(SelectedCode, false);
  953. // add unit to uses section
  954. if not CodeToolBoss.AddUnitToMainUsesSection(TargetCode, SelectedUnitName,'') then
  955. begin
  956. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor CodeToolBoss.'
  957. +'AddUnitToMainUsesSection failed: TargetCode=', TargetCode.Filename,
  958. ' SelectedUnitName=', SelectedUnitName]);
  959. LazarusIDE.DoJumpToCodeToolBossError;
  960. end;
  961. // insert identifier
  962. if InsertIdentifier then begin
  963. if CodeMarker.Deleted then begin
  964. DebugLn(['TCodeBrowserView.UseUnitInSrcEditor insert place was deleted']);
  965. exit;
  966. end;
  967. GetIdentStartEndAtPosition(Code.Source,CodeMarker.NewPosition,
  968. IdentStart,IdentEnd);
  969. Code.AbsoluteToLineCol(IdentStart,InsertStartPos.Y,InsertStartPos.X);
  970. InsertEndPos:=InsertStartPos;
  971. inc(InsertEndPos.X,IdentEnd-IdentStart);
  972. SrcEdit.ReplaceText(InsertStartPos,InsertEndPos,Identifier);
  973. end;
  974. finally
  975. List.Free;
  976. CodeMarker.Free;
  977. end;
  978. end;
  979. procedure TCodeBrowserView.Work(var Done: Boolean);
  980. // do some work
  981. // This is called during OnIdle, so progress in small steps
  982. var
  983. OldStage: TCodeBrowserWorkStage;
  984. begin
  985. OldStage:=fStage;
  986. case fStage of
  987. cbwsGetScopeOptions: WorkGetScopeOptions;
  988. cbwsGatherPackages: WorkGatherPackages;
  989. cbwsFreeUnusedPackages: WorkFreeUnusedPackages;
  990. cbwsAddNewPackages: WorkAddNewUnitLists;
  991. cbwsGatherFiles: WorkGatherFileLists;
  992. cbwsGatherOutdatedFiles: WorkGatherOutdatedFiles;
  993. cbwsUpdateUnits: WorkUpdateUnits;
  994. cbwsGetViewOptions: WorkGetViewOptions;
  995. cbwsUpdateTreeView: WorkUpdateTreeView;
  996. else
  997. FOptionsChangeStamp:=Options.ChangeStamp;
  998. UpdateNeeded:=false;
  999. Done:=true;
  1000. ProgressBar1.Position:=ProgressTotal;
  1001. ProgressBar1.Visible:=false;
  1002. exit;
  1003. end;
  1004. if ord(OldStage)<ord(cbwsFinished) then begin
  1005. Done:=false;
  1006. ProgressBar1.Visible:=true;
  1007. UpdateStatusBar(fStage<cbwsFinished);
  1008. end;
  1009. //if fStage=cbwsFinished then CodeToolBoss.WriteMemoryStats;
  1010. end;
  1011. procedure TCodeBrowserView.WorkGetScopeOptions;
  1012. var
  1013. CurChangStamp: LongInt;
  1014. begin
  1015. DebugLn(['TCodeBrowserView.WorkGetScopeOptions START']);
  1016. IdleTimer1.Enabled:=false;
  1017. ProgressBar1.Position:=ProgressGetScopeStart;
  1018. CurChangStamp:=Options.ChangeStamp;
  1019. Options.WithRequiredPackages:=ScopeWithRequiredPackagesCheckBox.Checked;
  1020. Options.Scope:=ScopeComboBox.Text;
  1021. // this stage finished -> next stage
  1022. if UpdateNeeded or (Options.ChangeStamp<>CurChangStamp) then
  1023. fStage:=cbwsGatherPackages
  1024. else
  1025. fStage:=cbwsGetViewOptions;
  1026. ProgressBar1.Position:=ProgressGetScopeStart+ProgressGetScopeSize;
  1027. end;
  1028. procedure TCodeBrowserView.WorkGatherPackages;
  1029. procedure AddPackage(APackage: TLazPackage);
  1030. begin
  1031. TCodeBrowserUnitList.Create(APackage.Name,FWorkingParserRoot);
  1032. end;
  1033. procedure AddPackages(FirstDependency: TPkgDependency);
  1034. var
  1035. List: TFPList;
  1036. i: Integer;
  1037. begin
  1038. List:=nil;
  1039. try
  1040. PackageGraph.GetAllRequiredPackages(nil,FirstDependency,List);
  1041. if (List=nil) then exit;
  1042. for i:=0 to List.Count-1 do begin
  1043. if TObject(List[i]) is TLazPackage then
  1044. AddPackage(TLazPackage(List[i]));
  1045. end;
  1046. finally
  1047. List.Free;
  1048. end;
  1049. end;
  1050. var
  1051. APackage: TLazPackage;
  1052. RootOwner: string;
  1053. i: Integer;
  1054. begin
  1055. // clean up
  1056. if fOutdatedFiles<>nil then fOutdatedFiles.Clear;
  1057. // find ParserRoot
  1058. RootOwner:='';
  1059. if Options.Scope=IDEDescription then begin
  1060. RootOwner:=CodeBrowserIDEName;
  1061. end else if Options.Scope=ProjectDescription then begin
  1062. RootOwner:=CodeBrowserProjectName;
  1063. end else begin
  1064. APackage:=PackageGraph.FindPackageWithName(Options.Scope,nil);
  1065. if APackage<>nil then
  1066. RootOwner:=APackage.Name;
  1067. end;
  1068. DebugLn(['TCodeBrowserView.WorkGatherPackages RootOwner="',RootOwner,'"']);
  1069. FreeAndNil(FWorkingParserRoot);
  1070. FWorkingParserRoot:=TCodeBrowserUnitList.Create(RootOwner,nil);
  1071. // find required packages
  1072. if Options.WithRequiredPackages then begin
  1073. if SysUtils.CompareText(FWorkingParserRoot.Owner,CodeBrowserIDEName)=0 then begin
  1074. for i:=0 to PackageGraph.Count-1 do
  1075. AddPackage(PackageGraph[i]);
  1076. end else if SysUtils.CompareText(FWorkingParserRoot.Owner,CodeBrowserProjectName)=0
  1077. then begin
  1078. AddPackages(Project1.FirstRequiredDependency);
  1079. end else if FWorkingParserRoot.Owner<>'' then begin
  1080. APackage:=PackageGraph.FindPackageWithName(FWorkingParserRoot.Owner,nil);
  1081. if APackage<>nil then
  1082. AddPackages(APackage.FirstRequiredDependency);
  1083. end;
  1084. end;
  1085. // update ParserRoot item (children will be updated on next Idle)
  1086. if FParserRoot=nil then begin
  1087. FParserRoot:=TCodeBrowserUnitList.Create(FWorkingParserRoot.Owner,nil);
  1088. inc(FScannedPackages);
  1089. end else begin
  1090. FParserRoot.Owner:=FWorkingParserRoot.Owner;
  1091. end;
  1092. // this stage finished -> next stage
  1093. fStage:=cbwsFreeUnusedPackages;
  1094. ProgressBar1.Position:=ProgressGatherPackagesStart+ProgressGatherPackagesSize;
  1095. end;
  1096. procedure TCodeBrowserView.WorkFreeUnusedPackages;
  1097. function FindUnusedUnitList: TCodeBrowserUnitList;
  1098. var
  1099. Node: TAVLTreeNode;
  1100. UnusedPackage: TCodeBrowserUnitList;
  1101. PackageName: String;
  1102. begin
  1103. // find an unused package (a package in ParserRoot but not in WorkingParserRoot)
  1104. Result:=nil;
  1105. if (FParserRoot=nil) or (FParserRoot.UnitLists=nil) then exit;
  1106. Node:=FParserRoot.UnitLists.FindLowest;
  1107. while Node<>nil do begin
  1108. UnusedPackage:=TCodeBrowserUnitList(Node.Data);
  1109. PackageName:=UnusedPackage.Owner;
  1110. if (FWorkingParserRoot=nil)
  1111. or (FWorkingParserRoot.UnitLists=nil)
  1112. or (FWorkingParserRoot.UnitLists.FindKey(Pointer(PackageName),
  1113. @CompareAnsiStringWithUnitListOwner)=nil)
  1114. then begin
  1115. Result:=UnusedPackage;
  1116. exit;
  1117. end;
  1118. Node:=FParserRoot.UnitLists.FindSuccessor(Node);
  1119. end;
  1120. end;
  1121. var
  1122. UnusedPackage: TCodeBrowserUnitList;
  1123. begin
  1124. DebugLn(['TCodeBrowserView.WorkFreeUnusedPackages START']);
  1125. // find an unused package
  1126. UnusedPackage:=FindUnusedUnitList;
  1127. if UnusedPackage=nil then begin
  1128. // this stage finished -> next stage
  1129. fStage:=cbwsAddNewPackages;
  1130. ProgressBar1.Position:=ProgressFreeUnusedPkgStart+ProgressFreeUnusedPkgSize;
  1131. exit;
  1132. end;
  1133. // free the unused package
  1134. FreeUnitList(UnusedPackage);
  1135. end;
  1136. procedure TCodeBrowserView.WorkAddNewUnitLists;
  1137. var
  1138. Node: TAVLTreeNode;
  1139. List: TCodeBrowserUnitList;
  1140. begin
  1141. ProgressBar1.Position:=ProgressAddNewUnitListsStart;
  1142. if (FWorkingParserRoot<>nil) and (FWorkingParserRoot.UnitLists<>nil)
  1143. and (FParserRoot<>nil) then begin
  1144. Node:=FWorkingParserRoot.UnitLists.FindLowest;
  1145. while Node<>nil do begin
  1146. List:=TCodeBrowserUnitList(Node.Data);
  1147. if FParserRoot.FindUnitList(List.Owner)=nil then begin
  1148. // new unit list
  1149. TCodeBrowserUnitList.Create(List.Owner,FParserRoot);
  1150. inc(FScannedPackages);
  1151. end;
  1152. Node:=FWorkingParserRoot.UnitLists.FindSuccessor(Node);
  1153. end;
  1154. end;
  1155. // this stage finished -> next stage
  1156. fStage:=cbwsGatherFiles;
  1157. ProgressBar1.Position:=ProgressAddNewUnitListsStart+ProgressAddNewUnitListsSize;
  1158. end;
  1159. procedure TCodeBrowserView.WorkGatherFileLists;
  1160. function ListFilesAreValid(List: TCodeBrowserUnitList): boolean;
  1161. begin
  1162. Result:=List.UnitsValid;
  1163. end;
  1164. function FindListWithInvalidFileList(StartList: TCodeBrowserUnitList
  1165. ): TCodeBrowserUnitList;
  1166. var
  1167. APackage: TCodeBrowserUnitList;
  1168. Node: TAVLTreeNode;
  1169. begin
  1170. Result:=nil;
  1171. if StartList=nil then exit;
  1172. if not ListFilesAreValid(StartList) then begin
  1173. Result:=StartList;
  1174. exit;
  1175. end;
  1176. if (StartList.UnitLists=nil) then exit;
  1177. Node:=StartList.UnitLists.FindLowest;
  1178. while Node<>nil do begin
  1179. APackage:=TCodeBrowserUnitList(Node.Data);
  1180. Result:=FindListWithInvalidFileList(APackage);
  1181. if Result<>nil then exit;
  1182. Node:=StartList.UnitLists.FindSuccessor(Node);
  1183. end;
  1184. end;
  1185. var
  1186. List: TCodeBrowserUnitList;
  1187. begin
  1188. DebugLn(['TCodeBrowserView.WorkGatherFiles START']);
  1189. // find a unit list which needs update
  1190. List:=FindListWithInvalidFileList(FParserRoot);
  1191. if List=nil then begin
  1192. // this stage finished -> next stage
  1193. fStage:=cbwsGatherOutdatedFiles;
  1194. ProgressBar1.Position:=ProgressGatherFileListsStart+ProgressGatherFileListsSize;
  1195. exit;
  1196. end;
  1197. WorkUpdateFileList(List);
  1198. end;
  1199. procedure TCodeBrowserView.WorkUpdateFileList(List: TCodeBrowserUnitList);
  1200. var
  1201. NewFileList: TAVLTree;
  1202. procedure AddFile(const Filename: string; ClearIncludedByInfo: boolean);
  1203. begin
  1204. //DebugLn(['AddFile Filename="',Filename,'"']);
  1205. if Filename='' then exit;
  1206. if System.Pos('$',Filename)>0 then begin
  1207. DebugLn(['WARNING: TCodeBrowserView.WorkUpdateFiles Macros in filename ',Filename]);
  1208. exit;
  1209. end;
  1210. if NewFileList.FindKey(Pointer(Filename),@CompareAnsiStringWithUnitFilename)<>nil
  1211. then exit;
  1212. //DebugLn(['TCodeBrowserView.WorkUpdateFiles AddFile ',Filename]);
  1213. NewFileList.Add(TCodeBrowserUnit.Create(Filename));
  1214. if ClearIncludedByInfo then begin
  1215. CodeToolBoss.SourceCache.ClearIncludedByEntry(Filename);
  1216. end;
  1217. end;
  1218. procedure AddFilesOfProject(AProject: TProject);
  1219. var
  1220. AnUnitInfo: TUnitInfo;
  1221. begin
  1222. if AProject=nil then exit;
  1223. AnUnitInfo:=AProject.FirstPartOfProject;
  1224. //DebugLn(['AddFilesOfProject ',AnUnitInfo<>nil]);
  1225. while AnUnitInfo<>nil do begin
  1226. //DebugLn(['AddFilesOfProject ',AnUnitInfo.Filename]);
  1227. if FilenameIsPascalUnit(AnUnitInfo.Filename)
  1228. or (AnUnitInfo=aProject.MainUnitInfo) then
  1229. AddFile(AnUnitInfo.Filename,false);
  1230. AnUnitInfo:=AnUnitInfo.NextPartOfProject;
  1231. end;
  1232. end;
  1233. procedure AddFilesOfPackageFCL;
  1234. var
  1235. LazDir: String;
  1236. UnitSetID: string;
  1237. UnitSetChanged: Boolean;
  1238. UnitSet: TFPCUnitSetCache;
  1239. Filename: String;
  1240. ConfigCache: TFPCTargetConfigCache;
  1241. Node: TAVLTreeNode;
  1242. Item: PStringToStringTreeItem;
  1243. begin
  1244. // use unitset of the lazarus source directory
  1245. LazDir:=AppendPathDelim(EnvironmentOptions.GetParsedLazarusDirectory);
  1246. if (LazDir='') or (not FilenameIsAbsolute(LazDir)) then exit;
  1247. UnitSetID:=CodeToolBoss.GetUnitSetIDForDirectory(LazDir);
  1248. if UnitSetID='' then exit;
  1249. UnitSetChanged:=false;
  1250. UnitSet:=CodeToolBoss.FPCDefinesCache.FindUnitSetWithID(UnitSetID,
  1251. UnitSetChanged,false);
  1252. if UnitSet=nil then exit;
  1253. ConfigCache:=UnitSet.GetConfigCache(false);
  1254. if (ConfigCache=nil) or (ConfigCache.Units=nil) then exit;
  1255. Node:=ConfigCache.Units.Tree.FindLowest;
  1256. while Node<>nil do begin
  1257. Item:=PStringToStringTreeItem(Node.Data);
  1258. Filename:=Item^.Value;
  1259. if (CompareFileExt(Filename,'ppu',false)=0) then begin
  1260. // search source in fpc sources
  1261. Filename:=UnitSet.GetUnitSrcFile(ExtractFileNameOnly(Filename));
  1262. end;
  1263. if FilenameIsPascalUnit(Filename) then
  1264. AddFile(Filename,false);
  1265. Node:=ConfigCache.Units.Tree.F