PageRenderTime 73ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/ide/codebrowser.pas

http://github.com/graemeg/lazarus
Pascal | 3356 lines | 2875 code | 280 blank | 201 comment | 398 complexity | e2cb45deae453ab5eab4e6f5b1f1ff4f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception
  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.FindSuccessor(Node);
  1266. end;
  1267. end;
  1268. procedure AddFilesOfPackage(APackage: TLazPackage);
  1269. var
  1270. i: Integer;
  1271. PkgFile: TPkgFile;
  1272. aFilename: String;
  1273. begin
  1274. if APackage=nil then exit;
  1275. for i:=0 to APackage.FileCount-1 do begin
  1276. PkgFile:=APackage.Files[i];
  1277. if (PkgFile.FileType in PkgFileUnitTypes) then begin
  1278. aFilename:=PkgFile.GetFullFilename;
  1279. if not FilenameIsPascalUnit(aFilename) then begin
  1280. debugln(['WARNING: AddFilesOfPackage: package ',APackage.Filename,' has a unit with a non unit extension: ',aFilename]);
  1281. end;
  1282. AddFile(aFilename,true);
  1283. end;
  1284. end;
  1285. if APackage.Name='FCL' then begin
  1286. AddFilesOfPackageFCL;
  1287. end;
  1288. end;
  1289. procedure AddFilesOfDirectory(const Directory: string;
  1290. ClearIncludedByInfo: boolean);
  1291. // ! needs ending PathDelim !
  1292. var
  1293. FileInfo: TSearchRec;
  1294. begin
  1295. //DebugLn(['AddFilesOfDirectory Directory="',Directory,'"']);
  1296. if (not FilenameIsAbsolute(Directory))
  1297. or (not DirectoryExistsUTF8(Directory)) then begin
  1298. DebugLn(['AddFilesOfDirectory WARNING: does not exist: "',Directory,'"']);
  1299. exit;
  1300. end;
  1301. if FindFirstUTF8(Directory+FileMask,faAnyFile,FileInfo)=0 then begin
  1302. repeat
  1303. // check if special file
  1304. if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='')
  1305. then
  1306. continue;
  1307. if FilenameIsPascalUnit(FileInfo.Name) then
  1308. AddFile(Directory+FileInfo.Name,ClearIncludedByInfo);
  1309. until FindNextUTF8(FileInfo)<>0;
  1310. end;
  1311. FindCloseUTF8(FileInfo);
  1312. end;
  1313. procedure AddFilesOfSearchPath(const SrcPath, BaseDir: string;
  1314. ClearIncludedByInfo: boolean);
  1315. var
  1316. Dir: String;
  1317. p: Integer;
  1318. begin
  1319. //DebugLn(['AddFilesOfSearchPath SrcPath="',SrcPath,'" BaseDir="',BaseDir,'"']);
  1320. p:=1;
  1321. while (p<=length(SrcPath)) do begin
  1322. Dir:=GetNextDelimitedItem(SrcPath,';',p);
  1323. if Dir<>'' then begin
  1324. if not FilenameIsAbsolute(Dir) then
  1325. Dir:=BaseDir+PathDelim+Dir;
  1326. Dir:=CleanAndExpandDirectory(Dir);
  1327. AddFilesOfDirectory(Dir,ClearIncludedByInfo);
  1328. end;
  1329. end;
  1330. end;
  1331. procedure AddFilesOfIDE;
  1332. var
  1333. LazDefines: TDefineTemplate;
  1334. LazSrcDir: TDefineTemplate;
  1335. LazIDEDir: TDefineTemplate;
  1336. LazIDESrcPath: TDefineTemplate;
  1337. SrcPath: String;
  1338. LazDir: String;
  1339. begin
  1340. LazDir:=AppendPathDelim(EnvironmentOptions.GetParsedLazarusDirectory);
  1341. if not DirectoryExistsUTF8(LazDir) then begin
  1342. DebugLn(['AddFilesOfIDE WARNING: lazarus directory not found: "',LazDir,'"']);
  1343. exit;
  1344. end;
  1345. // get the SrcPath template of the lazarus/ide directory
  1346. LazDefines:=CodeToolBoss.DefineTree
  1347. .FindDefineTemplateByName(StdDefTemplLazarusSources,true);
  1348. if LazDefines=nil then begin
  1349. DebugLn(['AddFilesOfIDE WARNING: codetools define templates for lazarus not found']);
  1350. exit;
  1351. end;
  1352. LazSrcDir:=LazDefines.FindChildByName(StdDefTemplLazarusSrcDir);
  1353. if LazSrcDir=nil then begin
  1354. DebugLn(['AddFilesOfIDE WARNING: codetools define templates for lazarus directory not found']);
  1355. exit;
  1356. end;
  1357. LazIDEDir:=LazSrcDir.FindChildByName('ide');
  1358. if LazIDEDir=nil then begin
  1359. DebugLn(['AddFilesOfIDE WARNING: codetools define templates for lazarus ide directory not found']);
  1360. exit;
  1361. end;
  1362. LazIDESrcPath:=LazIDEDir.FindChildByName('IDE path addition');
  1363. if LazIDESrcPath=nil then begin
  1364. DebugLn(['AddFilesOfIDE WARNING: codetools define templates for src path of lazarus ide directory not found']);
  1365. exit;
  1366. end;
  1367. SrcPath:=StringReplace(LazIDESrcPath.Value,'$(#LazarusDir)',LazDir,
  1368. [rfReplaceAll, rfIgnoreCase]);
  1369. AddFilesOfSearchPath(SrcPath+';.',LazDir+'ide'+PathDelim,true);
  1370. end;
  1371. procedure DeleteUnusedFiles;
  1372. var
  1373. Node: TAVLTreeNode;
  1374. CurUnit: TCodeBrowserUnit;
  1375. NextNode: TAVLTreeNode;
  1376. begin
  1377. if List.Units=nil then exit;
  1378. Node:=List.Units.FindLowest;
  1379. while Node<>nil do begin
  1380. NextNode:=List.Units.FindSuccessor(Node);
  1381. CurUnit:=TCodeBrowserUnit(Node.Data);
  1382. if NewFileList.FindKey(Pointer(CurUnit.Filename),
  1383. @CompareAnsiStringWithUnitFilename)=nil
  1384. then begin
  1385. // this unit is not part of List anymore -> delete
  1386. RemoveUnit(CurUnit);
  1387. List.DeleteUnit(CurUnit);
  1388. end;
  1389. Node:=NextNode;
  1390. end;
  1391. end;
  1392. procedure AddNewFiles;
  1393. var
  1394. Node: TAVLTreeNode;
  1395. AnUnit: TCodeBrowserUnit;
  1396. begin
  1397. Node:=NewFileList.FindLowest;
  1398. while Node<>nil do begin
  1399. AnUnit:=TCodeBrowserUnit(Node.Data);
  1400. //DebugLn(['AddNewFiles ',AnUnit.Filename,' exists=',List.FindUnit(AnUnit.Filename)<>nil]);
  1401. if List.FindUnit(AnUnit.Filename)=nil then begin
  1402. // this unit was not part of List -> add
  1403. //DebugLn(['AddNewFiles "',List.Owner,'" "',AnUnit.Filename,'"']);
  1404. List.AddUnit(AnUnit.Filename);
  1405. end;
  1406. Node:=NewFileList.FindSuccessor(Node);
  1407. end;
  1408. end;
  1409. var
  1410. APackage: TLazPackage;
  1411. begin
  1412. DebugLn(['TCodeBrowserView.WorkUpdateFiles ',List.Owner]);
  1413. NewFileList:=TAVLTree.Create(@CompareUnitFilenames);
  1414. try
  1415. // get new list of files
  1416. if List.Owner=CodeBrowserIDEName then begin
  1417. AddFilesOfIDE;
  1418. end else if List.Owner=CodeBrowserProjectName then begin
  1419. AddFilesOfProject(Project1);
  1420. end else begin
  1421. APackage:=PackageGraph.FindPackageWithName(List.Owner,nil);
  1422. AddFilesOfPackage(APackage);
  1423. end;
  1424. // update file list
  1425. DeleteUnusedFiles;
  1426. AddNewFiles;
  1427. List.UnitsValid:=true;
  1428. finally
  1429. NewFileList.FreeAndClear;
  1430. NewFileList.Free;
  1431. end;
  1432. end;
  1433. procedure TCodeBrowserView.WorkGatherOutdatedFiles;
  1434. // add all files to fOutdatedFiles
  1435. procedure AddFile(AnUnit: TCodeBrowserUnit);
  1436. begin
  1437. if fOutdatedFiles=nil then
  1438. fOutdatedFiles:=TAVLTree.Create(@CompareUnitFilenames);
  1439. if fOutdatedFiles.Find(AnUnit)<>nil then exit;
  1440. fOutdatedFiles.Add(AnUnit);
  1441. end;
  1442. procedure AddFiles(List: TCodeBrowserUnitList);
  1443. var
  1444. Node: TAVLTreeNode;
  1445. begin
  1446. if List.Units<>nil then begin
  1447. Node:=List.Units.FindLowest;
  1448. while Node<>nil do begin
  1449. AddFile(TCodeBrowserUnit(Node.Data));
  1450. Node:=List.Units.FindSuccessor(Node);
  1451. end;
  1452. end;
  1453. if List.UnitLists<>nil then begin
  1454. Node:=List.UnitLists.FindLowest;
  1455. while Node<>nil do begin
  1456. AddFiles(TCodeBrowserUnitList(Node.Data));
  1457. Node:=List.UnitLists.FindSuccessor(Node);
  1458. end;
  1459. end;
  1460. end;
  1461. begin
  1462. if fOutdatedFiles<>nil then
  1463. fOutdatedFiles.Clear;
  1464. AddFiles(ParserRoot);
  1465. // this stage finished -> next stage
  1466. fStage:=cbwsUpdateUnits;
  1467. ProgressBar1.Position:=ProgressGatherOutdatedFilesStart+ProgressGatherOutdatedFilesSize;
  1468. end;
  1469. procedure TCodeBrowserView.WorkUpdateUnits;
  1470. function FindOutdatedUnit: TCodeBrowserUnit;
  1471. var
  1472. Node: TAVLTreeNode;
  1473. begin
  1474. Result:=nil;
  1475. if fOutdatedFiles=nil then exit;
  1476. Node:=fOutdatedFiles.FindLowest;
  1477. if Node=nil then exit;
  1478. Result:=TCodeBrowserUnit(Node.Data);
  1479. end;
  1480. const
  1481. SmallTimeStep = (1/86400)/5;
  1482. var
  1483. AnUnit: TCodeBrowserUnit;
  1484. StartTime: TDateTime;
  1485. begin
  1486. //DebugLn(['TCodeBrowserView.WorkUpdateUnits START']);
  1487. CodeToolBoss.ActivateWriteLock;
  1488. try
  1489. // parse units
  1490. StartTime:=Now;
  1491. repeat
  1492. AnUnit:=FindOutdatedUnit;
  1493. if AnUnit=nil then begin
  1494. // this stage finished -> next stage
  1495. fStage:=cbwsGetViewOptions;
  1496. ProgressBar1.Position:=ProgressUpdateUnitsStart+ProgressUpdateUnitsSize;
  1497. exit;
  1498. end;
  1499. WorkUpdateUnit(AnUnit);
  1500. until Abs(Now-StartTime)>SmallTimeStep;
  1501. finally
  1502. CodeToolBoss.DeactivateWriteLock;
  1503. end;
  1504. end;
  1505. procedure TCodeBrowserView.WorkUpdateUnit(AnUnit: TCodeBrowserUnit);
  1506. procedure UpdateScannedCounters(Tool: TCodeTool);
  1507. var
  1508. LineCnt: Integer;
  1509. ByteCnt: Integer;
  1510. i: Integer;
  1511. Link: TSourceLink;
  1512. CodeBuf: TCodeBuffer;
  1513. LastCode: TCodeBuffer;
  1514. begin
  1515. if (Tool=nil) or (Tool.Scanner=nil) then exit;
  1516. LineCnt:=0;
  1517. ByteCnt:=0;
  1518. LastCode:=nil;
  1519. for i:=0 to Tool.Scanner.LinkCount-1 do begin
  1520. Link:=Tool.Scanner.Links[i];
  1521. CodeBuf:=TCodeBuffer(Link.Code);
  1522. if CodeBuf=nil then continue;
  1523. if CodeBuf<>LastCode then begin
  1524. inc(LineCnt,CodeBuf.LineCount);
  1525. inc(ByteCnt,CodeBuf.SourceLength);
  1526. LastCode:=CodeBuf;
  1527. end;
  1528. end;
  1529. AnUnit.ScannedBytes:=ByteCnt;
  1530. AnUnit.ScannedLines:=LineCnt;
  1531. AnUnit.ScannedIdentifiers:=CountIdentifiers(Tool);
  1532. AnUnit.CodeTool:=Tool;
  1533. inc(FScannedBytes,AnUnit.ScannedBytes);
  1534. inc(FScannedLines,AnUnit.ScannedLines);
  1535. inc(FScannedIdentifiers,AnUnit.ScannedIdentifiers);
  1536. //DebugLn(['UpdateScannedCounters ',ExtractFileName(AnUnit.Filename),' LineCnt=',LineCnt,' ByteCnt=',ByteCnt,' ',DbgSName(AnUnit.CodeTool)]);
  1537. end;
  1538. var
  1539. MainCodeBuf: TCodeBuffer;
  1540. Tool: TCodeTool;
  1541. begin
  1542. //DebugLn(['TCodeBrowserView.WorkUpdateUnit START ',AnUnit.Filename]);
  1543. // mark as updated
  1544. fOutdatedFiles.Remove(AnUnit);
  1545. // reset scanning counters
  1546. if AnUnit.Scanned then begin
  1547. dec(FScannedBytes,AnUnit.ScannedBytes);
  1548. dec(FScannedLines,AnUnit.ScannedLines);
  1549. dec(FScannedIdentifiers,AnUnit.ScannedIdentifiers);
  1550. AnUnit.ScannedBytes:=0;
  1551. AnUnit.ScannedLines:=0;
  1552. AnUnit.ScannedIdentifiers:=0;
  1553. dec(FScannedUnits);
  1554. end;
  1555. AnUnit.Scanned:=true;
  1556. inc(FScannedUnits);
  1557. // load the file
  1558. AnUnit.CodeBuffer:=CodeToolBoss.LoadFile(AnUnit.Filename,false,false);
  1559. if AnUnit.CodeBuffer=nil then exit;
  1560. // check if this is a unit
  1561. MainCodeBuf:=CodeToolBoss.GetMainCode(AnUnit.CodeBuffer);
  1562. if MainCodeBuf<>AnUnit.CodeBuffer then begin
  1563. // this file was used as an include file
  1564. DebugLn(['TCodeBrowserView.WorkUpdateUnit HINT: this is not a unit: ',AnUnit.Filename,
  1565. ' (it was included by ',MainCodeBuf.Filename,')']);
  1566. exit;
  1567. end;
  1568. // scan
  1569. CodeToolBoss.Explore(AnUnit.CodeBuffer,Tool,false,true);
  1570. UpdateScannedCounters(Tool);
  1571. //DebugLn(['TCodeBrowserView.WorkUpdateUnit END ',AnUnit.Filename]);
  1572. end;
  1573. procedure TCodeBrowserView.WorkGetViewOptions;
  1574. var
  1575. NewLevels: TStringList;
  1576. begin
  1577. //DebugLn(['TCodeBrowserView.WorkGetViewOptions START']);
  1578. Options.ShowPrivate:=ShowPrivateCheckBox.Checked;
  1579. Options.ShowProtected:=ShowProtectedCheckBox.Checked;
  1580. Options.ShowEmptyNodes:=ShowEmptyNodesCheckBox.Checked;
  1581. // levels
  1582. NewLevels:=TStringList.Create;
  1583. if ShowPackagesCheckBox.Checked then
  1584. NewLevels.Add(CodeBrowserLevelNames[cblPackages]);
  1585. if ShowUnitsCheckBox.Checked then
  1586. NewLevels.Add(CodeBrowserLevelNames[cblUnits]);
  1587. if ShowIdentifiersCheckBox.Checked then
  1588. NewLevels.Add(CodeBrowserLevelNames[cblIdentifiers]);
  1589. Options.Levels:=NewLevels;
  1590. NewLevels.Free;
  1591. // level filter
  1592. Options.LevelFilterText[cblPackages]:=PackageFilterEdit.Text;
  1593. if PackageFilterBeginsSpeedButton.Down then
  1594. Options.LevelFilterType[cblPackages]:=cbtfBegins;
  1595. if PackageFilterContainsSpeedButton.Down then
  1596. Options.LevelFilterType[cblPackages]:=cbtfContains;
  1597. Options.LevelFilterText[cblUnits]:=UnitFilterEdit.Text;
  1598. //DebugLn(['TCodeBrowserView.WorkGetOptions UnitFIlter=',Options.LevelFilterText[cblUnits],' Edit=',UnitFilterEdit.Text]);
  1599. if UnitFilterBeginsSpeedButton.Down then
  1600. Options.LevelFilterType[cblUnits]:=cbtfBegins;
  1601. if UnitFilterContainsSpeedButton.Down then
  1602. Options.LevelFilterType[cblUnits]:=cbtfContains;
  1603. Options.LevelFilterText[cblIdentifiers]:=IdentifierFilterEdit.Text;
  1604. if IdentifierFilterBeginsSpeedButton.Down then
  1605. Options.LevelFilterType[cblIdentifiers]:=cbtfBegins;
  1606. if IdentifierFilterContainsSpeedButton.Down then
  1607. Options.LevelFilterType[cblIdentifiers]:=cbtfContains;
  1608. DebugLn(['TCodeBrowserView.WorkGetViewOptions UpdateNeeded=',UpdateNeeded,' ChangeStamp=',Options.ChangeStamp<>FOptionsChangeStamp]);
  1609. // this stage finished -> next stage
  1610. if UpdateNeeded or (Options.ChangeStamp<>FOptionsChangeStamp) then
  1611. fStage:=cbwsUpdateTreeView
  1612. else
  1613. fStage:=cbwsFinished;
  1614. ProgressBar1.Position:=ProgressGetViewOptionsStart+ProgressGetViewOptionsSize;
  1615. end;
  1616. procedure TCodeBrowserView.WorkUpdateTreeView;
  1617. begin
  1618. ProgressBar1.Position:=ProgressUpdateTreeViewStart;
  1619. UpdateTreeView;
  1620. // this stage finished -> next stage
  1621. fStage:=cbwsFinished;
  1622. ProgressBar1.Position:=ProgressUpdateTreeViewStart+ProgressUpdateTreeViewSize;
  1623. end;
  1624. procedure TCodeBrowserView.FreeUnitList(List: TCodeBrowserUnitList);
  1625. var
  1626. Node: TAVLTreeNode;
  1627. AnUnit: TCodeBrowserUnit;
  1628. begin
  1629. //DebugLn(['TCodeBrowserView.FreeUnitList ',List.Owner]);
  1630. dec(FScannedPackages);
  1631. if List.Units<>nil then begin
  1632. Node:=List.Units.FindLowest;
  1633. while Node<>nil do begin
  1634. AnUnit:=TCodeBrowserUnit(Node.Data);
  1635. RemoveUnit(AnUnit);
  1636. Node:=List.Units.FindSuccessor(Node);
  1637. end;
  1638. end;
  1639. List.Free;
  1640. end;
  1641. procedure TCodeBrowserView.UpdateStatusBar(Lazy: boolean);
  1642. const
  1643. SmallTimeStep = 1/86400;
  1644. function BigIntToStr(i: integer): string;
  1645. var
  1646. p: Integer;
  1647. ThousandSep: String;
  1648. begin
  1649. if i=0 then begin
  1650. Result:='0';
  1651. exit;
  1652. end;
  1653. Result:='';
  1654. if i>=100000 then begin
  1655. i:=i div 1000;
  1656. Result:='k';
  1657. if i>=100000 then begin
  1658. i:=i div 1000;
  1659. Result:='m';
  1660. if i>=100000 then begin
  1661. i:=i div 1000;
  1662. Result:='g';
  1663. if i>=100000 then begin
  1664. i:=i div 1000;
  1665. Result:='t';
  1666. end;
  1667. end;
  1668. end;
  1669. end;
  1670. p:=0;
  1671. ThousandSep:=AnsiToUTF8(DefaultFormatSettings.ThousandSeparator);
  1672. while i>0 do begin
  1673. if p=3 then begin
  1674. Result:=ThousandSep+Result;
  1675. p:=0;
  1676. end;
  1677. Result:=chr((i mod 10)+ord('0'))+Result;
  1678. i:=i div 10;
  1679. inc(p);
  1680. end;
  1681. end;
  1682. var
  1683. s: String;
  1684. begin
  1685. if Lazy and (Abs(Now-fLastStatusBarUpdate)<SmallTimeStep) then begin
  1686. // the last update is not long ago
  1687. // => skip update
  1688. exit;
  1689. end;
  1690. fLastStatusBarUpdate:=Now;
  1691. s:=Format(lisPackagesUnitsIdentifiersLinesBytes, [BigIntToStr(VisiblePackages)
  1692. , BigIntToStr(ScannedPackages), BigIntToStr(VisibleUnits), BigIntToStr(
  1693. ScannedUnits), BigIntToStr(VisibleIdentifiers), BigIntToStr(
  1694. ScannedIdentifiers), BigIntToStr(ScannedLines), BigIntToStr(ScannedBytes)]);
  1695. if fStage<>cbwsFinished then
  1696. s:=Format(lisScanning2, [s]);
  1697. StatusBar1.SimpleText:=s;
  1698. end;
  1699. function TCodeBrowserView.GetCodeTool(AnUnit: TCodeBrowserUnit): TStandardCodeTool;
  1700. begin
  1701. //DebugLn(['TCodeBrowserView.GetCodeTool ',AnUnit.CodeTool<>nil,' ',AnUnit.CodeBuffer<>nil]);
  1702. Result:=AnUnit.CodeTool;
  1703. if Result<>nil then exit;
  1704. if AnUnit.CodeBuffer=nil then exit;
  1705. Result:=CodeToolBoss.GetCodeToolForSource(AnUnit.CodeBuffer,true,false)
  1706. as TCodeTool;
  1707. AnUnit.CodeTool:=Result;
  1708. //DebugLn(['TCodeBrowserView.GetCodeTool END ',AnUnit.Filename,' ',Result<>nil]);
  1709. end;
  1710. procedure TCodeBrowserView.GetNodeIdentifier(Tool: TStandardCodeTool;
  1711. CTNode: TCodeTreeNode; out Identifier: string);
  1712. function Shorten(const s: string): string;
  1713. const
  1714. MAX_LEN=100;
  1715. begin
  1716. Result:=DbgStr(s);
  1717. if Length(Result)>MAX_LEN then
  1718. Result:=LeftStr(Result, MAX_LEN)+'...';
  1719. end;
  1720. begin
  1721. if CTNode.StartPos>=CTNode.EndPos then begin
  1722. Identifier:='';
  1723. exit;
  1724. end;
  1725. case CTNode.Desc of
  1726. ctnProcedure:
  1727. begin
  1728. Identifier:=Tool.ExtractProcName(CTNode,ProcIdentifierFlags);
  1729. end;
  1730. ctnVarDefinition:
  1731. begin
  1732. Identifier:=Tool.ExtractDefinitionName(CTNode);
  1733. end;
  1734. ctnConstDefinition:
  1735. begin
  1736. Identifier:=Tool.ExtractDefinitionName(CTNode);
  1737. end;
  1738. ctnTypeDefinition,ctnGenericType:
  1739. begin
  1740. Identifier:=Tool.ExtractDefinitionName(CTNode);
  1741. end;
  1742. ctnProperty:
  1743. begin
  1744. Identifier:=Tool.ExtractPropName(CTNode,false);
  1745. end;
  1746. ctnEnumIdentifier:
  1747. begin
  1748. Identifier:=Tool.ExtractIdentifier(CTNode.StartPos);
  1749. end;
  1750. end;
  1751. end;
  1752. procedure TCodeBrowserView.GetNodeDescription(Tool: TStandardCodeTool;
  1753. CTNode: TCodeTreeNode; Identifier: string; out Description: string);
  1754. function Shorten(const s: string): string;
  1755. const
  1756. MAX_LEN=100;
  1757. begin
  1758. Result:=DbgStr(s);
  1759. if Length(Result)>MAX_LEN then
  1760. Result:=LeftStr(Result, MAX_LEN)+'...';
  1761. end;
  1762. const
  1763. NodeFlags = [];
  1764. var
  1765. Inheritance: String;
  1766. begin
  1767. if CTNode.StartPos>=CTNode.EndPos then begin
  1768. Description:='';
  1769. exit;
  1770. end;
  1771. case CTNode.Desc of
  1772. ctnProcedure:
  1773. begin
  1774. Description:=Tool.ExtractProcHead(CTNode,ProcDescFlags);
  1775. end;
  1776. ctnVarDefinition:
  1777. begin
  1778. Description:='var '+Identifier
  1779. +' : '+Shorten(Tool.ExtractDefinitionNodeType(CTNode));
  1780. end;
  1781. ctnConstDefinition:
  1782. begin
  1783. Description:='const '+Shorten(Tool.ExtractNode(CTNode,NodeFlags));
  1784. end;
  1785. ctnTypeDefinition,ctnGenericType:
  1786. begin
  1787. Description:='type '+Identifier;
  1788. if CTNode.FirstChild<>nil then begin
  1789. case CTNode.FirstChild.Desc of
  1790. ctnClass,ctnClassInterface,ctnObject,
  1791. ctnObjCClass,ctnObjCCategory,ctnObjCProtocol,
  1792. ctnCPPClass,
  1793. ctnClassHelper,ctnRecordHelper,ctnTypeHelper:
  1794. begin
  1795. case CTNode.FirstChild.Desc of
  1796. ctnClassInterface:
  1797. Description:=Description+' = interface';
  1798. ctnObject:
  1799. Description:=Description+' = object';
  1800. ctnObjCClass:
  1801. Description:=Description+' = objcclass';
  1802. ctnObjCCategory:
  1803. Description:=Description+' = objccategory';
  1804. ctnObjCProtocol:
  1805. Description:=Description+' = objcprotocol';
  1806. ctnCPPClass:
  1807. Description:=Description+' = cppclass';
  1808. ctnClassHelper:
  1809. Description:=Description+' = class helper';
  1810. ctnRecordHelper:
  1811. Description:=Description+' = record helper';
  1812. ctnTypeHelper:
  1813. Description:=Description+' = type helper';
  1814. else
  1815. Description:=Description+' = class';
  1816. end;
  1817. Inheritance:=Tool.ExtractClassInheritance(CTNode.FirstChild,[]);
  1818. if Inheritance<>'' then
  1819. Description:=Description+'('+Inheritance+')';
  1820. end;
  1821. ctnRecordType:
  1822. Description:=Description+' = record';
  1823. end;
  1824. end;
  1825. end;
  1826. ctnProperty:
  1827. begin
  1828. Description:='property '+Shorten(Tool.ExtractProperty(CTNode,PropDescFlags));
  1829. end;
  1830. ctnEnumIdentifier:
  1831. begin
  1832. Description:='enum '+Identifier;
  1833. end;
  1834. end;
  1835. end;
  1836. procedure TCodeBrowserView.UpdateTreeView;
  1837. var
  1838. ShowPackages: boolean;
  1839. ShowUnits: boolean;
  1840. ShowIdentifiers: boolean;
  1841. ShowPrivate: boolean;
  1842. ShowProtected: boolean;
  1843. ShowEmptyNodes: boolean;
  1844. NewPackageCount: integer;
  1845. NewUnitCount: integer;
  1846. NewIdentifierCount, ShownIdentifierCount: PtrInt;
  1847. UsedMem: PtrUInt;
  1848. LevelFilterText: array[TCodeBrowserLevel] of string;
  1849. LevelFilterType: array[TCodeBrowserLevel] of TCodeBrowserTextFilter;
  1850. function IncUsedMem(c: integer): boolean;
  1851. begin
  1852. Result:=(UsedMem div 16384)<>((UsedMem{%H-}+c) div 16384);
  1853. {%H-}inc(UsedMem,c);
  1854. end;
  1855. function IdentifierFitsFilter(LvlType: TCodeBrowserLevel;
  1856. const Identifier: string): boolean;
  1857. begin
  1858. //DebugLn(['IdentifierFitsFilter Identifier=',Identifier,' Filter=',LevelFilterText[LvlType]]);
  1859. if (LevelFilterText[LvlType]='') then exit(true);
  1860. if Identifier='' then exit(false);
  1861. case LevelFilterType[LvlType] of
  1862. cbtfBegins:
  1863. Result:=ComparePrefixIdent(PChar(Pointer(LevelFilterText[LvlType])),
  1864. PChar(Pointer(Identifier)));
  1865. cbtfContains:
  1866. begin
  1867. Result:=IdentifierPos(PChar(Pointer(LevelFilterText[LvlType])),
  1868. PChar(Pointer(Identifier)))>=0;
  1869. //if Result then
  1870. // debugln(['IdentifierFitsFilter Identifier="',Identifier,'" Filter="',LevelFilterText[LvlType],'"']);
  1871. end
  1872. else
  1873. Result:=true;
  1874. end;
  1875. end;
  1876. procedure AddUnitNodes(SrcUnit: TCodeBrowserUnit; var DestUnit: TObject);
  1877. var
  1878. CTTool: TStandardCodeTool;
  1879. procedure AddChildNode(ParentBrowserNode: TCodeBrowserNode;
  1880. CTNode: TCodeTreeNode);
  1881. var
  1882. NewChildNode: TCodeBrowserNode;
  1883. ChildDescription, ChildIdentifier: string;
  1884. NewCodePos: TCodePosition;
  1885. begin
  1886. //DebugLn(['AddChildNode ',ChildCTNode.DescAsString,' ',ChildDescription]);
  1887. if ShownIdentifierCount>=CodeBrowserMaxTVIdentifiers then exit;
  1888. if (CTNode.Parent.Desc=ctnClassPrivate) and (not ShowPrivate) then
  1889. exit;
  1890. if (CTNode.Parent.Desc=ctnClassProtected) and (not ShowProtected)
  1891. then
  1892. exit;
  1893. GetNodeIdentifier(CTTool,CTNode,ChildIdentifier);
  1894. if IdentifierFitsFilter(cblIdentifiers,ChildIdentifier) then begin
  1895. inc(ShownIdentifierCount);
  1896. GetNodeDescription(CTTool,CTNode,ChildIdentifier,ChildDescription);
  1897. NewChildNode:=ParentBrowserNode.AddNode(ChildDescription,ChildIdentifier);
  1898. if NewChildNode<>nil then begin
  1899. NewChildNode.Desc:=CTNode.Desc;
  1900. CTTool.CleanPosToCodePos(CTNode.StartPos,NewCodePos);
  1901. NewChildNode.CodePos:=NewCodePos;
  1902. {$IFDEF VerboseCodeBrowser}
  1903. if (length(ChildDescription)>1000) then
  1904. debugln(['AddChildNode WARNING: big description ',SrcUnit.Filename,' desc=',ChildDescription]);
  1905. if IncUsedMem(NewChildNode.GetMemSize) then
  1906. debugln(['AddChildNode used mem ',UsedMem]);
  1907. {$ENDIF}
  1908. end;
  1909. end;
  1910. end;
  1911. procedure AddIdentifierNode(CTNode: TCodeTreeNode);
  1912. var
  1913. NewNode: TCodeBrowserNode;
  1914. ChildCTNode: TCodeTreeNode;
  1915. Description, Identifier: string;
  1916. CurUnit: TCodeBrowserUnit;
  1917. NewCodePos: TCodePosition;
  1918. begin
  1919. if not ShowIdentifiers then exit;
  1920. if ShownIdentifierCount>CodeBrowserMaxTVIdentifiers then exit;
  1921. if DestUnit=nil then
  1922. DestUnit:=TCodeBrowserUnit.Create('');
  1923. CurUnit:=TCodeBrowserUnit(DestUnit);
  1924. //DebugLn(['AddIdentifierNode ',CTNode.DescAsString,' Description="',Description,'"']);
  1925. GetNodeIdentifier(CTTool,CTNode,Identifier);
  1926. NewNode:=CurUnit.AddNode('',Identifier);
  1927. {$IFDEF VerboseCodeBrowser}
  1928. if (length(Description)>100) then
  1929. debugln(['AddIdentifierNode WARNING: big description ',CurUnit.Filename,' desc=',Description]);
  1930. if IncUsedMem(NewNode.GetMemSize) then
  1931. debugln(['AddIdentifierNode used mem ',UsedMem,' ',CurUnit.Filename,' ',CurUnit.ChildNodeCount]);
  1932. {$ENDIF}
  1933. NewNode.Desc:=CTNode.Desc;
  1934. CTTool.CleanPosToCodePos(CTNode.StartPos,NewCodePos);
  1935. NewNode.CodePos:=NewCodePos;
  1936. //DebugLn(['AddIdentifierNode Code=',NewNode.FCodePos.Code<>nil,' P=',NewNode.FCodePos.P]);
  1937. if (CTNode.Desc in [ctnTypeDefinition,ctnGenericType])
  1938. and (CTNode.FirstChild<>nil)
  1939. and (CTNode.FirstChild.Desc in AllClasses+[ctnRecordType,ctnEnumerationType])
  1940. then begin
  1941. // add child nodes
  1942. ChildCTNode:=CTNode.FirstChild;
  1943. while (ChildCTNode<>nil) and (ChildCTNode.StartPos<CTNode.EndPos) do
  1944. begin
  1945. if ChildCTNode.Desc in
  1946. [ctnProcedure,ctnVarDefinition,ctnProperty,ctnEnumIdentifier]
  1947. then begin
  1948. AddChildNode(NewNode,ChildCTNode);
  1949. end;
  1950. if ChildCTNode.Desc=ctnProcedureHead then
  1951. ChildCTNode:=ChildCTNode.NextSkipChilds
  1952. else
  1953. ChildCTNode:=ChildCTNode.Next;
  1954. end;
  1955. end;
  1956. if (NewNode.ChildNodes=nil)
  1957. and (not IdentifierFitsFilter(cblIdentifiers,Identifier)) then begin
  1958. // identifier is not needed -> remove
  1959. // ToDo: remove nodes later
  1960. CurUnit.DeleteNode(NewNode);
  1961. end else begin
  1962. // keep node, set Description
  1963. GetNodeDescription(CTTool,CTNode,Identifier,Description);
  1964. NewNode.Description:=Description;
  1965. inc(ShownIdentifierCount);
  1966. end;
  1967. end;
  1968. var
  1969. CTNode: TCodeTreeNode;
  1970. begin
  1971. if SrcUnit=nil then exit;
  1972. //DebugLn(['AddUnitNodes SrcUnit.Filename="',SrcUnit.Filename,'"']);
  1973. CTTool:=GetCodeTool(SrcUnit);
  1974. if CTTool=nil then exit;
  1975. if CTTool.Tree=nil then exit;
  1976. CTNode:=CTTool.Tree.Root;
  1977. while CTNode<>nil do begin
  1978. //DebugLn(['AddUnitNodes ',CTNode.DescAsString]);
  1979. case CTNode.Desc of
  1980. ctnProcedure:
  1981. if not CTTool.NodeIsMethodBody(CTNode) then
  1982. AddIdentifierNode(CTNode);
  1983. ctnVarDefinition,ctnConstDefinition,ctnTypeDefinition,ctnGenericType:
  1984. if not CTTool.NodeIsForwardDeclaration(CTNode) then
  1985. AddIdentifierNode(CTNode);
  1986. end;
  1987. // go to next node
  1988. case CTNode.Desc of
  1989. ctnProgram,ctnLibrary,ctnPackage,ctnUnit,ctnInterface,
  1990. ctnTypeSection,ctnConstSection,ctnVarSection,ctnResStrSection:
  1991. // go into child nodes
  1992. CTNode:=CTNode.Next;
  1993. ctnImplementation, ctnBeginBlock, ctnAsmBlock: break;
  1994. else
  1995. // skip children and go to next sibling or parent
  1996. CTNode:=CTNode.NextSkipChilds;
  1997. end;
  1998. end;
  1999. end;
  2000. procedure AddUnits(SrcList: TCodeBrowserUnitList;
  2001. var DestParentList: TCodeBrowserUnitList);
  2002. procedure RaiseParentNotUnitList;
  2003. begin
  2004. raise Exception.Create('TCodeBrowserView.UpdateTreeView.AddUnits.RaiseParentNotUnitList');
  2005. end;
  2006. var
  2007. Node: TAVLTreeNode;
  2008. CurUnit: TCodeBrowserUnit;
  2009. NewUnit: TCodeBrowserUnit;
  2010. List: TCodeBrowserUnitList;
  2011. OldDestParentList: TObject;
  2012. begin
  2013. if SrcList=nil then exit;
  2014. //DebugLn(['AddUnits SrcList.Owner="',SrcList.Owner,'" HasUnits=',SrcList.Units<>nil]);
  2015. if SrcList.Units=nil then exit;
  2016. OldDestParentList:=DestParentList;
  2017. NewUnit:=nil;
  2018. Node:=SrcList.Units.FindLowest;
  2019. while Node<>nil do begin
  2020. CurUnit:=TCodeBrowserUnit(Node.Data);
  2021. if (CurUnit.Filename='')
  2022. or IdentifierFitsFilter(cblUnits,ExtractFileNameOnly(CurUnit.Filename))
  2023. then begin
  2024. if DestParentList=nil then begin
  2025. DestParentList:=TCodeBrowserUnitList.Create(CodeBrowserHidden,nil);
  2026. end else if not (DestParentList is TCodeBrowserUnitList) then
  2027. RaiseParentNotUnitList;
  2028. List:=TCodeBrowserUnitList(DestParentList);
  2029. if ShowUnits then begin
  2030. // create a unit node
  2031. NewUnit:=List.AddUnit(CurUnit.Filename);
  2032. NewUnit.CodeBuffer:=CurUnit.CodeBuffer;
  2033. NewUnit.CodeTool:=CurUnit.CodeTool;
  2034. end else if NewUnit=nil then begin
  2035. // create a dummy unit node to add all identifiers
  2036. NewUnit:=List.FindUnit('');
  2037. if NewUnit=nil then
  2038. NewUnit:=List.AddUnit('');
  2039. end;
  2040. //DebugLn(['AddUnits AddUnitNodes ',CurUnit.Filename]);
  2041. AddUnitNodes(CurUnit,TObject(NewUnit));
  2042. if (not ShowEmptyNodes) and (NewUnit.ChildNodeCount=0) then begin
  2043. // remove empty unit
  2044. List.DeleteUnit(NewUnit);
  2045. NewUnit:=nil;
  2046. if OldDestParentList=nil then begin
  2047. FreeAndNil(DestParentList);
  2048. end;
  2049. end;
  2050. if (NewUnit<>nil) and (NewUnit.UnitList=nil) and (List<>nil) then
  2051. List.AddUnit(NewUnit);
  2052. end;
  2053. Node:=SrcList.Units.FindSuccessor(Node);
  2054. end;
  2055. end;
  2056. procedure AddUnitLists(SrcList: TCodeBrowserUnitList;
  2057. var DestParentList: TCodeBrowserUnitList);
  2058. var
  2059. Node: TAVLTreeNode;
  2060. SubList: TCodeBrowserUnitList;
  2061. NewList: TCodeBrowserUnitList;
  2062. OldDestParentList: TCodeBrowserUnitList;
  2063. NewListCreated: Boolean;
  2064. CreateNode: Boolean;
  2065. begin
  2066. if SrcList=nil then exit;
  2067. //DebugLn(['AddUnitLists SrcList.Owner="',SrcList.Owner,'"']);
  2068. OldDestParentList:=DestParentList;
  2069. // check filter
  2070. CreateNode:=IdentifierFitsFilter(cblPackages,SrcList.Owner);
  2071. // create node
  2072. NewListCreated:=false;
  2073. if CreateNode then begin
  2074. if ShowPackages then begin
  2075. if DestParentList=nil then begin
  2076. DestParentList:=TCodeBrowserUnitList.Create(CodeBrowserHidden,nil);
  2077. end;
  2078. NewList:=TCodeBrowserUnitList.Create(SrcList.Owner,DestParentList);
  2079. NewListCreated:=true;
  2080. end else begin
  2081. NewList:=DestParentList;
  2082. end;
  2083. end;
  2084. // create nodes for unitlists
  2085. if SrcList.UnitLists<>nil then begin
  2086. Node:=SrcList.UnitLists.FindLowest;
  2087. while Node<>nil do begin
  2088. SubList:=TCodeBrowserUnitList(Node.Data);
  2089. AddUnitLists(SubList,DestParentList);// DestParentList because: as sibling not as child!
  2090. Node:=SrcList.UnitLists.FindSuccessor(Node);
  2091. end;
  2092. end;
  2093. if CreateNode then begin
  2094. // create nodes for units
  2095. AddUnits(SrcList,NewList);
  2096. // remove empty unit lists
  2097. if (not ShowEmptyNodes) and NewListCreated and (NewList.IsEmpty) then begin
  2098. //DebugLn(['AddUnitLists EMPTY ',NewList.Owner,' ',NewList.UnitListCount,' ',NewList.UnitCount]);
  2099. if DestParentList=NewList then
  2100. DestParentList:=nil;
  2101. NewList.Free;
  2102. NewList:=nil;
  2103. if (OldDestParentList=nil) and (DestParentList<>nil)
  2104. and DestParentList.IsEmpty then begin
  2105. FreeAndNil(DestParentList);
  2106. end;
  2107. end;
  2108. // update DestParentList
  2109. if (DestParentList=nil) then
  2110. DestParentList:=NewList;
  2111. end;
  2112. end;
  2113. procedure AddTreeNodes(CodeNode: TObject; ParentViewNode: TTreeNode);
  2114. var
  2115. TVNode: TTreeNode;
  2116. procedure RecursiveAdd(Tree: TAVLTree);
  2117. var
  2118. Node: TAVLTreeNode;
  2119. begin
  2120. if Tree<>nil then begin
  2121. Node:=Tree.FindLowest;
  2122. while Node<>nil do begin
  2123. AddTreeNodes(TObject(Node.Data), TVNode);
  2124. Node:=Tree.FindSuccessor(Node);
  2125. end;
  2126. end;
  2127. end;
  2128. {off $DEFINE DisableTreeViewNodes}
  2129. procedure AddToTreeView(Name: String);
  2130. begin
  2131. {$IFNDEF DisableTreeViewNodes}
  2132. TVNode:=BrowseTreeView.Items.AddChildObject(
  2133. ParentViewNode, Name, CodeNode);
  2134. TVNode.ImageIndex:=GetNodeImage(CodeNode);
  2135. TVNode.SelectedIndex:=TVNode.ImageIndex;
  2136. {$ENDIF}
  2137. end;
  2138. // create visual nodes (TTreeNode)
  2139. var
  2140. CurList: TCodeBrowserUnitList;
  2141. CurListName: String;
  2142. CurUnit: TCodeBrowserUnit;
  2143. CurUnitName: String;
  2144. CurTool: TStandardCodeTool;
  2145. CurNode: TCodeBrowserNode;
  2146. ExpandParent: Boolean;
  2147. begin
  2148. if CodeNode=nil then exit;
  2149. ExpandParent:=true;
  2150. //DebugLn(['AddTreeNodes ',DbgSName(CodeNode)]);
  2151. TVNode:=ParentViewNode;
  2152. if CodeNode is TCodeBrowserUnitList then begin
  2153. CurList:=TCodeBrowserUnitList(CodeNode);
  2154. //DebugLn(['AddTreeNodes ',CurList.Owner]);
  2155. if CurList.Owner=CodeBrowserHidden then begin
  2156. TVNode:=ParentViewNode;
  2157. end else begin
  2158. CurListName:=ListOwnerToText(CurList.Owner);
  2159. inc(NewPackageCount);
  2160. AddToTreeView(CurListName);
  2161. end;
  2162. RecursiveAdd(CurList.UnitLists);
  2163. RecursiveAdd(CurList.Units);
  2164. end
  2165. else if CodeNode is TCodeBrowserUnit then begin
  2166. CurUnit:=TCodeBrowserUnit(CodeNode);
  2167. CurTool:=nil;
  2168. if CurUnit.Filename<>'' then
  2169. CurTool:=GetCodeTool(CurUnit);
  2170. if CurTool<>nil then begin
  2171. // add a tree node for this unit
  2172. CurUnitName:=TCodeTool(CurTool).GetCachedSourceName;
  2173. if CurUnitName='' then
  2174. CurUnitName:=ExtractFileNameOnly(CurTool.MainFilename);
  2175. inc(NewUnitCount);
  2176. AddToTreeView(CurUnitName);
  2177. end else begin
  2178. // do not add a tree node for this unit
  2179. TVNode:=ParentViewNode;
  2180. end;
  2181. // create tree nodes for code nodes
  2182. RecursiveAdd(CurUnit.ChildNodes);
  2183. end
  2184. else if CodeNode is TCodeBrowserNode then begin
  2185. CurNode:=TCodeBrowserNode(CodeNode);
  2186. if CurNode.Description<>'' then begin
  2187. inc(NewIdentifierCount);
  2188. //if (NewIdentifierCount mod 100)=0 then
  2189. // DebugLn(['AddTreeNodes ',NewIdentifierCount,' ',CurNode.Description]);
  2190. AddToTreeView(CurNode.Description);
  2191. // create tree nodes for child code nodes
  2192. RecursiveAdd(CurNode.ChildNodes);
  2193. // do not expand unit nodes
  2194. if (ParentViewNode<>nil)
  2195. and (TObject(ParentViewNode.Data) is TCodeBrowserUnit) then
  2196. ExpandParent:=false;
  2197. end;
  2198. end;
  2199. if ParentViewNode<>nil then
  2200. ParentViewNode.Expanded:=ExpandParent;
  2201. end;
  2202. var
  2203. lvl: TCodeBrowserLevel;
  2204. i: Integer;
  2205. begin
  2206. UsedMem:=0;
  2207. ShowPackages:=Options.HasLevel(cblPackages);
  2208. ShowUnits:=Options.HasLevel(cblUnits);
  2209. ShowIdentifiers:=Options.HasLevel(cblIdentifiers);
  2210. ShowPrivate:=Options.ShowPrivate;
  2211. ShowProtected:=Options.ShowProtected;
  2212. ShowEmptyNodes:=Options.ShowEmptyNodes;
  2213. NewPackageCount:=0;
  2214. NewUnitCount:=0;
  2215. NewIdentifierCount:=0;
  2216. ShownIdentifierCount:=0;
  2217. for lvl:=Low(TCodeBrowserLevel) to High(TCodeBrowserLevel) do begin
  2218. LevelFilterText[lvl]:=Options.LevelFilterText[lvl];
  2219. LevelFilterType[lvl]:=Options.LevelFilterType[lvl];
  2220. debugln(['TCodeBrowserView.UpdateTreeView lvl=',ord(lvl),' type=',ord(LevelFilterType[lvl]),' filter="',LevelFilterText[lvl],'"']);
  2221. end;
  2222. //DebugLn(['TCodeBrowserView.UpdateTreeView ShowPackages=',ShowPackages,' ShowUnits=',ShowUnits,' ShowIdentifiers=',ShowIdentifiers]);
  2223. BrowseTreeView.Cursor:=crHourGlass;
  2224. BrowseTreeView.BeginUpdate;
  2225. CodeToolBoss.ActivateWriteLock;
  2226. try
  2227. InitTreeView;
  2228. // create internal nodes
  2229. AddUnitLists(ParserRoot,fViewRoot);
  2230. // create treeview nodes
  2231. AddTreeNodes(ViewRoot,nil);
  2232. // if there are only a few items expand the whole tree
  2233. if BrowseTreeView.Items.Count<30 then
  2234. for i:=0 to BrowseTreeView.Items.TopLvlCount-1 do
  2235. BrowseTreeView.Items.TopLvlItems[i].Expand(true);
  2236. finally
  2237. CodeToolBoss.DeactivateWriteLock;
  2238. //DebugLn(['TCodeBrowserView.UpdateTreeView EndUpdate']);
  2239. BrowseTreeView.EndUpdate;
  2240. //DebugLn(['TCodeBrowserView.UpdateTreeView AFER ENDUPDATE']);
  2241. BrowseTreeView.Cursor:=crDefault;
  2242. end;
  2243. VisiblePackages:=NewPackageCount;
  2244. VisibleUnits:=NewUnitCount;
  2245. VisibleIdentifiers:=NewIdentifierCount;
  2246. UpdateStatusBar(false);
  2247. end;
  2248. procedure TCodeBrowserView.RemoveUnit(AnUnit: TCodeBrowserUnit);
  2249. begin
  2250. if AnUnit.Scanned then begin
  2251. dec(FScannedUnits);
  2252. dec(FScannedLines,AnUnit.ScannedLines);
  2253. dec(FScannedBytes,AnUnit.ScannedBytes);
  2254. dec(FScannedIdentifiers,AnUnit.ScannedIdentifiers);
  2255. AnUnit.Scanned:=false;
  2256. if fOutdatedFiles<>nil then
  2257. fOutdatedFiles.Remove(AnUnit);
  2258. end;
  2259. end;
  2260. function TCodeBrowserView.CountIdentifiers(Tool: TCodeTool): integer;
  2261. var
  2262. Node: TCodeTreeNode;
  2263. begin
  2264. Result:=0;
  2265. if (Tool=nil) or (Tool.Tree=nil) then exit;
  2266. Node:=Tool.Tree.Root;
  2267. while Node<>nil do begin
  2268. if Node.Desc=ctnImplementation then break;
  2269. if (Node.Desc in (AllIdentifierDefinitions+[ctnProcedure,ctnProperty]))
  2270. and (not Tool.NodeIsForwardDeclaration(Node)) then
  2271. inc(Result);
  2272. if not (Node.Desc in [ctnProcedure,ctnBeginBlock,ctnAsmBlock]) then
  2273. Node:=Node.Next
  2274. else
  2275. Node:=Node.NextSkipChilds;
  2276. end;
  2277. end;
  2278. procedure TCodeBrowserView.ClearTreeView;
  2279. begin
  2280. BrowseTreeView.Items.Clear;
  2281. FreeAndNil(FViewRoot);
  2282. end;
  2283. procedure TCodeBrowserView.InitTreeView;
  2284. begin
  2285. ClearTreeView;
  2286. end;
  2287. function TCodeBrowserView.ListOwnerToText(const ListOwner: string): string;
  2288. begin
  2289. if ListOwner=CodeBrowserIDEName then
  2290. Result:=IDEDescription
  2291. else if ListOwner=CodeBrowserProjectName then
  2292. Result:=ProjectDescription
  2293. else
  2294. Result:=ListOwner;
  2295. end;
  2296. function TCodeBrowserView.GetNodeImage(CodeNode: TObject): integer;
  2297. var
  2298. List: TCodeBrowserUnitList;
  2299. Node: TCodeBrowserNode;
  2300. begin
  2301. Result:=ImgIDDefault;
  2302. if CodeNode is TCodeBrowserUnit then begin
  2303. Result:=ImgIDUnitCode;
  2304. end else if CodeNode is TCodeBrowserUnitList then begin
  2305. List:=TCodeBrowserUnitList(CodeNode);
  2306. if List.Owner=IDEDescription then
  2307. Result:=ImgIDProject
  2308. else if List.Owner=ProjectDescription then
  2309. Result:=ImgIDProject
  2310. else
  2311. Result:=ImgIDPackage;
  2312. end else if CodeNode is TCodeBrowserNode then begin
  2313. Node:=TCodeBrowserNode(CodeNode);
  2314. case Node.Desc of
  2315. ctnProgram,ctnLibrary,ctnPackage:
  2316. Result:=ImgIDProgramCode;
  2317. ctnUnit:
  2318. Result:=ImgIDUnitCode;
  2319. ctnInterface:
  2320. Result:=ImgIDInterfaceSection;
  2321. ctnImplementation:
  2322. Result:=ImgIDImplementation;
  2323. ctnInitialization:
  2324. Result:=ImgIDInitialization;
  2325. ctnFinalization:
  2326. Result:=ImgIDFinalization;
  2327. ctnTypeSection:
  2328. Result:=ImgIDTypeSection;
  2329. ctnTypeDefinition,ctnGenericType:
  2330. Result:=ImgIDType;
  2331. ctnVarSection:
  2332. Result:=ImgIDVarSection;
  2333. ctnVarDefinition:
  2334. Result:=ImgIDVariable;
  2335. ctnConstSection,ctnResStrSection:
  2336. Result:=ImgIDConstSection;
  2337. ctnConstDefinition:
  2338. Result:=ImgIDConst;
  2339. ctnClass,ctnObject,ctnObjCClass,ctnObjCCategory,ctnObjCProtocol,ctnCPPClass:
  2340. Result:=ImgIDClass;
  2341. ctnProcedure:
  2342. Result:=ImgIDProc;
  2343. ctnProperty:
  2344. Result:=ImgIDProperty;
  2345. end;
  2346. end;
  2347. end;
  2348. function TCodeBrowserView.GetTVNodeHint(TVNode: TTreeNode): string;
  2349. var
  2350. NodeData: TObject;
  2351. CurUnit: TCodeBrowserUnit;
  2352. Node: TCodeBrowserNode;
  2353. Line, Column: integer;
  2354. BaseURL, HTMLHint: String;
  2355. begin
  2356. Result:='';
  2357. if (TVNode=nil) or (TVNode.Data=nil) then exit;
  2358. NodeData:=TObject(TVNode.Data);
  2359. //DebugLn(['TCodeBrowserView.GetTVNodeHint ',DbgSName(NodeData)]);
  2360. if NodeData is TCodeBrowserUnitList then begin
  2361. end else if NodeData is TCodeBrowserUnit then begin
  2362. CurUnit:=TCodeBrowserUnit(NodeData);
  2363. if CurUnit.Filename<>'' then
  2364. Result:=TVNode.Text+LineEnding+CurUnit.Filename;
  2365. end else if NodeData is TCodeBrowserNode then begin
  2366. Node:=TCodeBrowserNode(NodeData);
  2367. if Node.CodePos.Code<>nil then begin
  2368. Result:=TVNode.Text+LineEnding+Node.CodePos.Code.Filename;
  2369. Node.CodePos.Code.AbsoluteToLineCol(Node.CodePos.P,Line,Column);
  2370. if Line>0 then
  2371. Result:=Result+' ('+IntToStr(Line)+','+IntToStr(Column)+')';
  2372. if GetCodeHelp(TVNode, BaseURL, HTMLHint) then
  2373. Result := HTMLHint;
  2374. end;
  2375. end;
  2376. end;
  2377. function TCodeBrowserView.GetCodeHelp(TVNode: TTreeNode; out BaseURL,
  2378. HTMLHint: string): boolean;
  2379. var
  2380. NodeData: TObject;
  2381. Node: TCodeBrowserNode;
  2382. Tool: TCodeTool;
  2383. CleanPos: integer;
  2384. CTNode: TCodeTreeNode;
  2385. NewCodePos: TCodeXYPosition;
  2386. begin
  2387. Result:=false;
  2388. BaseURL:='';
  2389. HTMLHint:='';
  2390. if (TVNode=nil) or (TVNode.Data=nil) then exit;
  2391. NodeData:=TObject(TVNode.Data);
  2392. if NodeData is TCodeBrowserNode then begin
  2393. Node:=TCodeBrowserNode(NodeData);
  2394. if Node.CodePos.Code=nil then exit;
  2395. if not LazarusIDE.BeginCodeTools then // commit source editor changes to codetools
  2396. exit;
  2397. // parse unit
  2398. CodeToolBoss.Explore(Node.CodePos.Code,Tool,false,false);
  2399. if Tool=nil then exit;
  2400. // find source position in parsed code
  2401. if Tool.CodePosToCleanPos(Node.CodePos,CleanPos)<>0 then exit;
  2402. // find node
  2403. CTNode:=Tool.FindDeepestNodeAtPos(CleanPos,false);
  2404. if (CTNode=nil) or (CTNode.Desc<>Node.Desc) then
  2405. exit; // source has changed
  2406. // find cleanpos of identifier
  2407. case CTNode.Desc of
  2408. ctnProcedure:
  2409. begin
  2410. if SysUtils.CompareText(Tool.ExtractProcName(CTNode,ProcIdentifierFlags),
  2411. Node.Identifier)<>0
  2412. then
  2413. exit; // source has changed
  2414. Tool.MoveCursorToProcName(CTNode,true);
  2415. CleanPos:=Tool.CurPos.StartPos;
  2416. end;
  2417. ctnProperty:
  2418. begin
  2419. if SysUtils.CompareText(Tool.ExtractPropName(CTNode,false),Node.Identifier)<>0
  2420. then
  2421. exit; // source has changed
  2422. Tool.MoveCursorToPropName(CTNode);
  2423. CleanPos:=Tool.CurPos.StartPos;
  2424. end;
  2425. ctnGenericType:
  2426. begin
  2427. Tool.ExtractDefinitionName(CTNode);
  2428. if CTNode.FirstChild<>nil then
  2429. CleanPos:=CTNode.FirstChild.StartPos;
  2430. if SysUtils.CompareText(Tool.ExtractIdentifier(CleanPos),Node.Identifier)<>0
  2431. then
  2432. exit; // source has changed
  2433. end;
  2434. ctnVarDefinition,ctnTypeDefinition,ctnConstDefinition,
  2435. ctnEnumIdentifier:
  2436. if SysUtils.CompareText(Tool.ExtractIdentifier(CleanPos),Node.Identifier)<>0
  2437. then
  2438. exit; // source has changed
  2439. else
  2440. exit;
  2441. end;
  2442. // get source position
  2443. if not Tool.CleanPosToCaret(CleanPos,NewCodePos) then exit;
  2444. // ask the help system about the identifier
  2445. if LazarusHelp.GetHintForSourcePosition(NewCodePos.Code.Filename,
  2446. Point(NewCodePos.X,NewCodePos.Y),BaseURL,HTMLHint)<>shrSuccess then exit;
  2447. if HTMLHint <> '' then
  2448. Result:=true;
  2449. end;
  2450. end;
  2451. procedure TCodeBrowserView.ExpandCollapseAllNodesInTreeView(
  2452. NodeType: TExpandableNodeType; Expand: boolean);
  2453. var
  2454. Node: TTreeNode;
  2455. begin
  2456. BrowseTreeView.BeginUpdate;
  2457. Node:=BrowseTreeView.Items.GetFirstNode;
  2458. while Node<>nil do begin
  2459. if (Node.Data<>nil) then begin
  2460. case NodeType of
  2461. entPackage:
  2462. if TObject(Node.Data) is TCodeBrowserUnitList then
  2463. Node.Expanded:=Expand;
  2464. entUnit:
  2465. if TObject(Node.Data) is TCodeBrowserUnit then
  2466. Node.Expanded:=Expand;
  2467. entClass:
  2468. if (TObject(Node.Data) is TCodeBrowserNode) then
  2469. Node.Expanded:=Expand;
  2470. end;
  2471. end;
  2472. Node:=Node.GetNext;
  2473. end;
  2474. BrowseTreeView.EndUpdate;
  2475. end;
  2476. procedure TCodeBrowserView.CopyNode(TVNode: TTreeNode; NodeType: TCopyNodeType);
  2477. var
  2478. Node: TCodeBrowserNode;
  2479. s: string;
  2480. begin
  2481. if (TVNode=nil) or (TVNode.Data=nil) then exit;
  2482. s:='';
  2483. if TObject(TVNode.Data) is TCodeBrowserUnitList then begin
  2484. s:=TVNode.Text;
  2485. end;
  2486. if TObject(TVNode.Data) is TCodeBrowserUnit then begin
  2487. s:=TVNode.Text;
  2488. end;
  2489. if (TObject(TVNode.Data) is TCodeBrowserNode) then begin
  2490. Node:=TCodeBrowserNode(TVNode.Data);
  2491. if NodeType=cntIdentifier then
  2492. s:=Node.Identifier
  2493. else
  2494. s:=Node.Description;
  2495. end;
  2496. Clipboard.AsText:=s;
  2497. end;
  2498. procedure TCodeBrowserView.InvalidateStage(AStage: TCodeBrowserWorkStage);
  2499. begin
  2500. if ord(fStage)<=ord(AStage) then exit;
  2501. fStage:=AStage;
  2502. IdleConnected:=true;
  2503. end;
  2504. function TCodeBrowserView.GetSelectedUnit: TCodeBrowserUnit;
  2505. var
  2506. TVNode: TTreeNode;
  2507. Node: TObject;
  2508. begin
  2509. Result:=nil;
  2510. TVNode:=BrowseTreeView.Selected;
  2511. if TVNode=nil then exit;
  2512. Node:=TObject(TVNode.Data);
  2513. if Node=nil then exit;
  2514. if not (Node is TCodeBrowserUnit) then exit;
  2515. Result:=TCodeBrowserUnit(Node);
  2516. end;
  2517. function TCodeBrowserView.GetSelectedPackage: TLazPackage;
  2518. var
  2519. TVNode: TTreeNode;
  2520. Node: TObject;
  2521. UnitList: TCodeBrowserUnitList;
  2522. begin
  2523. Result:=nil;
  2524. TVNode:=BrowseTreeView.Selected;
  2525. if TVNode=nil then exit;
  2526. Node:=TObject(TVNode.Data);
  2527. if Node=nil then exit;
  2528. if not (Node is TCodeBrowserUnitList) then exit;
  2529. UnitList:=TCodeBrowserUnitList(Node);
  2530. Result:=PackageGraph.FindPackageWithName(UnitList.Owner,nil);
  2531. end;
  2532. function TCodeBrowserView.GetCurUnitInSrcEditor(out FileOwner: TObject; out
  2533. UnitCode: TCodeBuffer): boolean;
  2534. var
  2535. SrcEdit: TSourceEditorInterface;
  2536. Code: TCodeBuffer;
  2537. Owners: TFPList;
  2538. begin
  2539. FileOwner:=nil;
  2540. UnitCode:=nil;
  2541. Result:=false;
  2542. SrcEdit:=SourceEditorManagerIntf.ActiveEditor;
  2543. if SrcEdit=nil then exit;
  2544. Code:=CodeToolBoss.GetMainCode(TCodeBuffer(SrcEdit.CodeToolsBuffer));
  2545. if Code=nil then exit;
  2546. Owners:=PkgBoss.GetOwnersOfUnit(Code.FileName);
  2547. try
  2548. if (Owners=nil) or (Owners.Count=0) then exit;
  2549. FileOwner:=TObject(Owners[0]);
  2550. UnitCode:=Code;
  2551. Result:=true;
  2552. finally
  2553. Owners.Free;
  2554. end;
  2555. end;
  2556. function TCodeBrowserView.GetCurPackageInSrcEditor: TLazPackage;
  2557. var
  2558. SrcEdit: TSourceEditorInterface;
  2559. Owners: TFPList;
  2560. i: Integer;
  2561. begin
  2562. Result:=nil;
  2563. SrcEdit:=SourceEditorManagerIntf.ActiveEditor;
  2564. if SrcEdit=nil then exit;
  2565. Owners:=PkgBoss.GetOwnersOfUnit(SrcEdit.FileName);
  2566. try
  2567. if (Owners=nil) then exit;
  2568. for i:=0 to Owners.Count-1 do begin
  2569. if TObject(Owners[i]) is TLazPackage then begin
  2570. Result:=TLazPackage(Owners[i]);
  2571. exit;
  2572. end;
  2573. end;
  2574. finally
  2575. Owners.Free;
  2576. end;
  2577. end;
  2578. procedure TCodeBrowserView.OpenTVNode(TVNode: TTreeNode);
  2579. var
  2580. NodeData: TObject;
  2581. List: TCodeBrowserUnitList;
  2582. APackage: TLazPackage;
  2583. CurUnit: TCodeBrowserUnit;
  2584. Node: TCodeBrowserNode;
  2585. Line,Column: integer;
  2586. begin
  2587. if (TVNode=nil) or (TVNode.Data=nil) then exit;
  2588. NodeData:=TObject(TVNode.Data);
  2589. if NodeData is TCodeBrowserUnitList then begin
  2590. List:=TCodeBrowserUnitList(NodeData);
  2591. DebugLn(['TCodeBrowserView.OpenSelected "',List.Owner,'=',CodeBrowserProjectName,'"']);
  2592. if List.Owner=CodeBrowserProjectName then begin
  2593. // open project inspector
  2594. DebugLn(['TCodeBrowserView.OpenSelected open project inspector']);
  2595. ExecuteIDECommand(Self,ecProjectInspector);
  2596. end else if List.Owner=CodeBrowserIDEName then begin
  2597. // open the IDE -> already open
  2598. end else if List.Owner=CodeBrowserHidden then begin
  2599. // nothing
  2600. end else begin
  2601. // open package
  2602. APackage:=PackageGraph.FindPackageWithName(List.Owner,nil);
  2603. if APackage<>nil then begin
  2604. PackageEditingInterface.DoOpenPackageWithName(List.Owner,[],false);
  2605. end;
  2606. end;
  2607. end else if NodeData is TCodeBrowserUnit then begin
  2608. CurUnit:=TCodeBrowserUnit(NodeData);
  2609. if CurUnit.Filename<>'' then begin
  2610. LazarusIDE.DoOpenEditorFile(CurUnit.Filename,-1,-1,[ofOnlyIfExists]);
  2611. end;
  2612. end else if NodeData is TCodeBrowserNode then begin
  2613. Node:=TCodeBrowserNode(NodeData);
  2614. if (Node.CodePos.Code<>nil)
  2615. and (Node.CodePos.Code.Filename<>'') then begin
  2616. Node.CodePos.Code.AbsoluteToLineCol(Node.CodePos.P,Line,Column);
  2617. LazarusIDE.DoOpenFileAndJumpToPos(Node.CodePos.Code.Filename,
  2618. Point(Column,Line),-1,-1,-1,[ofOnlyIfExists]);
  2619. end;
  2620. end;
  2621. end;
  2622. procedure TCodeBrowserView.BeginUpdate;
  2623. begin
  2624. inc(fUpdateCount);
  2625. BrowseTreeView.BeginUpdate;
  2626. end;
  2627. procedure TCodeBrowserView.EndUpdate;
  2628. begin
  2629. dec(fUpdateCount);
  2630. BrowseTreeView.EndUpdate;
  2631. end;
  2632. function TCodeBrowserView.ExportTree: TModalResult;
  2633. var
  2634. SaveDialog: TSaveDialog;
  2635. begin
  2636. SaveDialog:=TSaveDialog.Create(nil);
  2637. try
  2638. InitIDEFileDialog(SaveDialog);
  2639. SaveDialog.Title:='Save tree as text (*.txt) ...';
  2640. SaveDialog.FileName:='identifiers.txt';
  2641. SaveDialog.DefaultExt:='txt';
  2642. if not SaveDialog.Execute then exit(mrCancel);
  2643. Result:=ExportTreeAsText(SaveDialog.FileName);
  2644. finally
  2645. StoreIDEFileDialog(SaveDialog);
  2646. SaveDialog.Free;
  2647. end;
  2648. end;
  2649. function TCodeBrowserView.ExportTreeAsText(Filename: string): TModalResult;
  2650. procedure WriteNode(var List: TStrings; Node: TTreeNode; Prefix: String='');
  2651. const
  2652. CodeBrowserTypes: array[1..3] of TClass =
  2653. (TCodeBrowserUnitList, TCodeBrowserUnit, TCodeBrowserNode);
  2654. NodeIndent = ' ';
  2655. var
  2656. Child: TTreeNode;
  2657. i: Integer;
  2658. begin
  2659. if Node=nil then exit;
  2660. for i:=Low(CodeBrowserTypes) to High(CodeBrowserTypes) do begin
  2661. if TObject(Node.Data) is CodeBrowserTypes[i] then begin
  2662. List.Add(prefix+Node.Text);
  2663. Prefix:=Prefix+NodeIndent;
  2664. break;
  2665. end;
  2666. end;
  2667. Child:=Node.GetFirstChild;
  2668. while Child<>nil do begin
  2669. WriteNode(List,Child,Prefix);
  2670. Child:=Child.GetNextSibling;
  2671. end;
  2672. end;
  2673. var
  2674. List: TStrings;
  2675. begin
  2676. Filename:=TrimAndExpandFilename(Filename);
  2677. if Filename='' then exit(mrCancel);
  2678. Result:=CheckCreatingFile(Filename,true,true,true);
  2679. if Result<>mrOk then exit;
  2680. List:=TStringList.Create;
  2681. try
  2682. WriteNode(List,BrowseTreeView.Items.GetFirstNode);
  2683. Result:=SaveStringToFile(Filename,List.Text,[],
  2684. 'exporting identifiers as text');
  2685. finally
  2686. List.Free;
  2687. end;
  2688. end;
  2689. function TCodeBrowserView.GetScopeToCurUnitOwner(UseFCLAsDefault: boolean): string;
  2690. var
  2691. SrcEdit: TSourceEditorInterface;
  2692. Code: TCodeBuffer;
  2693. MainCode: TCodeBuffer;
  2694. Owners: TFPList;
  2695. begin
  2696. Result:='';
  2697. if UseFCLAsDefault then
  2698. Result:=PackageGraph.FCLPackage.Name;
  2699. SrcEdit:=SourceEditorManagerIntf.ActiveEditor;
  2700. if SrcEdit=nil then exit;
  2701. Code:=TCodeBuffer(SrcEdit.CodeToolsBuffer);
  2702. if Code=nil then exit;
  2703. MainCode:=CodeToolBoss.GetMainCode(Code);
  2704. if MainCode<>nil then
  2705. Code:=MainCode;
  2706. Owners:=PkgBoss.GetPossibleOwnersOfUnit(Code.FileName,[]);
  2707. try
  2708. if (Owners=nil) or (Owners.Count=0) then exit;
  2709. if TObject(Owners[0])=Project1 then begin
  2710. Result:=ProjectDescription;
  2711. exit;
  2712. end;
  2713. if TObject(Owners[0]) is TLazPackage then begin
  2714. Result:=TLazPackage(Owners[0]).Name;
  2715. exit;
  2716. end;
  2717. finally
  2718. Owners.Free;
  2719. end;
  2720. end;
  2721. function TCodeBrowserView.SetScopeToCurUnitOwner(UseFCLAsDefault,
  2722. WithRequiredPackages: boolean): boolean;
  2723. var
  2724. NewScope: String;
  2725. begin
  2726. Result:=false;
  2727. NewScope:=GetScopeToCurUnitOwner(UseFCLAsDefault);
  2728. if NewScope='' then exit;
  2729. ScopeComboBox.Text:=NewScope;
  2730. ScopeWithRequiredPackagesCheckBox.Checked:=WithRequiredPackages;
  2731. InvalidateStage(cbwsGetScopeOptions);
  2732. end;
  2733. procedure TCodeBrowserView.SetFilterToSimpleIdentifier(Identifier: string);
  2734. begin
  2735. ShowPackagesCheckBox.Checked:=true;
  2736. PackageFilterEdit.Text:='';
  2737. PackageFilterContainsSpeedButton.Down:=true;
  2738. ShowUnitsCheckBox.Checked:=true;
  2739. UnitFilterEdit.Text:='';
  2740. UnitFilterContainsSpeedButton.Down:=true;
  2741. ShowIdentifiersCheckBox.Checked:=true;
  2742. IdentifierFilterEdit.Text:=Identifier;
  2743. IdentifierFilterBeginsSpeedButton.Down:=true;
  2744. ShowEmptyNodesCheckBox.Checked:=false;
  2745. InvalidateStage(cbwsGetViewOptions);
  2746. end;
  2747. procedure TCodeBrowserView.BrowseTreeViewShowHint(Sender: TObject; HintInfo: PHintInfo);
  2748. var
  2749. TVNode: TTreeNode;
  2750. HintStr: String;
  2751. begin
  2752. //DebugLn(['TCodeBrowserView.BrowseTreeViewShowHint ',dbgs(HintInfo^.CursorPos)]);
  2753. HintStr:='';
  2754. TVNode:=BrowseTreeView.GetNodeAt(HintInfo^.CursorPos.X, HintInfo^.CursorPos.Y);
  2755. if TVNode<>nil then
  2756. HintStr:=GetTVNodeHint(TVNode);
  2757. HintInfo^.HintStr:=''; // do not use the normal mechanism,
  2758. // ... open a THintWindow with LazarusHelp instead
  2759. if csDestroying in ComponentState then exit;
  2760. FHintManager.ShowHint(HintInfo^.HintPos, HintStr);
  2761. end;
  2762. procedure TCodeBrowserView.CloseHintWindow;
  2763. begin
  2764. FHintManager.HideHint;
  2765. end;
  2766. procedure TCodeBrowserView.CollapseAllPackagesMenuItemClick(Sender: TObject);
  2767. begin
  2768. ExpandCollapseAllNodesInTreeView(entPackage,false);
  2769. end;
  2770. procedure TCodeBrowserView.CollapseAllUnitsMenuItemClick(Sender: TObject);
  2771. begin
  2772. ExpandCollapseAllNodesInTreeView(entUnit,false);
  2773. end;
  2774. procedure TCodeBrowserView.CollapseAllClassesMenuItemClick(Sender: TObject);
  2775. begin
  2776. ExpandCollapseAllNodesInTreeView(entClass,false);
  2777. end;
  2778. procedure TCodeBrowserView.CopyDescriptionMenuItemClick(Sender: TObject);
  2779. begin
  2780. CopyNode(BrowseTreeView.Selected,cntDescription);
  2781. end;
  2782. procedure TCodeBrowserView.CopyIdentifierMenuItemClick(Sender: TObject);
  2783. begin
  2784. CopyNode(BrowseTreeView.Selected,cntIdentifier);
  2785. end;
  2786. procedure TCodeBrowserView.ExpandAllClassesMenuItemClick(Sender: TObject);
  2787. begin
  2788. ExpandCollapseAllNodesInTreeView(entClass,true);
  2789. end;
  2790. procedure TCodeBrowserView.ExpandAllPackagesMenuItemClick(Sender: TObject);
  2791. begin
  2792. ExpandCollapseAllNodesInTreeView(entPackage,true);
  2793. end;
  2794. procedure TCodeBrowserView.ExpandAllUnitsMenuItemClick(Sender: TObject);
  2795. begin
  2796. ExpandCollapseAllNodesInTreeView(entUnit,true);
  2797. end;
  2798. procedure TCodeBrowserView.ExportMenuItemClick(Sender: TObject);
  2799. begin
  2800. ExportTree;
  2801. end;
  2802. procedure TCodeBrowserView.BrowseTreeViewMouseDown(Sender: TOBject;
  2803. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2804. begin
  2805. if ssDouble in Shift then
  2806. OpenTVNode(BrowseTreeView.GetNodeAt(X,Y));
  2807. end;
  2808. procedure TCodeBrowserView.UsePkgInProjectMenuItemClick(Sender: TObject);
  2809. var
  2810. APackage: TLazPackage;
  2811. begin
  2812. APackage:=GetSelectedPackage;
  2813. if APackage=nil then exit;
  2814. PkgBoss.AddProjectDependency(Project1,APackage);
  2815. end;
  2816. procedure TCodeBrowserView.UseUnitInCurUnitMenuItemClick(Sender: TObject);
  2817. begin
  2818. UseUnitInSrcEditor(false);
  2819. end;
  2820. procedure TCodeBrowserView.UsePkgInCurUnitMenuItemClick(Sender: TObject);
  2821. var
  2822. APackage: TLazPackage;
  2823. TargetPackage: TLazPackage;
  2824. List: TFPList;
  2825. begin
  2826. APackage:=GetSelectedPackage;
  2827. if APackage=nil then exit;
  2828. TargetPackage:=GetCurPackageInSrcEditor;
  2829. if TargetPackage=nil then exit;
  2830. List:=TFPList.Create;
  2831. try
  2832. List.Add(TargetPackage);
  2833. if PkgBoss.AddDependencyToOwners(List,APackage)=mrOk then begin
  2834. PackageEditingInterface.DoOpenPackageWithName(TargetPackage.Name,[],false);
  2835. end;
  2836. finally
  2837. List.Free;
  2838. end;
  2839. end;
  2840. procedure TCodeBrowserView.UseIdentifierInCurUnitMenuItemClick(Sender: TObject);
  2841. begin
  2842. UseUnitInSrcEditor(true);
  2843. end;
  2844. procedure TCodeBrowserView.BrowseTreeViewMouseMove(Sender: TObject;
  2845. Shift: TShiftState; X, Y: Integer);
  2846. begin
  2847. CloseHintWindow;
  2848. end;
  2849. procedure TCodeBrowserView.FormDeactivate(Sender: TObject);
  2850. begin
  2851. CloseHintWindow;
  2852. end;
  2853. { TCodeBrowserViewOptions }
  2854. procedure TCodeBrowserViewOptions.SetModified(const AValue: boolean);
  2855. begin
  2856. if AValue then
  2857. IncreaseChangeStamp;
  2858. if FModified=AValue then exit;
  2859. FModified:=AValue;
  2860. end;
  2861. function TCodeBrowserViewOptions.GetLevelFilterText(Level: TCodeBrowserLevel
  2862. ): string;
  2863. begin
  2864. Result:=FLevelFilterText[Level];
  2865. end;
  2866. function TCodeBrowserViewOptions.GetLevelFilterType(Level: TCodeBrowserLevel
  2867. ): TCodeBrowserTextFilter;
  2868. begin
  2869. Result:=FLevelFilterType[Level];
  2870. end;
  2871. procedure TCodeBrowserViewOptions.SetLevelFilterText(Level: TCodeBrowserLevel;
  2872. const AValue: string);
  2873. begin
  2874. if FLevelFilterText[Level]=AValue then exit;
  2875. FLevelFilterText[Level]:=AValue;
  2876. Modified:=true;
  2877. end;
  2878. procedure TCodeBrowserViewOptions.SetLevelFilterType(Level: TCodeBrowserLevel;
  2879. const AValue: TCodeBrowserTextFilter);
  2880. begin
  2881. if FLevelFilterType[Level]=AValue then exit;
  2882. FLevelFilterType[Level]:=AValue;
  2883. Modified:=true;
  2884. end;
  2885. procedure TCodeBrowserViewOptions.SetScope(const AValue: string);
  2886. begin
  2887. if FScope=AValue then exit;
  2888. FScope:=AValue;
  2889. Modified:=true;
  2890. end;
  2891. procedure TCodeBrowserViewOptions.SetLevels(const AValue: TStrings);
  2892. begin
  2893. if FLevels=AValue then exit;
  2894. if FLevels.Text=AValue.Text then exit;
  2895. FLevels.Assign(AValue);
  2896. Modified:=true;
  2897. end;
  2898. procedure TCodeBrowserViewOptions.SetShowEmptyNodes(const AValue: boolean);
  2899. begin
  2900. if FShowEmptyNodes=AValue then exit;
  2901. FShowEmptyNodes:=AValue;
  2902. Modified:=true;
  2903. end;
  2904. procedure TCodeBrowserViewOptions.SetShowPrivate(const AValue: boolean);
  2905. begin
  2906. if FShowPrivate=AValue then exit;
  2907. FShowPrivate:=AValue;
  2908. Modified:=true;
  2909. end;
  2910. procedure TCodeBrowserViewOptions.SetShowProtected(const AValue: boolean);
  2911. begin
  2912. if FShowProtected=AValue then exit;
  2913. FShowProtected:=AValue;
  2914. Modified:=true;
  2915. end;
  2916. procedure TCodeBrowserViewOptions.SetStoreWithRequiredPackages(
  2917. const AValue: boolean);
  2918. begin
  2919. if FStoreWithRequiredPackages=AValue then exit;
  2920. FStoreWithRequiredPackages:=AValue;
  2921. end;
  2922. procedure TCodeBrowserViewOptions.SetWithRequiredPackages(const AValue: boolean);
  2923. begin
  2924. if FWithRequiredPackages=AValue then exit;
  2925. FWithRequiredPackages:=AValue;
  2926. Modified:=true;
  2927. end;
  2928. procedure TCodeBrowserViewOptions.IncreaseChangeStamp;
  2929. begin
  2930. CTIncreaseChangeStamp(FChangeStamp);
  2931. end;
  2932. constructor TCodeBrowserViewOptions.Create;
  2933. begin
  2934. FLevels:=TStringList.Create;
  2935. FChangeStamp:=CTInvalidChangeStamp;
  2936. Clear;
  2937. end;
  2938. destructor TCodeBrowserViewOptions.Destroy;
  2939. begin
  2940. FreeAndNil(FLevels);
  2941. inherited Destroy;
  2942. end;
  2943. procedure TCodeBrowserViewOptions.Clear;
  2944. var
  2945. l: TCodeBrowserLevel;
  2946. begin
  2947. FLevels.Clear;
  2948. FLevels.Text:=CodeBrowserLevelNames[cblPackages]+#13
  2949. +CodeBrowserLevelNames[cblUnits]+#13
  2950. +CodeBrowserLevelNames[cblIdentifiers];
  2951. WithRequiredPackages:=false;
  2952. ShowPrivate:=false;
  2953. ShowProtected:=true;
  2954. Scope:='Project';
  2955. for l:=Low(TCodeBrowserLevel) to High(TCodeBrowserLevel) do begin
  2956. FLevelFilterType[l]:=cbtfContains;
  2957. FLevelFilterText[l]:='';
  2958. end;
  2959. IncreaseChangeStamp;
  2960. Modified:=false;
  2961. end;
  2962. procedure TCodeBrowserViewOptions.LoadFromConfig(ConfigStore: TConfigStorage;
  2963. const Path: string);
  2964. var
  2965. l: TCodeBrowserLevel;
  2966. SubPath: String;
  2967. begin
  2968. Clear;
  2969. WithRequiredPackages:=ConfigStore.GetValue(Path+'WithRequiredPackages/Value',false);
  2970. Scope:=ConfigStore.GetValue(Path+'Scope/Value','Project');
  2971. ShowPrivate:=ConfigStore.GetValue(Path+'ShowPrivate/Value',false);
  2972. ShowProtected:=ConfigStore.GetValue(Path+'ShowProtected/Value',true);
  2973. ShowEmptyNodes:=ConfigStore.GetValue(Path+'ShowEmptyNodes/Value',true);
  2974. ConfigStore.GetValue(Path+'Levels/',FLevels);
  2975. for l:=Low(TCodeBrowserLevel) to High(TCodeBrowserLevel) do begin
  2976. SubPath:=Path+'LevelFilter/'+CodeBrowserLevelNames[l];
  2977. FLevelFilterType[l]:=StringToCodeBrowserTextFilter(
  2978. ConfigStore.GetValue(SubPath+'/Type',''));
  2979. FLevelFilterText[l]:=ConfigStore.GetValue(SubPath+'/Text','');
  2980. end;
  2981. Modified:=false;
  2982. end;
  2983. procedure TCodeBrowserViewOptions.SaveToConfig(ConfigStore: TConfigStorage;
  2984. const Path: string);
  2985. var
  2986. l: TCodeBrowserLevel;
  2987. SubPath: String;
  2988. b: Boolean;
  2989. begin
  2990. b:=WithRequiredPackages;
  2991. if not StoreWithRequiredPackages then
  2992. b:=false;
  2993. ConfigStore.SetDeleteValue(Path+'WithRequiredPackages/Value',b,false);
  2994. ConfigStore.SetDeleteValue(Path+'Scope/Value',Scope,'Project');
  2995. ConfigStore.SetDeleteValue(Path+'ShowPrivate/Value',ShowPrivate,false);
  2996. ConfigStore.SetDeleteValue(Path+'ShowProtected/Value',ShowProtected,true);
  2997. ConfigStore.SetDeleteValue(Path+'ShowEmptyNodes/Value',ShowEmptyNodes,true);
  2998. ConfigStore.SetValue(Path+'Levels/',FLevels);
  2999. for l:=Low(TCodeBrowserLevel) to High(TCodeBrowserLevel) do begin
  3000. SubPath:=Path+'LevelFilter/'+CodeBrowserLevelNames[l];
  3001. ConfigStore.SetDeleteValue(SubPath+'/Type',
  3002. CodeBrowserTextFilterNames[FLevelFilterType[l]],
  3003. CodeBrowserTextFilterNames[cbtfBegins]);
  3004. ConfigStore.SetDeleteValue(SubPath+'/Text',FLevelFilterText[l],'');
  3005. end;
  3006. Modified:=false;
  3007. end;
  3008. function TCodeBrowserViewOptions.HasLevel(Level: TCodeBrowserLevel): boolean;
  3009. begin
  3010. Result:=Levels.IndexOf(CodeBrowserLevelNames[Level])>=0;
  3011. end;
  3012. { TQuickFixIdentifierNotFound_Search }
  3013. function TQuickFixIdentifierNotFound_Search.IsApplicable(Msg: TMessageLine; out
  3014. Identifier: string): boolean;
  3015. var
  3016. Dummy: string;
  3017. begin
  3018. Result:=false;
  3019. Identifier:='';
  3020. if not Msg.HasSourcePosition then exit;
  3021. Result:=TIDEFPCParser.MsgLineIsId(Msg,5000,Identifier,Dummy);
  3022. end;
  3023. procedure TQuickFixIdentifierNotFound_Search.CreateMenuItems(
  3024. Fixes: TMsgQuickFixes);
  3025. var
  3026. Msg: TMessageLine;
  3027. Identifier: string;
  3028. i: Integer;
  3029. begin
  3030. for i:=0 to Fixes.LineCount-1 do begin
  3031. Msg:=Fixes.Lines[i];
  3032. if not IsApplicable(Msg,Identifier) then continue;
  3033. Fixes.AddMenuItem(Self,Msg,lisQuickFixSearchIdentifier);
  3034. exit;
  3035. end;
  3036. end;
  3037. procedure TQuickFixIdentifierNotFound_Search.QuickFix(Fixes: TMsgQuickFixes;
  3038. Msg: TMessageLine);
  3039. var
  3040. Identifier: String;
  3041. KnownFilename: String;
  3042. Caret: TPoint;
  3043. Filename: String;
  3044. begin
  3045. if not IsApplicable(Msg,Identifier) then exit;
  3046. if not LazarusIDE.BeginCodeTools then begin
  3047. DebugLn(['TQuickFixIdentifierNotFound_Search.Execute failed because IDE busy']);
  3048. exit;
  3049. end;
  3050. // get identifier
  3051. if (Identifier='') or (not IsValidIdent(Identifier)) then begin
  3052. DebugLn(['TQuickFixIdentifierNotFound_Search.Execute not an identifier "',dbgstr(Identifier),'"']);
  3053. exit;
  3054. end;
  3055. Filename:=Msg.GetFullFilename;
  3056. KnownFilename:= LazarusIDE.FindSourceFile(Filename, Project1.ProjectDirectory,
  3057. [fsfSearchForProject, fsfUseIncludePaths, fsfMapTempToVirtualFiles]);
  3058. Caret:=Point(Msg.Line,Msg.Column);
  3059. if (KnownFilename <> '') and (KnownFilename <> Filename) then begin
  3060. if LazarusIDE.DoOpenFileAndJumpToPos(KnownFilename,Caret,-1,-1,-1,OpnFlagsPlainFile)<>mrOk
  3061. then
  3062. if LazarusIDE.DoOpenFileAndJumpToPos(Filename,Caret,-1,-1,-1,OpnFlagsPlainFile)<>mrOk
  3063. then exit;
  3064. end
  3065. else
  3066. if LazarusIDE.DoOpenFileAndJumpToPos(Filename,Caret,-1,-1,-1,OpnFlagsPlainFile
  3067. )<>mrOk
  3068. then exit;
  3069. // start code browser
  3070. ShowCodeBrowser(Identifier);
  3071. end;
  3072. end.