codetools: use global changesteps for quick updateneeded checks

git-svn-id: trunk@29787 -
This commit is contained in:
mattias 2011-03-10 22:22:47 +00:00
parent 06da501b26
commit 517bd4b789
10 changed files with 180 additions and 147 deletions

View File

@ -283,6 +283,7 @@ begin
inherited Create; inherited Create;
FItems:=TAVLTree.Create(@CompareCodeBuffers); FItems:=TAVLTree.Create(@CompareCodeBuffers);
FIncludeLinks:=TAVLTree.Create(@CompareIncludedByLink); FIncludeLinks:=TAVLTree.Create(@CompareIncludedByLink);
FChangeStamp:=CTInvalidChangeStamp64;
end; end;
destructor TCodeCache.Destroy; destructor TCodeCache.Destroy;
@ -969,10 +970,7 @@ end;
procedure TCodeCache.IncreaseChangeStamp; procedure TCodeCache.IncreaseChangeStamp;
begin begin
if FChangeStamp<high(FChangeStamp) then CTIncreaseChangeStamp64(FChangeStamp);
inc(FChangeStamp)
else
FChangeStamp:=low(FChangeStamp);
end; end;
procedure TCodeCache.WriteAllFileNames; procedure TCodeCache.WriteAllFileNames;

View File

@ -147,8 +147,8 @@ type
Code: TCodeBuffer; GoToMainCode: boolean): TFindDeclarationTool; Code: TCodeBuffer; GoToMainCode: boolean): TFindDeclarationTool;
function OnGetDirectoryCache(const ADirectory: string): TCTDirectoryCache; function OnGetDirectoryCache(const ADirectory: string): TCTDirectoryCache;
procedure OnToolSetWriteLock(Lock: boolean); procedure OnToolSetWriteLock(Lock: boolean);
procedure OnToolGetWriteLockInfo(out WriteLockIsSet: boolean; procedure OnToolGetChangeSteps(out SourcesChangeStep, FilesChangeStep,
out WriteLockStep: integer); InitValuesChangeStep: int64);
function OnParserProgress(Tool: TCustomCodeTool): boolean; function OnParserProgress(Tool: TCustomCodeTool): boolean;
procedure OnToolTreeChange(Tool: TCustomCodeTool; NodesDeleting: boolean); procedure OnToolTreeChange(Tool: TCustomCodeTool; NodesDeleting: boolean);
function OnScannerProgress(Sender: TLinkScanner): boolean; function OnScannerProgress(Sender: TLinkScanner): boolean;
@ -1245,7 +1245,7 @@ begin
Code.Scanner:=TLinkScanner.Create; Code.Scanner:=TLinkScanner.Create;
Code.Scanner.OnGetInitValues:=@OnScannerGetInitValues; Code.Scanner.OnGetInitValues:=@OnScannerGetInitValues;
Code.Scanner.OnSetGlobalWriteLock:=@OnToolSetWriteLock; Code.Scanner.OnSetGlobalWriteLock:=@OnToolSetWriteLock;
Code.Scanner.OnGetGlobalWriteLockInfo:=@OnToolGetWriteLockInfo; Code.Scanner.OnGetGlobalChangeSteps:=@OnToolGetChangeSteps;
Code.Scanner.OnProgress:=@OnScannerProgress; Code.Scanner.OnProgress:=@OnScannerProgress;
end; end;
end; end;
@ -5032,7 +5032,6 @@ begin
TCodeTool(Result).OnGetSrcPathForCompiledUnit:=@DoOnGetSrcPathForCompiledUnit; TCodeTool(Result).OnGetSrcPathForCompiledUnit:=@DoOnGetSrcPathForCompiledUnit;
TCodeTool(Result).OnGetMethodName:=@OnInternalGetMethodName; TCodeTool(Result).OnGetMethodName:=@OnInternalGetMethodName;
Result.OnSetGlobalWriteLock:=@OnToolSetWriteLock; Result.OnSetGlobalWriteLock:=@OnToolSetWriteLock;
Result.OnGetGlobalWriteLockInfo:=@OnToolGetWriteLockInfo;
Result.OnTreeChange:=@OnToolTreeChange; Result.OnTreeChange:=@OnToolTreeChange;
TCodeTool(Result).OnParserProgress:=@OnParserProgress; TCodeTool(Result).OnParserProgress:=@OnParserProgress;
end; end;
@ -5183,14 +5182,6 @@ begin
NodesDeletedStep:=FCodeTreeNodesDeletedStep; NodesDeletedStep:=FCodeTreeNodesDeletedStep;
end; end;
procedure TCodeToolManager.OnToolGetWriteLockInfo(out WriteLockIsSet: boolean;
out WriteLockStep: integer);
begin
WriteLockIsSet:=FWriteLockCount>0;
WriteLockStep:=FWriteLockStep;
//DebugLn(' FWriteLockCount=',FWriteLockCount,' FWriteLockStep=',FWriteLockStep);
end;
function TCodeToolManager.GetResourceTool: TResourceCodeTool; function TCodeToolManager.GetResourceTool: TResourceCodeTool;
begin begin
if FResourceTool=nil then FResourceTool:=TResourceCodeTool.Create; if FResourceTool=nil then FResourceTool:=TResourceCodeTool.Create;
@ -5332,6 +5323,14 @@ begin
if Lock then ActivateWriteLock else DeactivateWriteLock; if Lock then ActivateWriteLock else DeactivateWriteLock;
end; end;
procedure TCodeToolManager.OnToolGetChangeSteps(out SourcesChangeStep,
FilesChangeStep, InitValuesChangeStep: int64);
begin
SourcesChangeStep:=SourceCache.ChangeStamp;
FilesChangeStep:=FileStateCache.TimeStamp;
InitValuesChangeStep:=DefineTree.ChangeStep;
end;
procedure TCodeToolManager.ConsistencyCheck; procedure TCodeToolManager.ConsistencyCheck;
var var
CurResult: LongInt; CurResult: LongInt;

