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:
mattias 2007-11-20 20:00:26 +00:00
parent 17b318bf8c
commit 7a243a0dbd
11 changed files with 371 additions and 60 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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.

View 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.

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;