mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-08 22:58:50 +02:00
codetools: added a cache for FindDeclarationAndOverload calls, IDE: combined macro time stamps of values and graph
git-svn-id: trunk@12937 -
This commit is contained in:
parent
17b318bf8c
commit
7a243a0dbd
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -59,6 +59,7 @@ components/chmhelp/packages/idehelp/chmhelppkg.pas svneol=native#text/plain
|
||||
components/chmhelp/packages/idehelp/lazchmhelp.pas svneol=native#text/plain
|
||||
components/codetools/allcodetoolunits.pp svneol=native#text/pascal
|
||||
components/codetools/basiccodetools.pas svneol=native#text/pascal
|
||||
components/codetools/cachecodetools.pas svneol=native#text/plain
|
||||
components/codetools/codeatom.pas svneol=native#text/pascal
|
||||
components/codetools/codebeautifier.pas svneol=native#text/plain
|
||||
components/codetools/codecache.pas svneol=native#text/pascal
|
||||
|
@ -23,11 +23,10 @@ uses
|
||||
CodeTree, CodeAtom, SourceChanger, CodeToolMemManager, CodeCache,
|
||||
KeywordFuncLists, SourceLog, ExprEval, DefineTemplates, FileProcs,
|
||||
CodeToolsStrConsts, DirectoryCacher,
|
||||
MultiKeyWordListTool, ResourceCodeTool, CodeToolsStructs,
|
||||
MultiKeyWordListTool, ResourceCodeTool, CodeToolsStructs, CacheCodeTools,
|
||||
// fast xml units, changes not merged in current fpc
|
||||
Laz_DOM, Laz_XMLCfg, Laz_XMLRead, Laz_XMLWrite, Laz_XMLStreaming;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
|
240
components/codetools/cachecodetools.pas
Normal file
240
components/codetools/cachecodetools.pas
Normal file
@ -0,0 +1,240 @@
|
||||
{
|
||||
***************************************************************************
|
||||
* *
|
||||
* This source is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This code is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* General Public License for more details. *
|
||||
* *
|
||||
* A copy of the GNU General Public License is available on the World *
|
||||
* Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
|
||||
* obtain it by writing to the Free Software Foundation, *
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
Author: Mattias Gaertner
|
||||
|
||||
Abstract:
|
||||
High level caches.
|
||||
}
|
||||
unit CacheCodeTools;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils,
|
||||
CodeAtom, CodeCache, KeywordFuncLists, CustomCodeTool, FindDeclarationTool, AVL_Tree;
|
||||
|
||||
type
|
||||
|
||||
{ TDeclarationInheritanceCacheItem }
|
||||
|
||||
TDeclarationInheritanceCacheItem = class
|
||||
public
|
||||
CodePos: TCodePosition;
|
||||
ListOfPCodeXYPosition: TFPList;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
{ TDeclarationInheritanceCacheTree
|
||||
Tree of TDeclarationInheritanceCacheItem sorted by CompareDeclInhCacheItems }
|
||||
|
||||
TDeclarationInheritanceCacheTree = class(TAVLTree)
|
||||
public
|
||||
CodeToolsChangeStep: integer;
|
||||
constructor CreateDeclInhTree;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
TOnFindDeclarations = function(Code: TCodeBuffer; X,Y: integer;
|
||||
var ListOfPCodeXYPosition: TFPList;
|
||||
Flags: TFindDeclarationListFlags): boolean of object;
|
||||
|
||||
TDeclarationInheritanceCache = class
|
||||
private
|
||||
FCurrent: TDeclarationInheritanceCacheTree;
|
||||
FOldTrees: TFPList; // list of TDeclarationInheritanceCacheTree
|
||||
FOnFindDeclarations: TOnFindDeclarations;
|
||||
procedure CheckCurrentIsValid;
|
||||
procedure CleanCache(FreeItemCount: integer);
|
||||
public
|
||||
constructor Create(const TheOnFindDeclarations: TOnFindDeclarations);
|
||||
destructor Destroy; override;
|
||||
procedure Clear;
|
||||
function FindDeclarations(Code: TCodeBuffer; X,Y: integer;
|
||||
out ListOfPCodeXYPosition: TFPList;
|
||||
out CacheWasUsed: boolean): boolean;
|
||||
property OnFindDeclarations: TOnFindDeclarations read FOnFindDeclarations
|
||||
write FOnFindDeclarations;
|
||||
end;
|
||||
|
||||
function CompareDeclInhCacheItems(Data1, Data2: Pointer): integer;
|
||||
function ComparePCodePosWithDeclInhCacheItem(CodePosition, DeclInhItem: Pointer): integer;
|
||||
|
||||
implementation
|
||||
|
||||
function CompareDeclInhCacheItems(Data1, Data2: Pointer): integer;
|
||||
var
|
||||
Item1: TDeclarationInheritanceCacheItem;
|
||||
Item2: TDeclarationInheritanceCacheItem;
|
||||
begin
|
||||
Item1:=TDeclarationInheritanceCacheItem(Data1);
|
||||
Item2:=TDeclarationInheritanceCacheItem(Data2);
|
||||
Result:=CompareCodePositions(@Item1.CodePos,@Item2.CodePos);
|
||||
end;
|
||||
|
||||
function ComparePCodePosWithDeclInhCacheItem(CodePosition, DeclInhItem: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareCodePositions(PCodePosition(CodePosition),
|
||||
@TDeclarationInheritanceCacheItem(DeclInhItem).CodePos);
|
||||
end;
|
||||
|
||||
procedure TDeclarationInheritanceCache.CheckCurrentIsValid;
|
||||
begin
|
||||
if (FCurrent<>nil)
|
||||
and (FCurrent.CodeToolsChangeStep<>GlobalCodeNodeTreeChangeStep) then begin
|
||||
// the current cache is invalid => move to old
|
||||
if FOldTrees=nil then FOldTrees:=TFPList.Create;
|
||||
FOldTrees.Add(FCurrent);
|
||||
FCurrent:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDeclarationInheritanceCache.CleanCache(FreeItemCount: integer);
|
||||
// free some old cache items
|
||||
var
|
||||
i: Integer;
|
||||
OldTree: TDeclarationInheritanceCacheTree;
|
||||
begin
|
||||
for i:=1 to FreeItemCount do begin
|
||||
if FOldTrees=nil then exit;
|
||||
if FOldTrees.Count=0 then begin
|
||||
FreeAndNil(FOldTrees);
|
||||
end else begin
|
||||
OldTree:=TDeclarationInheritanceCacheTree(FOldTrees[FOldTrees.Count-1]);
|
||||
if OldTree.Count=0 then begin
|
||||
OldTree.Free;
|
||||
FOldTrees.Delete(FOldTrees.Count-1);
|
||||
end else begin
|
||||
OldTree.FreeAndDelete(OldTree.Root);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TDeclarationInheritanceCache.Create(
|
||||
const TheOnFindDeclarations: TOnFindDeclarations);
|
||||
begin
|
||||
OnFindDeclarations:=TheOnFindDeclarations;
|
||||
end;
|
||||
|
||||
destructor TDeclarationInheritanceCache.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
FreeAndNil(FCurrent);
|
||||
FreeAndNil(FOldTrees);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TDeclarationInheritanceCache.Clear;
|
||||
var
|
||||
i: LongInt;
|
||||
begin
|
||||
if FOldTrees<>nil then begin
|
||||
for i:=FOldTrees.Count downto 0 do
|
||||
TDeclarationInheritanceCacheTree(FOldTrees[i]).Free;
|
||||
FreeAndNil(FOldTrees);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDeclarationInheritanceCache.FindDeclarations(Code: TCodeBuffer; X,
|
||||
Y: integer; out ListOfPCodeXYPosition: TFPList; out CacheWasUsed: boolean
|
||||
): boolean;
|
||||
var
|
||||
CodePos: TCodePosition;
|
||||
AVLNode: TAVLTreeNode;
|
||||
Item: TDeclarationInheritanceCacheItem;
|
||||
begin
|
||||
Result:=false;
|
||||
ListOfPCodeXYPosition:=nil;
|
||||
CacheWasUsed:=true;
|
||||
if Code=nil then exit;
|
||||
CodePos.Code:=Code;
|
||||
Code.LineColToPosition(Y,X,CodePos.P);
|
||||
if (CodePos.P<1) or (CodePos.P>Code.SourceLength) then exit;
|
||||
|
||||
// move cursor to start of identifier (needed to find CodePos in cache)
|
||||
while (CodePos.P>1) and (IsIdentChar[Code.Source[CodePos.P-1]]) do
|
||||
dec(CodePos.P);
|
||||
if not IsIdentChar[Code.Source[CodePos.P]] then exit;
|
||||
|
||||
// search in cache
|
||||
CheckCurrentIsValid;
|
||||
if FCurrent<>nil then begin
|
||||
// the current cache is valid
|
||||
AVLNode:=FCurrent.FindKey(@CodePos,@ComparePCodePosWithDeclInhCacheItem);
|
||||
if AVLNode<>nil then begin
|
||||
Item:=TDeclarationInheritanceCacheItem(AVLNode.Data);
|
||||
ListOfPCodeXYPosition:=Item.ListOfPCodeXYPosition;
|
||||
Result:=ListOfPCodeXYPosition<>nil;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
CacheWasUsed:=false;
|
||||
|
||||
// ask the codetools
|
||||
if OnFindDeclarations(Code,X,Y,ListOfPCodeXYPosition,[])
|
||||
and (ListOfPCodeXYPosition<>nil)
|
||||
and (ListOfPCodeXYPosition.Count>0) then begin
|
||||
Result:=true;
|
||||
end else begin
|
||||
FreeAndNil(ListOfPCodeXYPosition);
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
// save to cache
|
||||
Item:=TDeclarationInheritanceCacheItem.Create;
|
||||
Item.CodePos:=CodePos;
|
||||
Item.ListOfPCodeXYPosition:=ListOfPCodeXYPosition;
|
||||
CheckCurrentIsValid;
|
||||
if FCurrent=nil then begin
|
||||
FCurrent:=TDeclarationInheritanceCacheTree.CreateDeclInhTree;
|
||||
FCurrent.CodeToolsChangeStep:=GlobalCodeNodeTreeChangeStep;
|
||||
end;
|
||||
FCurrent.Add(Item);
|
||||
|
||||
// clean up cache a bit
|
||||
CleanCache(5);
|
||||
end;
|
||||
|
||||
constructor TDeclarationInheritanceCacheTree.CreateDeclInhTree;
|
||||
begin
|
||||
Create(@CompareDeclInhCacheItems);
|
||||
end;
|
||||
|
||||
destructor TDeclarationInheritanceCacheTree.Destroy;
|
||||
begin
|
||||
FreeAndClear;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
{ TDeclarationInheritanceCacheItem }
|
||||
|
||||
destructor TDeclarationInheritanceCacheItem.Destroy;
|
||||
begin
|
||||
FreeListOfPCodeXYPosition(ListOfPCodeXYPosition);
|
||||
ListOfPCodeXYPosition:=nil;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -143,6 +143,7 @@ function AtomPosition(StartPos, EndPos: integer): TAtomPosition;
|
||||
function CodePosition(P: integer; Code: TCodeBuffer): TCodePosition;
|
||||
function CodeXYPosition(X, Y: integer; Code: TCodeBuffer): TCodeXYPosition;
|
||||
function CompareCodeXYPositions(Pos1, Pos2: PCodeXYPosition): integer;
|
||||
function CompareCodePositions(Pos1, Pos2: PCodePosition): integer;
|
||||
|
||||
procedure AddCodePosition(var ListOfPCodeXYPosition: TFPList;
|
||||
const NewCodePos: TCodeXYPosition);
|
||||
@ -194,6 +195,15 @@ begin
|
||||
else Result:=0;
|
||||
end;
|
||||
|
||||
function CompareCodePositions(Pos1, Pos2: PCodePosition): integer;
|
||||
begin
|
||||
if Pointer(Pos1^.Code)>Pointer(Pos2^.Code) then Result:=1
|
||||
else if Pointer(Pos1^.Code)<Pointer(Pos2^.Code) then Result:=-1
|
||||
else if Pos1^.P<Pos2^.P then Result:=1
|
||||
else if Pos1^.P>Pos2^.P then Result:=-1
|
||||
else Result:=0;
|
||||
end;
|
||||
|
||||
procedure AddCodePosition(var ListOfPCodeXYPosition: TFPList;
|
||||
const NewCodePos: TCodeXYPosition);
|
||||
var
|
||||
|
@ -108,6 +108,7 @@ type
|
||||
FWriteExceptions: boolean;
|
||||
FWriteLockCount: integer;// Set/Unset counter
|
||||
FWriteLockStep: integer; // current write lock ID
|
||||
function GetGlobalCodeNodeTreeChangeStep: integer;
|
||||
function OnScannerGetInitValues(Code: Pointer;
|
||||
out AChangeStep: integer): TExpressionEvaluator;
|
||||
procedure OnDefineTreeReadValue(Sender: TObject; const VariableName: string;
|
||||
@ -167,6 +168,7 @@ type
|
||||
procedure DeactivateWriteLock;
|
||||
property ChangeStep: integer read FChangeStep;
|
||||
procedure IncreaseChangeStep;
|
||||
property GlobalCodeNodeTreeChangeStep: integer read GetGlobalCodeNodeTreeChangeStep;
|
||||
|
||||
// file handling
|
||||
property SourceExtensions: string
|
||||
@ -2718,8 +2720,8 @@ end;
|
||||
|
||||
function TCodeToolManager.CreatePrivateMethod(Code: TCodeBuffer;
|
||||
const AClassName, NewMethodName: string; ATypeInfo: PTypeInfo;
|
||||
UseTypeInfoForParameters: boolean;
|
||||
const APropertyUnitName, APropertyPath: string): boolean;
|
||||
UseTypeInfoForParameters: boolean; const APropertyUnitName: string;
|
||||
const APropertyPath: string): boolean;
|
||||
begin
|
||||
{$IFDEF CTDEBUG}
|
||||
DebugLn('TCodeToolManager.CreatePrivateMethod A');
|
||||
@ -4103,6 +4105,11 @@ begin
|
||||
Result:=DefineTree.GetDefinesForVirtualDirectory;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.GetGlobalCodeNodeTreeChangeStep: integer;
|
||||
begin
|
||||
Result:=CustomCodeTool.GlobalCodeNodeTreeChangeStep;
|
||||
end;
|
||||
|
||||
procedure TCodeToolManager.OnDefineTreeReadValue(Sender: TObject;
|
||||
const VariableName: string; var Value: string; var Handled: boolean);
|
||||
begin
|
||||
@ -4386,10 +4393,10 @@ end;
|
||||
|
||||
procedure TCodeToolManager.IncreaseChangeStep;
|
||||
begin
|
||||
if FChangeStep<>$7fffffff then
|
||||
if FChangeStep<>High(Integer) then
|
||||
inc(FChangeStep)
|
||||
else
|
||||
FChangeStep:=-$7fffffff;
|
||||
FChangeStep:=Low(Integer);
|
||||
end;
|
||||
|
||||
procedure TCodeToolManager.OnToolGetWriteLockInfo(out WriteLockIsSet: boolean;
|
||||
@ -4397,7 +4404,7 @@ procedure TCodeToolManager.OnToolGetWriteLockInfo(out WriteLockIsSet: boolean;
|
||||
begin
|
||||
WriteLockIsSet:=FWriteLockCount>0;
|
||||
WriteLockStep:=FWriteLockStep;
|
||||
//DebugLn(' FWriteLockCount=',FWriteLockCount,' FWriteLockStep=',FWriteLockStep);
|
||||
//DebugLn(' FWriteLockCount=',FWriteLockCount,' FWriteLockStep=',FWriteLockStep);
|
||||
end;
|
||||
|
||||
function TCodeToolManager.GetResourceTool: TResourceCodeTool;
|
||||
|
@ -291,10 +291,10 @@ type
|
||||
ExceptionClass: ECodeToolErrors); virtual;
|
||||
procedure RaiseException(const AMessage: string); virtual;
|
||||
procedure RaiseExceptionFmt(const AMessage: string;
|
||||
const args : array of const);
|
||||
const args: array of const);
|
||||
procedure SaveRaiseException(const AMessage: string); virtual;
|
||||
procedure SaveRaiseExceptionFmt(const AMessage: string;
|
||||
const args : array of const);
|
||||
const args: array of const);
|
||||
property IgnoreErrorAfter: TCodePosition
|
||||
read FIgnoreErrorAfter write SetIgnoreErrorAfter;
|
||||
procedure ClearIgnoreErrorAfter;
|
||||
@ -318,9 +318,20 @@ type
|
||||
|
||||
var
|
||||
RaiseUnhandableExceptions: boolean;
|
||||
GlobalCodeNodeTreeChangeStep: integer = 0;
|
||||
|
||||
procedure IncreaseGlobalCodeNodeTreeChangeStep;
|
||||
|
||||
implementation
|
||||
|
||||
procedure IncreaseGlobalCodeNodeTreeChangeStep;
|
||||
begin
|
||||
if GlobalCodeNodeTreeChangeStep=High(integer) then
|
||||
GlobalCodeNodeTreeChangeStep:=Low(integer)
|
||||
else
|
||||
inc(GlobalCodeNodeTreeChangeStep);
|
||||
end;
|
||||
|
||||
|
||||
{ TCustomCodeTool }
|
||||
|
||||
@ -1923,6 +1934,7 @@ begin
|
||||
FTreeChangeStep:=Low(integer)
|
||||
else
|
||||
inc(FTreeChangeStep);
|
||||
IncreaseGlobalCodeNodeTreeChangeStep;
|
||||
end;
|
||||
|
||||
procedure TCustomCodeTool.RaiseExceptionInstance(TheException: ECodeToolError);
|
||||
|
@ -158,7 +158,7 @@ type
|
||||
TParsedCompilerOptions = class
|
||||
private
|
||||
FGetWritableOutputDirectory: TGetWritableOutputDirectory;
|
||||
FInvalidateGraphOnChange: boolean;
|
||||
FInvalidateParseOnChange: boolean;
|
||||
FOnLocalSubstitute: TLocalSubstitutionEvent;
|
||||
public
|
||||
UnparsedValues: array[TParsedCompilerOptString] of string;
|
||||
@ -185,8 +185,8 @@ type
|
||||
public
|
||||
property OnLocalSubstitute: TLocalSubstitutionEvent read FOnLocalSubstitute
|
||||
write FOnLocalSubstitute;
|
||||
property InvalidateGraphOnChange: boolean read FInvalidateGraphOnChange
|
||||
write FInvalidateGraphOnChange;
|
||||
property InvalidateParseOnChange: boolean read FInvalidateParseOnChange
|
||||
write FInvalidateParseOnChange;
|
||||
property GetWritableOutputDirectory: TGetWritableOutputDirectory
|
||||
read FGetWritableOutputDirectory write FGetWritableOutputDirectory;
|
||||
end;
|
||||
@ -265,7 +265,6 @@ type
|
||||
FDefaultMakeOptionsFlags: TCompilerCmdLineOptions;
|
||||
fInheritedOptions: TInheritedCompOptsParseTypesStrings;
|
||||
fInheritedOptParseStamps: integer;
|
||||
fInheritedOptGraphStamps: integer;
|
||||
fLoaded: Boolean;
|
||||
fOptionsString: String;
|
||||
FParsedOpts: TParsedCompilerOptions;
|
||||
@ -454,20 +453,18 @@ const
|
||||
);
|
||||
|
||||
type
|
||||
TCompilerGraphStampIncreasedEvent = procedure of object;
|
||||
TCompilerParseStampIncreasedEvent = procedure of object;
|
||||
TRunCompilerWithOptions = function(ExtTool: TIDEExternalToolOptions;
|
||||
ACompilerOptions: TBaseCompilerOptions): TModalResult of object;
|
||||
|
||||
var
|
||||
CompilerParseStamp: integer; // TimeStamp of base value for macros
|
||||
CompilerGraphStamp: integer; // TimeStamp of IDE graph (e.g. packages)
|
||||
OnParseString: TParseStringEvent = nil;
|
||||
CompilerGraphStampIncreased: TCompilerGraphStampIncreasedEvent = nil;
|
||||
CompilerParseStampIncreased: TCompilerParseStampIncreasedEvent = nil;
|
||||
|
||||
RunCompilerWithOptions: TRunCompilerWithOptions = nil;
|
||||
|
||||
procedure IncreaseCompilerParseStamp;
|
||||
procedure IncreaseCompilerGraphStamp;
|
||||
function ParseString(Options: TParsedCompilerOptions;
|
||||
const UnparsedValue: string;
|
||||
PlatformIndependent: boolean): string;
|
||||
@ -506,16 +503,8 @@ begin
|
||||
inc(CompilerParseStamp)
|
||||
else
|
||||
CompilerParseStamp:=MinParseStamp;
|
||||
end;
|
||||
|
||||
procedure IncreaseCompilerGraphStamp;
|
||||
begin
|
||||
if CompilerGraphStamp<MaxParseStamp then
|
||||
inc(CompilerGraphStamp)
|
||||
else
|
||||
CompilerGraphStamp:=MinParseStamp;
|
||||
if Assigned(CompilerGraphStampIncreased) then
|
||||
CompilerGraphStampIncreased();
|
||||
if Assigned(CompilerParseStampIncreased) then
|
||||
CompilerParseStampIncreased();
|
||||
end;
|
||||
|
||||
function ParseString(Options: TParsedCompilerOptions;
|
||||
@ -1334,7 +1323,7 @@ var
|
||||
p: TCompilerOptionsParseType;
|
||||
begin
|
||||
fInheritedOptParseStamps:=InvalidParseStamp;
|
||||
fInheritedOptGraphStamps:=InvalidParseStamp;
|
||||
//QWE fInheritedOptGraphStamps:=InvalidParseStamp;
|
||||
for p:=Low(TCompilerOptionsParseType) to High(TCompilerOptionsParseType) do
|
||||
for i:=Low(TInheritedCompilerOption) to High(TInheritedCompilerOption) do
|
||||
begin
|
||||
@ -1428,7 +1417,7 @@ var
|
||||
p: TCompilerOptionsParseType;
|
||||
begin
|
||||
if (fInheritedOptParseStamps<>CompilerParseStamp)
|
||||
or (fInheritedOptGraphStamps<>CompilerGraphStamp)
|
||||
//QWE or (fInheritedOptGraphStamps<>CompilerGraphStamp)
|
||||
then begin
|
||||
// update inherited options
|
||||
ClearInheritedOptions;
|
||||
@ -1442,7 +1431,7 @@ begin
|
||||
OptionsList.Free;
|
||||
end;
|
||||
fInheritedOptParseStamps:=CompilerParseStamp;
|
||||
fInheritedOptGraphStamps:=CompilerGraphStamp;
|
||||
//QWE fInheritedOptGraphStamps:=CompilerGraphStamp;
|
||||
end;
|
||||
Result:=fInheritedOptions[Parsed][Option];
|
||||
if RelativeToBaseDir then begin
|
||||
@ -2816,7 +2805,7 @@ procedure TParsedCompilerOptions.SetUnparsedValue(
|
||||
Option: TParsedCompilerOptString; const NewValue: string);
|
||||
begin
|
||||
if NewValue=UnparsedValues[Option] then exit;
|
||||
if InvalidateGraphOnChange then IncreaseCompilerGraphStamp;
|
||||
if InvalidateParseOnChange then IncreaseCompilerParseStamp;
|
||||
if Option=pcosBaseDir then
|
||||
InvalidateFiles
|
||||
else begin
|
||||
@ -3124,8 +3113,7 @@ end;
|
||||
|
||||
initialization
|
||||
CompilerParseStamp:=1;
|
||||
CompilerGraphStamp:=1;
|
||||
CompilerGraphStampIncreased:=nil;
|
||||
CompilerParseStampIncreased:=nil;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -32,10 +32,11 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, LCLProc, FileUtil,
|
||||
CodeTree, CodeToolManager, CodeCache, FileProcs, AvgLvlTree,
|
||||
CodeAtom, CodeTree, CodeToolManager, CodeCache, CacheCodeTools,
|
||||
FileProcs, AvgLvlTree,
|
||||
Laz_DOM, Laz_XMLRead, Laz_XMLWrite,
|
||||
MacroIntf, PackageIntf, LazHelpIntf, ProjectIntf, LazIDEIntf,
|
||||
IDEProcs, PackageDefs, EnvironmentOpts;
|
||||
CompilerOptions, IDEProcs, PackageDefs, EnvironmentOpts;
|
||||
|
||||
type
|
||||
{ TLazFPDocFile }
|
||||
@ -52,6 +53,8 @@ type
|
||||
function GetElementWithName(const ElementName: string): TDOMNode;
|
||||
end;
|
||||
|
||||
{ TLDSourceToFPDocFile - cache item for source to FPDoc file mapping }
|
||||
|
||||
TLDSourceToFPDocFile = class
|
||||
public
|
||||
SourceFilename: string;
|
||||
@ -79,6 +82,8 @@ type
|
||||
private
|
||||
FDocs: TAvgLvlTree;// tree of loaded TLazFPDocFile
|
||||
FHandlers: array[TLazDocManagerHandler] of TMethodList;
|
||||
FSrcToDocMap: TAvgLvlTree; // tree of TLDSourceToFPDocFile sorted for SourceFilename
|
||||
FDeclarationCache: TDeclarationInheritanceCache;
|
||||
procedure AddHandler(HandlerType: TLazDocManagerHandler;
|
||||
const AMethod: TMethod; AsLast: boolean = false);
|
||||
procedure RemoveHandler(HandlerType: TLazDocManagerHandler;
|
||||
@ -89,22 +94,23 @@ type
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure FreeDocs;
|
||||
procedure ClearSrcToDocMap;
|
||||
|
||||
function FindFPDocFile(const Filename: string): TLazFPDocFile;
|
||||
function LoadFPDocFile(const Filename: string;
|
||||
UpdateFromDisk, Revert: Boolean;
|
||||
out ADocFile: TLazFPDocFile;
|
||||
out UsedCache: boolean): Boolean;
|
||||
out CacheWasUsed: boolean): Boolean;
|
||||
function GetFPDocFilenameForHelpContext(
|
||||
Context: TPascalHelpContextList;
|
||||
out UsedCache: boolean): string;
|
||||
out CacheWasUsed: boolean): string;
|
||||
function GetFPDocFilenameForSource(SrcFilename: string;
|
||||
ResolveIncludeFiles: Boolean;
|
||||
out UsedCache: boolean): string;
|
||||
out CacheWasUsed: boolean): string;
|
||||
function CodeNodeToElementName(Tool: TCodeTool; CodeNode: TCodeTreeNode): string;
|
||||
function GetFPDocNode(Tool: TCodeTool; CodeNode: TCodeTreeNode; Complete: boolean;
|
||||
out FPDocFile: TLazFPDocFile; out DOMNode: TDOMNode;
|
||||
out UsedCache: boolean): TLazDocParseResult;
|
||||
out CacheWasUsed: boolean): TLazDocParseResult;
|
||||
public
|
||||
// Event lists
|
||||
procedure RemoveAllHandlersOfObject(AnObject: TObject);
|
||||
@ -121,10 +127,13 @@ var
|
||||
|
||||
function CompareLazFPDocFilenames(Data1, Data2: Pointer): integer;
|
||||
function CompareAnsistringWithLazFPDocFile(Key, Data: Pointer): integer;
|
||||
function CompareLDSrc2DocSrcFilenames(Data1, Data2: Pointer): integer;
|
||||
function CompareAnsistringWithLDSrc2DocSrcFile(Key, Data: Pointer): integer;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
function CompareLazFPDocFilenames(Data1, Data2: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareFilenames(TLazFPDocFile(Data1).Filename,
|
||||
@ -136,6 +145,17 @@ begin
|
||||
Result:=CompareFilenames(AnsiString(Key),TLazFPDocFile(Data).Filename);
|
||||
end;
|
||||
|
||||
function CompareLDSrc2DocSrcFilenames(Data1, Data2: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareFilenames(TLDSourceToFPDocFile(Data1).SourceFilename,
|
||||
TLDSourceToFPDocFile(Data2).SourceFilename);
|
||||
end;
|
||||
|
||||
function CompareAnsistringWithLDSrc2DocSrcFile(Key, Data: Pointer): integer;
|
||||
begin
|
||||
Result:=CompareFilenames(AnsiString(Key),TLDSourceToFPDocFile(Data).SourceFilename);
|
||||
end;
|
||||
|
||||
{ TLazFPDocFile }
|
||||
|
||||
destructor TLazFPDocFile.Destroy;
|
||||
@ -214,12 +234,18 @@ end;
|
||||
constructor TLazDocManager.Create;
|
||||
begin
|
||||
FDocs:=TAvgLvlTree.Create(@CompareLazFPDocFilenames);
|
||||
FSrcToDocMap:=TAvgLvlTree.Create(@CompareLDSrc2DocSrcFilenames);
|
||||
FDeclarationCache:=TDeclarationInheritanceCache.Create(
|
||||
@CodeToolBoss.FindDeclarationAndOverload);
|
||||
end;
|
||||
|
||||
destructor TLazDocManager.Destroy;
|
||||
begin
|
||||
ClearSrcToDocMap;
|
||||
FreeDocs;
|
||||
FreeAndNil(FDocs);
|
||||
FreeAndNil(FSrcToDocMap);
|
||||
FreeAndNil(FDeclarationCache);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
@ -235,12 +261,12 @@ begin
|
||||
end;
|
||||
|
||||
function TLazDocManager.LoadFPDocFile(const Filename: string; UpdateFromDisk,
|
||||
Revert: Boolean; out ADocFile: TLazFPDocFile; out UsedCache: boolean): Boolean;
|
||||
Revert: Boolean; out ADocFile: TLazFPDocFile; out CacheWasUsed: boolean): Boolean;
|
||||
var
|
||||
MemStream: TMemoryStream;
|
||||
begin
|
||||
Result:=false;
|
||||
UsedCache:=true;
|
||||
CacheWasUsed:=true;
|
||||
ADocFile:=FindFPDocFile(Filename);
|
||||
if ADocFile=nil then begin
|
||||
ADocFile:=TLazFPDocFile.Create;
|
||||
@ -259,7 +285,7 @@ begin
|
||||
// no update needed
|
||||
exit(true);
|
||||
end;
|
||||
UsedCache:=false;
|
||||
CacheWasUsed:=false;
|
||||
|
||||
DebugLn(['TLazDocManager.LoadFPDocFile parsing ',ADocFile.Filename]);
|
||||
CallDocChangeEvents(ldmhDocChanging,ADocFile);
|
||||
@ -284,24 +310,24 @@ begin
|
||||
end;
|
||||
|
||||
function TLazDocManager.GetFPDocFilenameForHelpContext(
|
||||
Context: TPascalHelpContextList; out UsedCache: boolean): string;
|
||||
Context: TPascalHelpContextList; out CacheWasUsed: boolean): string;
|
||||
var
|
||||
i: Integer;
|
||||
SrcFilename: String;
|
||||
begin
|
||||
Result:='';
|
||||
UsedCache:=true;
|
||||
CacheWasUsed:=true;
|
||||
if Context=nil then exit;
|
||||
for i:=0 to Context.Count-1 do begin
|
||||
if Context.Items[i].Descriptor<>pihcFilename then continue;
|
||||
SrcFilename:=Context.Items[i].Context;
|
||||
Result:=GetFPDocFilenameForSource(SrcFilename,true,UsedCache);
|
||||
Result:=GetFPDocFilenameForSource(SrcFilename,true,CacheWasUsed);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLazDocManager.GetFPDocFilenameForSource(SrcFilename: string;
|
||||
ResolveIncludeFiles: Boolean; out UsedCache: boolean): string;
|
||||
ResolveIncludeFiles: Boolean; out CacheWasUsed: boolean): string;
|
||||
var
|
||||
FPDocName: String;
|
||||
SearchPath: String;
|
||||
@ -368,9 +394,11 @@ var
|
||||
|
||||
var
|
||||
CodeBuf: TCodeBuffer;
|
||||
AVLNode: TAvgLvlTreeNode;
|
||||
MapEntry: TLDSourceToFPDocFile;
|
||||
begin
|
||||
Result:='';
|
||||
UsedCache:=false;
|
||||
CacheWasUsed:=true;
|
||||
|
||||
if ResolveIncludeFiles then begin
|
||||
CodeBuf:=CodeToolBoss.FindFile(SrcFilename);
|
||||
@ -383,6 +411,18 @@ begin
|
||||
end;
|
||||
|
||||
if not FilenameIsPascalSource(SrcFilename) then exit;
|
||||
|
||||
// first try cache
|
||||
MapEntry:=nil;
|
||||
AVLNode:=FSrcToDocMap.FindKey(Pointer(SrcFilename),@CompareAnsistringWithLDSrc2DocSrcFile);
|
||||
if AVLNode<>nil then begin
|
||||
MapEntry:=TLDSourceToFPDocFile(AVLNode.Data);
|
||||
if MapEntry.FPDocFilenameTimeStamp=CompilerParseStamp then begin
|
||||
Result:=MapEntry.FPDocFilename;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
CacheWasUsed:=false;
|
||||
|
||||
// first check if the file is owned by any project/package
|
||||
SearchPath:='';
|
||||
@ -395,6 +435,15 @@ begin
|
||||
FPDocName:=lowercase(ExtractFileNameOnly(SrcFilename))+'.xml';
|
||||
DebugLn(['TLazDocManager.GetFPDocFilenameForSource Search ',FPDocName,' in "',SearchPath,'"']);
|
||||
Result:=SearchFileInPath(FPDocName,'',SearchPath,';',ctsfcAllCase);
|
||||
|
||||
// save to cache
|
||||
if MapEntry=nil then begin
|
||||
MapEntry:=TLDSourceToFPDocFile.Create;
|
||||
MapEntry.SourceFilename:=SrcFilename;
|
||||
FSrcToDocMap.Add(MapEntry);
|
||||
end;
|
||||
MapEntry.FPDocFilename:=Result;
|
||||
MapEntry.FPDocFilenameTimeStamp:=CompilerParseStamp;
|
||||
end;
|
||||
|
||||
function TLazDocManager.CodeNodeToElementName(Tool: TCodeTool;
|
||||
@ -424,7 +473,7 @@ end;
|
||||
|
||||
function TLazDocManager.GetFPDocNode(Tool: TCodeTool; CodeNode: TCodeTreeNode;
|
||||
Complete: boolean; out FPDocFile: TLazFPDocFile; out DOMNode: TDOMNode;
|
||||
out UsedCache: boolean): TLazDocParseResult;
|
||||
out CacheWasUsed: boolean): TLazDocParseResult;
|
||||
var
|
||||
SrcFilename: String;
|
||||
FPDocFilename: String;
|
||||
@ -432,18 +481,18 @@ var
|
||||
begin
|
||||
FPDocFile:=nil;
|
||||
DOMNode:=nil;
|
||||
UsedCache:=true;
|
||||
CacheWasUsed:=true;
|
||||
|
||||
// find corresponding FPDoc file
|
||||
SrcFilename:=Tool.MainFilename;
|
||||
FPDocFilename:=GetFPDocFilenameForSource(SrcFilename,false,UsedCache);
|
||||
FPDocFilename:=GetFPDocFilenameForSource(SrcFilename,false,CacheWasUsed);
|
||||
if FPDocFilename='' then exit(ldprFailed);
|
||||
if (not UsedCache) and (not Complete) then exit(ldprParsing);
|
||||
if (not CacheWasUsed) and (not Complete) then exit(ldprParsing);
|
||||
|
||||
// load FPDoc file
|
||||
if not LoadFPDocFile(FPDocFilename,true,false,FPDocFile,UsedCache) then
|
||||
if not LoadFPDocFile(FPDocFilename,true,false,FPDocFile,CacheWasUsed) then
|
||||
exit(ldprFailed);
|
||||
if (not UsedCache) and (not Complete) then exit(ldprParsing);
|
||||
if (not CacheWasUsed) and (not Complete) then exit(ldprParsing);
|
||||
|
||||
// find FPDoc node
|
||||
ElementName:=CodeNodeToElementName(Tool,CodeNode);
|
||||
@ -466,6 +515,11 @@ begin
|
||||
FDocs.FreeAndClear;
|
||||
end;
|
||||
|
||||
procedure TLazDocManager.ClearSrcToDocMap;
|
||||
begin
|
||||
FSrcToDocMap.FreeAndClear;
|
||||
end;
|
||||
|
||||
procedure TLazDocManager.RemoveAllHandlersOfObject(AnObject: TObject);
|
||||
var
|
||||
HandlerType: TLazDocManagerHandler;
|
||||
|
10
ide/main.pp
10
ide/main.pp
@ -491,7 +491,7 @@ type
|
||||
var IsDefined: boolean);
|
||||
procedure CodeToolBossPrepareTree(Sender: TObject);
|
||||
function CTMacroFunctionProject(Data: Pointer): boolean;
|
||||
procedure OnCompilerGraphStampIncreased;
|
||||
procedure OnCompilerParseStampIncreased;
|
||||
|
||||
// MessagesView events
|
||||
procedure MessagesViewSelectionChanged(sender: TObject);
|
||||
@ -3427,7 +3427,7 @@ begin
|
||||
if frmCompilerOptions.ShowModal=mrOk then begin
|
||||
MainBuildBoss.RescanCompilerDefines(true);
|
||||
Project1.DefineTemplates.AllChanged;
|
||||
IncreaseCompilerGraphStamp;
|
||||
IncreaseCompilerParseStamp;
|
||||
end;
|
||||
finally
|
||||
frmCompilerOptions.Free;
|
||||
@ -3454,7 +3454,7 @@ begin
|
||||
if frmCompilerOptions.ShowModal=mrOk then begin
|
||||
MainBuildBoss.RescanCompilerDefines(true);
|
||||
Project1.DefineTemplates.AllChanged;
|
||||
IncreaseCompilerGraphStamp;
|
||||
IncreaseCompilerParseStamp;
|
||||
end;
|
||||
finally
|
||||
frmCompilerOptions.Free;
|
||||
@ -10867,7 +10867,7 @@ begin
|
||||
|
||||
CodeToolsOpts.AssignGlobalDefineTemplatesToTree(CodeToolBoss.DefineTree);
|
||||
|
||||
CompilerGraphStampIncreased:=@OnCompilerGraphStampIncreased;
|
||||
CompilerParseStampIncreased:=@OnCompilerParseStampIncreased;
|
||||
|
||||
// codetools consistency check
|
||||
c:=CodeToolBoss.ConsistencyCheck;
|
||||
@ -11028,7 +11028,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainIDE.OnCompilerGraphStampIncreased;
|
||||
procedure TMainIDE.OnCompilerParseStampIncreased;
|
||||
begin
|
||||
FRebuildingCompilerGraphCodeToolsDefinesNeeded:=true;
|
||||
end;
|
||||
|
@ -2358,7 +2358,7 @@ begin
|
||||
fPublishOptions:=TPublishPackageOptions.Create(Self);
|
||||
FProvides:=TStringList.Create;
|
||||
Clear;
|
||||
FUsageOptions.ParsedOpts.InvalidateGraphOnChange:=true;
|
||||
FUsageOptions.ParsedOpts.InvalidateParseOnChange:=true;
|
||||
end;
|
||||
|
||||
destructor TLazPackage.Destroy;
|
||||
|
@ -910,7 +910,7 @@ end;
|
||||
procedure TPkgManager.PackageGraphEndUpdate(Sender: TObject;
|
||||
GraphChanged: boolean);
|
||||
begin
|
||||
if GraphChanged then IncreaseCompilerGraphStamp;
|
||||
if GraphChanged then IncreaseCompilerParseStamp;
|
||||
if PackageGraphExplorer<>nil then begin
|
||||
if GraphChanged then PackageGraphExplorer.UpdateAll;
|
||||
PackageGraphExplorer.EndUpdate;
|
||||
|
Loading…
Reference in New Issue
Block a user