View File

@ -135,7 +135,6 @@ type
private private
FLastProgressPos: integer; FLastProgressPos: integer;
FNodesDeletedChangeStep: integer; FNodesDeletedChangeStep: integer;
FOnGetGlobalWriteLockInfo: TOnGetWriteLockInfo;
FOnParserProgress: TOnParserProgress; FOnParserProgress: TOnParserProgress;
FOnSetGlobalWriteLock: TOnSetWriteLock; FOnSetGlobalWriteLock: TOnSetWriteLock;
FScanner: TLinkScanner; FScanner: TLinkScanner;
@ -235,7 +234,7 @@ type
StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false): integer; StopAtDirectives: boolean = true; SkipEmptyLines: boolean = false): integer;
function UpdateNeeded(Range: TLinkScannerRange): boolean; function UpdateNeeded(Range: TLinkScannerRange): boolean;
function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean; deprecated; function UpdateNeeded(OnlyInterfaceNeeded: boolean): boolean; deprecated; // use UpdateNeeded(lsrImplementationStart) or UpdateNeeded(lsrEnd)
procedure BeginParsing(Range: TLinkScannerRange); virtual; procedure BeginParsing(Range: TLinkScannerRange); virtual;
procedure BeginParsingAndGetCleanPos( procedure BeginParsingAndGetCleanPos(
Range: TLinkScannerRange; CursorPos: TCodeXYPosition; Range: TLinkScannerRange; CursorPos: TCodeXYPosition;
@ -312,8 +311,6 @@ type
// write lock // write lock
procedure ActivateGlobalWriteLock; virtual; procedure ActivateGlobalWriteLock; virtual;
procedure DeactivateGlobalWriteLock; virtual; procedure DeactivateGlobalWriteLock; virtual;
property OnGetGlobalWriteLockInfo: TOnGetWriteLockInfo
read FOnGetGlobalWriteLockInfo write FOnGetGlobalWriteLockInfo;
property OnSetGlobalWriteLock: TOnSetWriteLock property OnSetGlobalWriteLock: TOnSetWriteLock
read FOnSetGlobalWriteLock write FOnSetGlobalWriteLock; read FOnSetGlobalWriteLock write FOnSetGlobalWriteLock;

View File

@ -377,7 +377,7 @@ type
FFirstDefineTemplate: TDefineTemplate; FFirstDefineTemplate: TDefineTemplate;
FCache: TAVLTree; // tree of TDirectoryDefines FCache: TAVLTree; // tree of TDirectoryDefines
FDefineStrings: TStringTree; FDefineStrings: TStringTree;
FChangeStep: integer; FChangeStep: int64;
FErrorDescription: string; FErrorDescription: string;
FErrorTemplate: TDefineTemplate; FErrorTemplate: TDefineTemplate;
FMacroFunctions: TKeyWordFunctionList; FMacroFunctions: TKeyWordFunctionList;
@ -406,7 +406,7 @@ type
public public
property RootTemplate: TDefineTemplate property RootTemplate: TDefineTemplate
read FFirstDefineTemplate write FFirstDefineTemplate; read FFirstDefineTemplate write FFirstDefineTemplate;
property ChangeStep: integer read FChangeStep; property ChangeStep: int64 read FChangeStep;
property ErrorTemplate: TDefineTemplate read FErrorTemplate; property ErrorTemplate: TDefineTemplate read FErrorTemplate;
property ErrorDescription: string read FErrorDescription; property ErrorDescription: string read FErrorDescription;
property OnGetVirtualDirectoryAlias: TOnGetVirtualDirectoryAlias property OnGetVirtualDirectoryAlias: TOnGetVirtualDirectoryAlias
@ -3710,6 +3710,7 @@ end;
constructor TDefineTree.Create; constructor TDefineTree.Create;
begin begin
inherited Create; inherited Create;
FChangeStep:=CTInvalidChangeStamp64;
FFirstDefineTemplate:=nil; FFirstDefineTemplate:=nil;
FCache:=TAVLTree.Create(@CompareDirectoryDefines); FCache:=TAVLTree.Create(@CompareDirectoryDefines);
FDefineStrings:=TStringTree.Create; FDefineStrings:=TStringTree.Create;
@ -4424,10 +4425,7 @@ end;
procedure TDefineTree.IncreaseChangeStep; procedure TDefineTree.IncreaseChangeStep;
begin begin
if FChangeStep<>$7fffffff then CTIncreaseChangeStamp64(FChangeStep);
inc(FChangeStep)
else
FChangeStep:=-$7fffffff;
if DirectoryCachePool<>nil then DirectoryCachePool.IncreaseConfigTimeStamp; if DirectoryCachePool<>nil then DirectoryCachePool.IncreaseConfigTimeStamp;
end; end;

View File

@ -1,10 +1,13 @@
#!/bin/bash #!/bin/bash
# do not include error.h - it only contains c macros for debugging # do not include gerror.h - it only contains c macros for debugging
# do not include gslice.h, gmem.h - it only contains c macros for fast mem allocation
dir=~/cpp/gtk3/glib/glib dir=~/cpp/gtk3/glib/glib
./h2pastest -uG_BEGIN_DECLS -uG_END_DECLS -uG_GNUC_CONST -dG_CONST_RETURN=const \ ./h2pastest -uG_BEGIN_DECLS -uG_END_DECLS -uG_GNUC_CONST -dG_CONST_RETURN=const \
-uGLIB_VAR -uG_INLINE_FUNC -uG_GNUC_MAY_ALIAS -uG_GNUC_MALLOC \ -uGLIB_VAR -uG_INLINE_FUNC -uG_GNUC_MAY_ALIAS -uG_GNUC_MALLOC \
-uG_GNUC_WARN_UNUSED_RESULT -uG_GNUC_NULL_TERMINATED \
-uG_GNUC_PURE \
$dir/glib.h \ $dir/glib.h \
$dir/galloca.h \ $dir/galloca.h \
$dir/garray.h \ $dir/garray.h \
@ -43,7 +46,6 @@ dir=~/cpp/gtk3/glib/glib
$dir/gmain.h \ $dir/gmain.h \
$dir/gmappedfile.h \ $dir/gmappedfile.h \
$dir/gmarkup.h \ $dir/gmarkup.h \
$dir/gmem.h \
$dir/gmessages.h \ $dir/gmessages.h \
$dir/gmirroringtable.h \ $dir/gmirroringtable.h \
$dir/gnode.h \ $dir/gnode.h \
@ -63,7 +65,6 @@ dir=~/cpp/gtk3/glib/glib
$dir/gscripttable.h \ $dir/gscripttable.h \
$dir/gsequence.h \ $dir/gsequence.h \
$dir/gshell.h \ $dir/gshell.h \
$dir/gslice.h \
$dir/gslist.h \ $dir/gslist.h \
$dir/gspawn.h \ $dir/gspawn.h \
$dir/gstdio.h \ $dir/gstdio.h \

View File

@ -251,7 +251,7 @@ function FileIsTextCached(const AFilename: string): boolean;
function FileAgeCached(const AFileName: string): Longint; function FileAgeCached(const AFileName: string): Longint;
function FileAgeToStr(aFileAge: longint): string; function FileAgeToStr(aFileAge: longint): string;
procedure InvalidateFileStateCache(const Filename: string = ''); procedure InvalidateFileStateCache(const Filename: string = ''); inline;
function CompareFileStateItems(Data1, Data2: Pointer): integer; function CompareFileStateItems(Data1, Data2: Pointer): integer;
function CompareFilenameWithFileStateCacheItem(Key, Data: Pointer): integer; function CompareFilenameWithFileStateCacheItem(Key, Data: Pointer): integer;
@ -3139,7 +3139,8 @@ end;
constructor TFileStateCache.Create; constructor TFileStateCache.Create;
begin begin
FFiles:=TAVLTree.Create(@CompareFileStateItems); FFiles:=TAVLTree.Create(@CompareFileStateItems);
FTimeStamp:=1; // one higher than default for new files FTimeStamp:=CTInvalidChangeStamp64;
CTIncreaseChangeStamp64(FTimeStamp); // one higher than default for new files
end; end;
destructor TFileStateCache.Destroy; destructor TFileStateCache.Destroy;
@ -3180,10 +3181,7 @@ begin
if Self=nil then exit; if Self=nil then exit;
if AFilename='' then begin if AFilename='' then begin
// invalidate all // invalidate all
if FTimeStamp<high(FTimeStamp) then CTIncreaseChangeStamp64(FTimeStamp);
inc(FTimeStamp)
else
FTimeStamp:=low(FTimeStamp);
for i:=0 to length(FChangeTimeStampHandler)-1 do for i:=0 to length(FChangeTimeStampHandler)-1 do
FChangeTimeStampHandler[i](Self); FChangeTimeStampHandler[i](Self);
end else begin end else begin

View File

@ -573,13 +573,13 @@ type
FOnGetSrcPathForCompiledUnit: TOnGetSrcPathForCompiledUnit; FOnGetSrcPathForCompiledUnit: TOnGetSrcPathForCompiledUnit;
FOnGetUnitSourceSearchPath: TOnGetSearchPath; FOnGetUnitSourceSearchPath: TOnGetSearchPath;
FFirstNodeCache: TCodeTreeNodeCache; FFirstNodeCache: TCodeTreeNodeCache;
FLastNodeCachesGlobalWriteLockStep: integer;
FRootNodeCache: TCodeTreeNodeCache; FRootNodeCache: TCodeTreeNodeCache;
FFirstBaseTypeCache: TBaseTypeCache; FFirstBaseTypeCache: TBaseTypeCache;
FDependentCodeTools: TAVLTree;// the codetools, that depend on this codetool FDependentCodeTools: TAVLTree;// the codetools, that depend on this codetool
FDependsOnCodeTools: TAVLTree;// the codetools, that this codetool depends on FDependsOnCodeTools: TAVLTree;// the codetools, that this codetool depends on
FClearingDependentNodeCaches: boolean; FClearingDependentNodeCaches: boolean;
FCheckingNodeCacheDependencies: boolean; FCheckingNodeCacheDependencies: boolean;
FSourcesChangeStep, FFilesChangeStep, FInitValuesChangeStep: int64;
{$IFDEF DebugPrefix} {$IFDEF DebugPrefix}
DebugPrefix: string; DebugPrefix: string;
procedure IncPrefix; procedure IncPrefix;
@ -619,7 +619,6 @@ type
protected protected
// node caches // node caches
procedure DoDeleteNodes(StartNode: TCodeTreeNode); override; procedure DoDeleteNodes(StartNode: TCodeTreeNode); override;
function NodeCacheGlobalWriteLockStepDidNotChange: boolean;
function CheckDependsOnNodeCaches(CheckedTools: TAVLTree = nil): boolean; function CheckDependsOnNodeCaches(CheckedTools: TAVLTree = nil): boolean;
procedure ClearNodeCaches(Force: boolean); procedure ClearNodeCaches(Force: boolean);
procedure ClearDependentNodeCaches; procedure ClearDependentNodeCaches;
@ -746,6 +745,7 @@ type
ExceptionOnNotFound: boolean): TFindDeclarationTool; ExceptionOnNotFound: boolean): TFindDeclarationTool;
function CheckDirectoryCache: boolean; function CheckDirectoryCache: boolean;
public public
constructor Create;
destructor Destroy; override; destructor Destroy; override;
procedure ConsistencyCheck; override; procedure ConsistencyCheck; override;
procedure CalcMemSize(Stats: TCTMemStats); override; procedure CalcMemSize(Stats: TCTMemStats); override;
@ -8797,6 +8797,14 @@ begin
Result:=FDirectoryCache<>nil; Result:=FDirectoryCache<>nil;
end; end;
constructor TFindDeclarationTool.Create;
begin
inherited Create;
FSourcesChangeStep:=CTInvalidChangeStamp64;
FFilesChangeStep:=CTInvalidChangeStamp64;
FInitValuesChangeStep:=CTInvalidChangeStamp64;
end;
procedure TFindDeclarationTool.DoDeleteNodes(StartNode: TCodeTreeNode); procedure TFindDeclarationTool.DoDeleteNodes(StartNode: TCodeTreeNode);
begin begin
ClearNodeCaches(true); ClearNodeCaches(true);
@ -8807,49 +8815,32 @@ begin
inherited DoDeleteNodes(StartNode); inherited DoDeleteNodes(StartNode);
end; end;
function TFindDeclarationTool.NodeCacheGlobalWriteLockStepDidNotChange: boolean; function TFindDeclarationTool.CheckDependsOnNodeCaches(
// checks if a node cache check is in the same GlobalWriteLockStep CheckedTools: TAVLTree = nil): boolean;
// returns true if _no_ update is needed
// returns false, if further checks are needed
var
GlobalWriteLockIsSet: boolean;
GlobalWriteLockStep: integer;
begin
Result:=false;
if Assigned(OnGetGlobalWriteLockInfo) then begin
OnGetGlobalWriteLockInfo(GlobalWriteLockIsSet,GlobalWriteLockStep);
if GlobalWriteLockIsSet then begin
// The global write lock is set. That means, input variables and code
// are frozen for all codetools and scanners, and therefore also for all
// node caches
if (FLastNodeCachesGlobalWriteLockStep=GlobalWriteLockStep) then begin
// source and values did not change since last NodeCache check
Result:=true;
end else begin
// this is the first check in this GlobalWriteLockStep
FLastNodeCachesGlobalWriteLockStep:=GlobalWriteLockStep;
// proceed normally ...
end;
end;
end;
{$IFDEF ShowCacheDependencies}
DebugLn('[TFindDeclarationTool.NodeCacheGlobalWriteLockStepDidNotChange] Result=',
DbgS(Result),' ',MainFilename);
{$ENDIF}
end;
function TFindDeclarationTool.CheckDependsOnNodeCaches
(CheckedTools: TAVLTree = nil): boolean;
var var
ANode: TAVLTreeNode; ANode: TAVLTreeNode;
ATool: TFindDeclarationTool; ATool: TFindDeclarationTool;
FreeCheckedTools: Boolean; FreeCheckedTools: Boolean;
SourcesChangeStep, FilesChangeStep, InitValuesChangeStep: int64;
begin begin
Result:=false; Result:=false;
//debugln(['TFindDeclarationTool.CheckDependsOnNodeCaches ',MainFilename,' FDependsOnCodeTools=',FDependsOnCodeTools]); //debugln(['TFindDeclarationTool.CheckDependsOnNodeCaches ',MainFilename,' FDependsOnCodeTools=',FDependsOnCodeTools]);
if (FDependsOnCodeTools=nil) or FCheckingNodeCacheDependencies if (FDependsOnCodeTools=nil) or FCheckingNodeCacheDependencies then exit;
or NodeCacheGlobalWriteLockStepDidNotChange if Scanner=nil then exit;
then exit; if Assigned(Scanner.OnGetGlobalChangeSteps) then begin
// check if any sources or values have changed
Scanner.OnGetGlobalChangeSteps(SourcesChangeStep,FilesChangeStep,
InitValuesChangeStep);
if (SourcesChangeStep=FSourcesChangeStep)
and (FilesChangeStep=FFilesChangeStep)
and (InitValuesChangeStep=FInitValuesChangeStep) then
// all sources and values are the same =>
exit;
FSourcesChangeStep:=SourcesChangeStep;
FFilesChangeStep:=FilesChangeStep;
FInitValuesChangeStep:=InitValuesChangeStep;
end;
if (CheckedTools<>nil) and (CheckedTools.Find(Self)<>nil) then exit; if (CheckedTools<>nil) and (CheckedTools.Find(Self)<>nil) then exit;
{$IFDEF ShowCacheDependencies} {$IFDEF ShowCacheDependencies}
@ -8914,10 +8905,6 @@ begin
DbgS(Force),' ',MainFilename); DbgS(Force),' ',MainFilename);
{$ENDIF} {$ENDIF}
// quick check: check if in the same GlobalWriteLockStep
if (not Force) and NodeCacheGlobalWriteLockStepDidNotChange then
exit;
// clear node caches // clear node caches
while FFirstNodeCache<>nil do begin while FFirstNodeCache<>nil do begin
NodeCache:=FFirstNodeCache; NodeCache:=FFirstNodeCache;
@ -8944,7 +8931,8 @@ var
ANode: TAVLTreeNode; ANode: TAVLTreeNode;
DependentTool: TFindDeclarationTool; DependentTool: TFindDeclarationTool;
begin begin
if (FDependentCodeTools=nil) or FClearingDependentNodeCaches then exit; if (FDependentCodeTools=nil) or (FDependentCodeTools.Count=0)
or FClearingDependentNodeCaches then exit;
FClearingDependentNodeCaches:=true; FClearingDependentNodeCaches:=true;
{$IFDEF ShowCacheDependencies} {$IFDEF ShowCacheDependencies}
DebugLn('[TFindDeclarationTool.ClearDependentNodeCaches] ',MainFilename); DebugLn('[TFindDeclarationTool.ClearDependentNodeCaches] ',MainFilename);
@ -8967,7 +8955,7 @@ var
ANode: TAVLTreeNode; ANode: TAVLTreeNode;
DependOnTool: TFindDeclarationTool; DependOnTool: TFindDeclarationTool;
begin begin
if FDependsOnCodeTools=nil then exit; if (FDependsOnCodeTools=nil) or (FDependsOnCodeTools.Count=0) then exit;
{$IFDEF ShowCacheDependencies} {$IFDEF ShowCacheDependencies}
DebugLn('[TFindDeclarationTool.ClearDependsOnToolRelationships] ',MainFilename); DebugLn('[TFindDeclarationTool.ClearDependsOnToolRelationships] ',MainFilename);
{$ENDIF} {$ENDIF}

View File

@ -82,8 +82,8 @@ type
out ChangeStep: integer): TExpressionEvaluator of object; out ChangeStep: integer): TExpressionEvaluator of object;
TOnIncludeCode = procedure(ParentCode, IncludeCode: Pointer) of object; TOnIncludeCode = procedure(ParentCode, IncludeCode: Pointer) of object;
TOnSetWriteLock = procedure(Lock: boolean) of object; TOnSetWriteLock = procedure(Lock: boolean) of object;
TOnGetWriteLockInfo = procedure(out WriteLockIsSet: boolean; TLSOnGetGlobalChangeSteps = procedure(out SourcesChangeStep, FilesChangeStep,
out WriteLockStep: integer) of object; InitValuesChangeStep: int64) of object;
{ TSourceLink is used to map between the codefiles and the cleaned source } { TSourceLink is used to map between the codefiles and the cleaned source }
PSourceLink = ^TSourceLink; PSourceLink = ^TSourceLink;
@ -227,6 +227,14 @@ type
ABuffer: Pointer; ABufferPos: integer); ABuffer: Pointer; ABufferPos: integer);
end; end;
TLinkScannerState = (
lssSourcesChanged, // used source buffers changed
lssInitValuesChanged, // used init values changed
lssFilesChanged, // used files on disk changed
lssIgnoreMissingIncludeFiles
);
TLinkScannerStates = set of TLinkScannerState;
{ TLinkScanner } { TLinkScanner }
TLinkScanner = class(TObject) TLinkScanner = class(TObject)
@ -254,13 +262,13 @@ type
FMainSourceFilename: string; FMainSourceFilename: string;
FMainCode: pointer; FMainCode: pointer;
FScanTill: TLinkScannerRange; FScanTill: TLinkScannerRange;
FIgnoreMissingIncludeFiles: boolean;
FNestedComments: boolean; FNestedComments: boolean;
FForceUpdateNeeded: boolean; FStates: TLinkScannerStates;
// global write lock // global write lock
FLastGlobalWriteLockStep: integer;
FOnGetGlobalWriteLockInfo: TOnGetWriteLockInfo;
FOnSetGlobalWriteLock: TOnSetWriteLock; FOnSetGlobalWriteLock: TOnSetWriteLock;
FGlobalSourcesChangeStep: int64;
FGlobalFilesChangeStep: int64;
FGlobalInitValuesChangeStep: int64;
function GetLinks(Index: integer): TSourceLink; function GetLinks(Index: integer): TSourceLink;
procedure SetLinks(Index: integer; const Value: TSourceLink); procedure SetLinks(Index: integer; const Value: TSourceLink);
procedure SetSource(ACode: Pointer); // set current source procedure SetSource(ACode: Pointer); // set current source
@ -269,6 +277,7 @@ type
procedure IncreaseChangeStep; procedure IncreaseChangeStep;
procedure SetMainCode(const Value: pointer); procedure SetMainCode(const Value: pointer);
procedure SetScanTill(const Value: TLinkScannerRange); procedure SetScanTill(const Value: TLinkScannerRange);
function GetIgnoreMissingIncludeFiles: boolean;
procedure SetIgnoreMissingIncludeFiles(const Value: boolean); procedure SetIgnoreMissingIncludeFiles(const Value: boolean);
function TokenIs(const AToken: shortstring): boolean; function TokenIs(const AToken: shortstring): boolean;
function UpTokenIs(const AToken: shortstring): boolean; function UpTokenIs(const AToken: shortstring): boolean;
@ -314,6 +323,7 @@ type
FMacrosOn: boolean; FMacrosOn: boolean;
FMissingIncludeFiles: TMissingIncludeFiles; FMissingIncludeFiles: TMissingIncludeFiles;
FIncludeStack: TFPList; // list of TSourceLink FIncludeStack: TFPList; // list of TSourceLink
FOnGetGlobalChangeSteps: TLSOnGetGlobalChangeSteps;
FSkippingDirectives: TLSSkippingDirective; FSkippingDirectives: TLSSkippingDirective;
FSkipIfLevel: integer; FSkipIfLevel: integer;
FCompilerMode: TCompilerMode; FCompilerMode: TCompilerMode;
@ -455,8 +465,8 @@ type
// global write lock // global write lock
procedure ActivateGlobalWriteLock; procedure ActivateGlobalWriteLock;
procedure DeactivateGlobalWriteLock; procedure DeactivateGlobalWriteLock;
property OnGetGlobalWriteLockInfo: TOnGetWriteLockInfo property OnGetGlobalChangeSteps: TLSOnGetGlobalChangeSteps
read FOnGetGlobalWriteLockInfo write FOnGetGlobalWriteLockInfo; read FOnGetGlobalChangeSteps write FOnGetGlobalChangeSteps;
property OnSetGlobalWriteLock: TOnSetWriteLock property OnSetGlobalWriteLock: TOnSetWriteLock
read FOnSetGlobalWriteLock write FOnSetGlobalWriteLock; read FOnSetGlobalWriteLock write FOnSetGlobalWriteLock;
@ -477,7 +487,7 @@ type
read FOnIncludeCode write FOnIncludeCode; read FOnIncludeCode write FOnIncludeCode;
property OnProgress: TLinkScannerProgress property OnProgress: TLinkScannerProgress
read FOnProgress write FOnProgress; read FOnProgress write FOnProgress;
property IgnoreMissingIncludeFiles: boolean read FIgnoreMissingIncludeFiles property IgnoreMissingIncludeFiles: boolean read GetIgnoreMissingIncludeFiles
write SetIgnoreMissingIncludeFiles; write SetIgnoreMissingIncludeFiles;
property InitialValues: TExpressionEvaluator property InitialValues: TExpressionEvaluator
read FInitValues write FInitValues; read FInitValues write FInitValues;
@ -1216,6 +1226,12 @@ begin
{$ENDIF} {$ENDIF}
ScanTill:=Range; ScanTill:=Range;
Clear; Clear;
if Assigned(OnGetGlobalChangeSteps) then
OnGetGlobalChangeSteps(FGlobalSourcesChangeStep,FGlobalFilesChangeStep,
FGlobalInitValuesChangeStep);
FStates:=FStates-[lssSourcesChanged,lssFilesChanged,lssInitValuesChanged];
{$IFDEF CTDEBUG} {$IFDEF CTDEBUG}
DebugLn('TLinkScanner.Scan B '); DebugLn('TLinkScanner.Scan B ');
{$ENDIF} {$ENDIF}
@ -1312,7 +1328,6 @@ begin
end; end;
end; end;
IncreaseChangeStep; IncreaseChangeStep;
FForceUpdateNeeded:=false;
FLastCleanedSrcLen:=CleanedLen; FLastCleanedSrcLen:=CleanedLen;
except except
on E: ELinkScannerError do begin on E: ELinkScannerError do begin
@ -1612,45 +1627,33 @@ end;
function TLinkScanner.UpdateNeeded( function TLinkScanner.UpdateNeeded(
Range: TLinkScannerRange; CheckFilesOnDisk: boolean): boolean; Range: TLinkScannerRange; CheckFilesOnDisk: boolean): boolean;
{ the clean source must be rebuilt if { the clean source must be rebuilt if
1. scanrange increased 1. a former check says so
2. unit source changed 2. scanrange increased
3. one of its include files changed 3. unit source changed
4. init values changed (e.g. initial compiler defines) 4. one of its include files changed
5. FForceUpdateNeeded is set 5. init values changed (e.g. initial compiler defines)
6. a missing include file can now be found 7. a missing include file can now be found
} }
var i: integer; var i: integer;
SrcLog: TSourceLog; SrcLog: TSourceLog;
NewInitValues: TExpressionEvaluator; NewInitValues: TExpressionEvaluator;
GlobalWriteLockIsSet: boolean;
GlobalWriteLockStep: integer;
NewInitValuesChangeStep: integer; NewInitValuesChangeStep: integer;
SrcChange: PSourceChangeStep; SrcChange: PSourceChangeStep;
CurSourcesChangeStep, CurFilesChangeStep, CurInitValuesChangeStep: int64;
begin begin
Result:=true; Result:=true;
if FForceUpdateNeeded then exit;
// do a quick test: check the GlobalWriteLockStep if Range=lsrNone then exit(false);
if Assigned(OnGetGlobalWriteLockInfo) then begin
OnGetGlobalWriteLockInfo(GlobalWriteLockIsSet,GlobalWriteLockStep);
if GlobalWriteLockIsSet then begin
// The global write lock is set. That means, input variables and code are
// frozen
if (FLastGlobalWriteLockStep=GlobalWriteLockStep) then begin
// source and values did not change since last UpdateNeeded check
// -> check only if ScanTill has increased
if ord(Range)>ord(ScannedRange) then exit;
Result:=false;
exit;
end else begin
// this is the first check in this GlobalWriteLockStep
FLastGlobalWriteLockStep:=GlobalWriteLockStep;
// proceed normally ...
end;
end;
end;
// check if ScanRange has increased if not Assigned(FOnCheckFileOnDisk) then CheckFilesOnDisk:=false;
// use the last check result
if [lssSourcesChanged,lssInitValuesChanged]*FStates<>[] then exit;
if CheckFilesOnDisk and (lssFilesChanged in FStates) then exit;
// check if range increased
// Note: if there was an error, then a range increase will raise the same error
// and no update is needed
if (ord(Range)>ord(ScannedRange)) and (not LastErrorIsValid) then begin if (ord(Range)>ord(ScannedRange)) and (not LastErrorIsValid) then begin
{$IFDEF VerboseUpdateNeeded} {$IFDEF VerboseUpdateNeeded}
DebugLn(['TLinkScanner.UpdateNeeded because range increased Range=',ord(Range),' ScannedRange=',ord(ScannedRange)]); DebugLn(['TLinkScanner.UpdateNeeded because range increased Range=',ord(Range),' ScannedRange=',ord(ScannedRange)]);
@ -1658,8 +1661,35 @@ begin
exit; exit;
end; end;
// check if any input has changed ... // do a quick test: check the global change steps for sources and values
FForceUpdateNeeded:=true; if Assigned(OnGetGlobalChangeSteps) then begin
OnGetGlobalChangeSteps(CurSourcesChangeStep,CurFilesChangeStep,CurInitValuesChangeStep);
if (CurSourcesChangeStep=FGlobalSourcesChangeStep)
and (CurInitValuesChangeStep=FGlobalInitValuesChangeStep)
and ((not CheckFilesOnDisk) or (CurFilesChangeStep=FGlobalSourcesChangeStep))
then begin
// sources and values did not change since last check
Result:=false;
exit;
end;
FGlobalSourcesChangeStep:=CurSourcesChangeStep;
FGlobalInitValuesChangeStep:=CurInitValuesChangeStep;
if CheckFilesOnDisk then FGlobalSourcesChangeStep:=CurFilesChangeStep;
end;
// check initvalues
if Assigned(FOnGetInitValues) then begin
NewInitValues:=FOnGetInitValues(Code,NewInitValuesChangeStep);
if (NewInitValues<>nil)
and (NewInitValuesChangeStep<>FInitValuesChangeStep)
and (not FInitValues.Equals(NewInitValues)) then begin
{$IFDEF VerboseUpdateNeeded}
DebugLn(['TLinkScanner.UpdateNeeded because InitValues changed ',MainFilename]);
{$ENDIF}
Include(FStates,lssInitValuesChanged);
exit;
end;
end;
// check all used files // check all used files
if Assigned(FOnGetSource) then begin if Assigned(FOnGetSource) then begin
@ -1669,45 +1699,38 @@ begin
//debugln(['TLinkScanner.UpdateNeeded ',ExtractFilename(MainFilename),' i=',i,' File=',FOnGetFileName(Self,SrcLog),' Last=',SrcChange^.ChangeStep,' Now=',SrcLog.ChangeStep]); //debugln(['TLinkScanner.UpdateNeeded ',ExtractFilename(MainFilename),' i=',i,' File=',FOnGetFileName(Self,SrcLog),' Last=',SrcChange^.ChangeStep,' Now=',SrcLog.ChangeStep]);
if SrcChange^.ChangeStep<>SrcLog.ChangeStep then begin if SrcChange^.ChangeStep<>SrcLog.ChangeStep then begin
{$IFDEF VerboseUpdateNeeded} {$IFDEF VerboseUpdateNeeded}
DebugLn(['TLinkScanner.UpdateNeeded because file changed: ',OnGetFileName(Self,SrcLog),' MainFilename=',MainFilename]); DebugLn(['TLinkScanner.UpdateNeeded because source buffer changed: ',OnGetFileName(Self,SrcLog),' MainFilename=',MainFilename]);
{$ENDIF} {$ENDIF}
Include(FStates,lssSourcesChanged);
exit; exit;
end; end;
end; end;
if CheckFilesOnDisk and Assigned(FOnCheckFileOnDisk) then begin if CheckFilesOnDisk then begin
// if files changed on disk, reload them // if files changed on disk, reload them
for i:=0 to FSourceChangeSteps.Count-1 do begin for i:=0 to FSourceChangeSteps.Count-1 do begin
SrcChange:=PSourceChangeStep(FSourceChangeSteps[i]); SrcChange:=PSourceChangeStep(FSourceChangeSteps[i]);
SrcLog:=FOnGetSource(Self,SrcChange^.Code); SrcLog:=FOnGetSource(Self,SrcChange^.Code);
FOnCheckFileOnDisk(SrcLog); if FOnCheckFileOnDisk(SrcLog) then begin
{$IFDEF VerboseUpdateNeeded}
DebugLn(['TLinkScanner.UpdateNeeded because file on disk changed: ',OnGetFileName(Self,SrcLog),' MainFilename=',MainFilename]);
{$ENDIF}
Include(FStates,lssFilesChanged);
exit;
end;
end; end;
end; end;
end; end;
// check initvalues
if Assigned(FOnGetInitValues) then begin
if FInitValues=nil then exit;
NewInitValues:=FOnGetInitValues(Code,NewInitValuesChangeStep);
if (NewInitValues<>nil)
and (NewInitValuesChangeStep<>FInitValuesChangeStep)
and (not FInitValues.Equals(NewInitValues)) then begin
{$IFDEF VerboseUpdateNeeded}
DebugLn(['TLinkScanner.UpdateNeeded because InitValues changed ',MainFilename]);
{$ENDIF}
exit;
end;
end;
// check missing include files // check missing include files
if MissingIncludeFilesNeedsUpdate then begin if CheckFilesOnDisk and MissingIncludeFilesNeedsUpdate then begin
{$IFDEF VerboseUpdateNeeded} {$IFDEF VerboseUpdateNeeded}
DebugLn(['TLinkScanner.UpdateNeeded because MissingIncludeFilesNeedsUpdate']); DebugLn(['TLinkScanner.UpdateNeeded because MissingIncludeFilesNeedsUpdate']);
{$ENDIF} {$ENDIF}
Include(FStates,lssFilesChanged);
exit; exit;
end; end;
// no update needed :) // no update needed :)
FForceUpdateNeeded:=false;
//DebugLn('TLinkScanner.UpdateNeeded END'); //DebugLn('TLinkScanner.UpdateNeeded END');
Result:=false; Result:=false;
end; end;
@ -3084,7 +3107,10 @@ end;
procedure TLinkScanner.SetIgnoreMissingIncludeFiles(const Value: boolean); procedure TLinkScanner.SetIgnoreMissingIncludeFiles(const Value: boolean);
begin begin
FIgnoreMissingIncludeFiles := Value; if Value then
Include(FStates,lssIgnoreMissingIncludeFiles)
else
Exclude(FStates,lssIgnoreMissingIncludeFiles);
end; end;
procedure TLinkScanner.PushIncludeLink(ACleanedPos, ASrcPos: integer; procedure TLinkScanner.PushIncludeLink(ACleanedPos, ASrcPos: integer;
@ -3499,6 +3525,11 @@ begin
FCompilerModeSwitch:=cmsDefault; FCompilerModeSwitch:=cmsDefault;
end; end;
function TLinkScanner.GetIgnoreMissingIncludeFiles: boolean;
begin
Result:=lssIgnoreMissingIncludeFiles in FStates;
end;
procedure TLinkScanner.SetCompilerModeSwitch(const AValue: TCompilerModeSwitch procedure TLinkScanner.SetCompilerModeSwitch(const AValue: TCompilerModeSwitch
); );
begin begin
@ -3791,8 +3822,6 @@ procedure TLinkScanner.DoCheckAbort;
begin begin
if not Assigned(OnProgress) then exit; if not Assigned(OnProgress) then exit;
if OnProgress(Self) then exit; if OnProgress(Self) then exit;
// mark scanning results as invalid
FForceUpdateNeeded:=true;
// raise abort exception // raise abort exception
RaiseExceptionClass('Abort',ELinkScannerAbort); RaiseExceptionClass('Abort',ELinkScannerAbort);
end; end;

View File

@ -1567,6 +1567,7 @@ Begin
// ' TextSelectedColor=',DbgS(TextSelectedColor), // ' TextSelectedColor=',DbgS(TextSelectedColor),
// ''); // '');
end; end;
debugln(['TSourceEditCompletion.ccExecute ',DbgSName(SourceEditorManager.ActiveCompletionPlugin)]);
if (CurrentCompletionType=ctIdentCompletion) and (SourceEditorManager.ActiveCompletionPlugin=nil) if (CurrentCompletionType=ctIdentCompletion) and (SourceEditorManager.ActiveCompletionPlugin=nil)
then then
StartShowCodeHelp StartShowCodeHelp

View File

@ -3,6 +3,7 @@
./runtests --format=plain --suite=TestCTScanRange ./runtests --format=plain --suite=TestCTScanRange
./runtests --format=plain --suite=TestCTScanRangeAscending ./runtests --format=plain --suite=TestCTScanRangeAscending
./runtests --format=plain --suite=TestCTScanRangeProcModified ./runtests --format=plain --suite=TestCTScanRangeProcModified
./runtests --format=plain --suite=TestCTScanRangeImplementationToEnd
} }
unit TestCTRangeScan; unit TestCTRangeScan;
@ -39,6 +40,7 @@ type
procedure TestCTScanRangeAscending; procedure TestCTScanRangeAscending;
procedure TestCTScanRangeDescending; procedure TestCTScanRangeDescending;
procedure TestCTScanRangeProcModified; procedure TestCTScanRangeProcModified;
procedure TestCTScanRangeImplementationToEnd;
end; end;
implementation implementation
@ -93,7 +95,7 @@ begin
RootNode:=Tool.Tree.Root; RootNode:=Tool.Tree.Root;
TreeChangeStep:=Tool.TreeChangeStep; TreeChangeStep:=Tool.TreeChangeStep;
AssertEquals('Step1: RootNode<>nil',true,RootNode<>nil); AssertEquals('Step1: RootNode<>nil',true,RootNode<>nil);
//Tool.WriteDebugTreeReport; Tool.WriteDebugTreeReport;
// append a comment at end and scan again => this should result in no tree change // append a comment at end and scan again => this should result in no tree change
Code.Source:=GetSource([crsfWithCommentAtEnd]); Code.Source:=GetSource([crsfWithCommentAtEnd]);
@ -213,6 +215,28 @@ begin
AssertEquals('step2: end. found',true,Tool.Tree.FindRootNode(ctnEndPoint)<>nil); AssertEquals('step2: end. found',true,Tool.Tree.FindRootNode(ctnEndPoint)<>nil);
end; end;
procedure TTestCodetoolsRangeScan.TestCTScanRangeImplementationToEnd;
var
Code: TCodeBuffer;
Tool: TEventsCodeTool;
begin
Code:=CodeToolBoss.CreateFile('TestRangeScan.pas');
Tool:=CodeToolBoss.GetCodeToolForSource(Code,false,true) as TCodeTool;
Code.Source:='';
Tool.BuildTree(lsrInit);
// scan source
Code.Source:=GetSource([crsfWithProc1]);
Tool.BuildTree(lsrImplementationStart);
Tool.WriteDebugTreeReport;
AssertEquals('step1: implementation found',true,Tool.FindImplementationNode<>nil);
Tool.BuildTree(lsrEnd);
Tool.WriteDebugTreeReport;
AssertEquals('step2: end. found',true,Tool.Tree.FindRootNode(ctnEndPoint)<>nil);
end;
initialization initialization
AddToCodetoolsTestSuite(TTestCodetoolsRangeScan); AddToCodetoolsTestSuite(TTestCodetoolsRangeScan);