mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 04:16:06 +02:00
MG: added node cache, which accelerates mass find declaration
git-svn-id: trunk@662 -
This commit is contained in:
parent
7a654795a8
commit
eb0a5dacfc
@ -469,8 +469,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
FCurCodeTool:=TCodeCompletionCodeTool(GetCodeToolForSource(MainCode,true));
|
FCurCodeTool:=TCodeCompletionCodeTool(GetCodeToolForSource(MainCode,true));
|
||||||
FCurCodeTool.ErrorPosition.Code:=nil;
|
FCurCodeTool.ErrorPosition.Code:=nil;
|
||||||
FCurCodeTool.OnSetGlobalWriteLock:=@OnToolSetWriteLock;
|
|
||||||
FCurCodeTool.OnGetGlobalWriteLockInfo:=@OnToolGetWriteLockInfo;
|
|
||||||
{$IFDEF CTDEBUG}
|
{$IFDEF CTDEBUG}
|
||||||
writeln('[TCodeToolManager.InitCurCodeTool] ',Code.Filename,' ',Code.SourceLength);
|
writeln('[TCodeToolManager.InitCurCodeTool] ',Code.Filename,' ',Code.SourceLength);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -1358,6 +1356,8 @@ begin
|
|||||||
Result.JumpCentered:=FJumpCentered;
|
Result.JumpCentered:=FJumpCentered;
|
||||||
Result.CursorBeyondEOL:=FCursorBeyondEOL;
|
Result.CursorBeyondEOL:=FCursorBeyondEOL;
|
||||||
TFindDeclarationTool(Result).OnGetCodeToolForBuffer:=@OnGetCodeToolForBuffer;
|
TFindDeclarationTool(Result).OnGetCodeToolForBuffer:=@OnGetCodeToolForBuffer;
|
||||||
|
Result.OnSetGlobalWriteLock:=@OnToolSetWriteLock;
|
||||||
|
Result.OnGetGlobalWriteLockInfo:=@OnToolGetWriteLockInfo;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TCodeToolManager.OnGetCodeToolForBuffer(Sender: TObject;
|
function TCodeToolManager.OnGetCodeToolForBuffer(Sender: TObject;
|
||||||
@ -1393,6 +1393,7 @@ procedure TCodeToolManager.OnToolGetWriteLockInfo(var WriteLockIsSet: boolean;
|
|||||||
begin
|
begin
|
||||||
WriteLockIsSet:=FWriteLockCount>0;
|
WriteLockIsSet:=FWriteLockCount>0;
|
||||||
WriteLockStep:=FWriteLockStep;
|
WriteLockStep:=FWriteLockStep;
|
||||||
|
//writeln(' FWriteLockCount=',FWriteLockCount,' FWriteLockStep=',FWriteLockStep);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCodeToolManager.OnToolSetWriteLock(Lock: boolean);
|
procedure TCodeToolManager.OnToolSetWriteLock(Lock: boolean);
|
||||||
|
@ -78,6 +78,7 @@ type
|
|||||||
ErrorPosition: TCodeXYPosition;
|
ErrorPosition: TCodeXYPosition;
|
||||||
|
|
||||||
property Scanner: TLinkScanner read FScanner write SetScanner;
|
property Scanner: TLinkScanner read FScanner write SetScanner;
|
||||||
|
function MainFilename: string;
|
||||||
|
|
||||||
function FindDeepestNodeAtPos(P: integer;
|
function FindDeepestNodeAtPos(P: integer;
|
||||||
ExceptionOnNotFound: boolean): TCodeTreeNode;
|
ExceptionOnNotFound: boolean): TCodeTreeNode;
|
||||||
@ -1481,6 +1482,14 @@ begin
|
|||||||
if Assigned(OnSetGlobalWriteLock) then OnSetGlobalWriteLock(false);
|
if Assigned(OnSetGlobalWriteLock) then OnSetGlobalWriteLock(false);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCustomCodeTool.MainFilename: string;
|
||||||
|
begin
|
||||||
|
if (Scanner<>nil) and (Scanner.MainCode<>nil) then
|
||||||
|
Result:=TCodeBuffer(Scanner.MainCode).Filename
|
||||||
|
else
|
||||||
|
Result:='(unknown mainfilename)';
|
||||||
|
end;
|
||||||
|
|
||||||
{ ECodeToolError }
|
{ ECodeToolError }
|
||||||
|
|
||||||
constructor ECodeToolError.Create(ASender: TCustomCodeTool;
|
constructor ECodeToolError.Create(ASender: TCustomCodeTool;
|
||||||
|
@ -70,30 +70,31 @@ type
|
|||||||
|
|
||||||
{
|
{
|
||||||
2. code tree node cache:
|
2. code tree node cache:
|
||||||
Some nodes (class, interface, implementation, program, type, var, const,
|
Some nodes (class, proc, record) contain a node cache. A node cache caches
|
||||||
...) contain a node
|
search results of searched identifiers for child nodes.
|
||||||
cache. A node cache caches identifier requests of direct child nodes.
|
|
||||||
Because node caches can store information of used units, the cahce must be
|
Every entry in the node cache describes the following relationship:
|
||||||
|
Identifier+Range -> Source Position
|
||||||
|
and can be interpreted as:
|
||||||
|
Identifier is a PChar to the beginning of an identifier string.
|
||||||
|
Range is a clenaed source range (CleanStartPos-CleanEndPos).
|
||||||
|
Source position is a tuple of NewTool, NewNode, NewCleanPos.
|
||||||
|
If the current context node is a child of a caching node and it is in the
|
||||||
|
range, then the result is valid. If NewNode=nil then there is no such
|
||||||
|
identifier valid at the context node.
|
||||||
|
|
||||||
|
Every node that define local identifiers contains a node cache.
|
||||||
|
These are: class, proc, record, withstatement
|
||||||
|
|
||||||
|
Because node caches can store information of used units, the cache must be
|
||||||
deleted every time a used unit is changed. Currently all node caches are
|
deleted every time a used unit is changed. Currently all node caches are
|
||||||
resetted every time the GlobalWriteLock increases.
|
resetted every time the GlobalWriteLock increases.
|
||||||
|
|
||||||
|
|
||||||
every 'cache' node get a list of
|
|
||||||
Identifier+CleanBackwardPos+CleanForwardPos -> TFindContext
|
|
||||||
This information means: if an identifier is searched at a
|
|
||||||
child node (not sub child node!) within the bounds, the cached
|
|
||||||
FindContext is valid.
|
|
||||||
'cache' nodes are:
|
|
||||||
- section nodes e.g. interface, program, ...
|
|
||||||
- class nodes
|
|
||||||
this cache must be deleted, every time the code tree changes, or
|
|
||||||
one of the used units changes.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
const
|
||||||
|
AllNodeCacheDescs = [ctnClass, ctnProcedure, ctnRecordType, ctnWithStatement];
|
||||||
|
|
||||||
|
type
|
||||||
PCodeTreeNodeCacheEntry = ^TCodeTreeNodeCacheEntry;
|
PCodeTreeNodeCacheEntry = ^TCodeTreeNodeCacheEntry;
|
||||||
TCodeTreeNodeCacheEntry = record
|
TCodeTreeNodeCacheEntry = record
|
||||||
Identifier: PChar;
|
Identifier: PChar;
|
||||||
@ -116,6 +117,8 @@ type
|
|||||||
function FindAVLNode(Identifier: PChar; CleanPos: integer): TAVLTreeNode;
|
function FindAVLNode(Identifier: PChar; CleanPos: integer): TAVLTreeNode;
|
||||||
function FindAVLNodeInRange(Identifier: PChar;
|
function FindAVLNodeInRange(Identifier: PChar;
|
||||||
CleanStartPos, CleanEndPos: integer): TAVLTreeNode;
|
CleanStartPos, CleanEndPos: integer): TAVLTreeNode;
|
||||||
|
function FindInRange(Identifier: PChar;
|
||||||
|
CleanStartPos, CleanEndPos: integer): PCodeTreeNodeCacheEntry;
|
||||||
function FindNearestAVLNode(Identifier: PChar;
|
function FindNearestAVLNode(Identifier: PChar;
|
||||||
CleanStartPos, CleanEndPos: integer; InFront: boolean): TAVLTreeNode;
|
CleanStartPos, CleanEndPos: integer; InFront: boolean): TAVLTreeNode;
|
||||||
function FindNearest(Identifier: PChar;
|
function FindNearest(Identifier: PChar;
|
||||||
@ -132,11 +135,15 @@ type
|
|||||||
procedure WriteDebugReport(const Prefix: string);
|
procedure WriteDebugReport(const Prefix: string);
|
||||||
function ConsistencyCheck: integer;
|
function ConsistencyCheck: integer;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
|
||||||
// all node types which can hold a cache
|
|
||||||
AllNodeCacheDescs = [ctnClass, ctnInterface, ctnInitialization, ctnProgram];
|
|
||||||
|
|
||||||
|
{
|
||||||
|
3. Base type node cache
|
||||||
|
|
||||||
|
ToDo:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
type
|
type
|
||||||
TGlobalIdentifierTree = class
|
TGlobalIdentifierTree = class
|
||||||
@ -473,7 +480,7 @@ end;
|
|||||||
constructor TCodeTreeNodeCache.Create(AnOwner: TCodeTreeNode);
|
constructor TCodeTreeNodeCache.Create(AnOwner: TCodeTreeNode);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
Owner:=AnOwner;
|
if AnOwner<>nil then BindToOwner(AnOwner);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TCodeTreeNodeCache.Destroy;
|
destructor TCodeTreeNodeCache.Destroy;
|
||||||
@ -652,11 +659,13 @@ var
|
|||||||
Entry: PCodeTreeNodeCacheEntry;
|
Entry: PCodeTreeNodeCacheEntry;
|
||||||
begin
|
begin
|
||||||
Result:=FindNearestAVLNode(Identifier,CleanStartPos,CleanEndPos,true);
|
Result:=FindNearestAVLNode(Identifier,CleanStartPos,CleanEndPos,true);
|
||||||
Entry:=PCodeTreeNodeCacheEntry(Result.Data);
|
if Result<>nil then begin
|
||||||
if (CleanStartPos>Entry^.CleanEndPos)
|
Entry:=PCodeTreeNodeCacheEntry(Result.Data);
|
||||||
or (CleanEndPos<Entry^.CleanStartPos) then begin
|
if (CleanStartPos>Entry^.CleanEndPos)
|
||||||
// node is not in range
|
or (CleanEndPos<Entry^.CleanStartPos) then begin
|
||||||
Result:=nil;
|
// node is not in range
|
||||||
|
Result:=nil;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -684,7 +693,6 @@ begin
|
|||||||
else begin
|
else begin
|
||||||
// cached result with identifier found
|
// cached result with identifier found
|
||||||
// -> check range
|
// -> check range
|
||||||
NextNode:=Result;
|
|
||||||
if CleanStartPos>=Entry^.CleanEndPos then begin
|
if CleanStartPos>=Entry^.CleanEndPos then begin
|
||||||
NextNode:=FItems.FindSuccessor(Result);
|
NextNode:=FItems.FindSuccessor(Result);
|
||||||
DirectionSucc:=true;
|
DirectionSucc:=true;
|
||||||
@ -698,7 +706,6 @@ begin
|
|||||||
while (NextNode<>nil) do begin
|
while (NextNode<>nil) do begin
|
||||||
Entry:=PCodeTreeNodeCacheEntry(NextNode.Data);
|
Entry:=PCodeTreeNodeCacheEntry(NextNode.Data);
|
||||||
if CompareIdentifiers(Identifier,Entry^.Identifier)<>0 then begin
|
if CompareIdentifiers(Identifier,Entry^.Identifier)<>0 then begin
|
||||||
Result:=nil;
|
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
Result:=NextNode;
|
Result:=NextNode;
|
||||||
@ -712,6 +719,7 @@ begin
|
|||||||
else
|
else
|
||||||
NextNode:=FItems.FindPrecessor(Result);
|
NextNode:=FItems.FindPrecessor(Result);
|
||||||
end;
|
end;
|
||||||
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
@ -787,6 +795,17 @@ begin
|
|||||||
Result:=nil;
|
Result:=nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TCodeTreeNodeCache.FindInRange(Identifier: PChar; CleanStartPos,
|
||||||
|
CleanEndPos: integer): PCodeTreeNodeCacheEntry;
|
||||||
|
var Node: TAVLTreeNode;
|
||||||
|
begin
|
||||||
|
Node:=FindAVLNodeInRange(Identifier,CleanStartPos,CleanEndPos);
|
||||||
|
if Node<>nil then
|
||||||
|
Result:=PCodeTreeNodeCacheEntry(Node.Data)
|
||||||
|
else
|
||||||
|
Result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TNodeCacheMemManager }
|
{ TNodeCacheMemManager }
|
||||||
|
|
||||||
procedure TNodeCacheMemManager.DisposeNode(Node: TCodeTreeNodeCache);
|
procedure TNodeCacheMemManager.DisposeNode(Node: TCodeTreeNodeCache);
|
||||||
|
@ -45,6 +45,7 @@ interface
|
|||||||
{ $DEFINE ShowExprEval}
|
{ $DEFINE ShowExprEval}
|
||||||
{ $DEFINE ShowFoundIdentifier}
|
{ $DEFINE ShowFoundIdentifier}
|
||||||
{ $DEFINE ShowCachedIdentifiers}
|
{ $DEFINE ShowCachedIdentifiers}
|
||||||
|
{ $DEFINE ShowNodeCache}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
{$IFDEF MEM_CHECK}
|
{$IFDEF MEM_CHECK}
|
||||||
@ -230,6 +231,7 @@ type
|
|||||||
FOnGetUnitSourceSearchPath: TOnGetSearchPath;
|
FOnGetUnitSourceSearchPath: TOnGetSearchPath;
|
||||||
FFirstNodeCache: TCodeTreeNodeCache;
|
FFirstNodeCache: TCodeTreeNodeCache;
|
||||||
FLastNodeCachesGlobalWriteLockStep: integer;
|
FLastNodeCachesGlobalWriteLockStep: integer;
|
||||||
|
FRootNodeCache: TCodeTreeNodeCache;
|
||||||
{$IFDEF CTDEBUG}
|
{$IFDEF CTDEBUG}
|
||||||
DebugPrefix: string;
|
DebugPrefix: string;
|
||||||
procedure IncPrefix;
|
procedure IncPrefix;
|
||||||
@ -277,6 +279,12 @@ type
|
|||||||
protected
|
protected
|
||||||
procedure DoDeleteNodes; override;
|
procedure DoDeleteNodes; override;
|
||||||
procedure ClearNodeCaches(Force: boolean);
|
procedure ClearNodeCaches(Force: boolean);
|
||||||
|
function CreateNewNodeCache(Node: TCodeTreeNode): TCodeTreeNodeCache;
|
||||||
|
function GetNodeCache(Node: TCodeTreeNode;
|
||||||
|
CreateIfNotExists: boolean): TCodeTreeNodeCache;
|
||||||
|
procedure AddResultToNodeCaches(Identifier: PChar;
|
||||||
|
StartNode, EndNode: TCodeTreeNode; SearchedForward: boolean;
|
||||||
|
Params: TFindDeclarationParams);
|
||||||
function FindDeclarationOfIdentifier(
|
function FindDeclarationOfIdentifier(
|
||||||
Params: TFindDeclarationParams): boolean;
|
Params: TFindDeclarationParams): boolean;
|
||||||
function FindContextNodeAtCursor(
|
function FindContextNodeAtCursor(
|
||||||
@ -339,7 +347,7 @@ const
|
|||||||
fdfClassPrivate];
|
fdfClassPrivate];
|
||||||
fdfGlobals = [fdfExceptionOnNotFound, fdfIgnoreUsedUnits];
|
fdfGlobals = [fdfExceptionOnNotFound, fdfIgnoreUsedUnits];
|
||||||
fdfGlobalsSameIdent = fdfGlobals+[fdfIgnoreMissingParams,fdfFirstIdentFound,
|
fdfGlobalsSameIdent = fdfGlobals+[fdfIgnoreMissingParams,fdfFirstIdentFound,
|
||||||
fdfOnlyCompatibleProc];
|
fdfOnlyCompatibleProc,fdfSearchInAncestors];
|
||||||
fdfDefaultForExpressions = [fdfSearchInParentNodes,fdfSearchInAncestors,
|
fdfDefaultForExpressions = [fdfSearchInParentNodes,fdfSearchInAncestors,
|
||||||
fdfExceptionOnNotFound]+fdfAllClassVisibilities;
|
fdfExceptionOnNotFound]+fdfAllClassVisibilities;
|
||||||
|
|
||||||
@ -430,6 +438,10 @@ writeln('TFindDeclarationTool.FindDeclaration D CursorNode=',NodeDescriptionAsSt
|
|||||||
end;
|
end;
|
||||||
if CursorNode.Desc=ctnProcedureHead then
|
if CursorNode.Desc=ctnProcedureHead then
|
||||||
CursorNode:=CursorNode.Parent;
|
CursorNode:=CursorNode.Parent;
|
||||||
|
if CursorNode.Desc=ctnProcedure then begin
|
||||||
|
BuildSubTreeForProcHead(CursorNode);
|
||||||
|
CursorNode:=FindDeepestNodeAtPos(CleanCursorPos,true);
|
||||||
|
end;
|
||||||
MoveCursorToCleanPos(CleanCursorPos);
|
MoveCursorToCleanPos(CleanCursorPos);
|
||||||
while (CurPos.StartPos>1) and (IsIdentChar[Src[CurPos.StartPos-1]]) do
|
while (CurPos.StartPos>1) and (IsIdentChar[Src[CurPos.StartPos-1]]) do
|
||||||
dec(CurPos.StartPos);
|
dec(CurPos.StartPos);
|
||||||
@ -787,40 +799,41 @@ function TFindDeclarationTool.FindIdentifierInContext(
|
|||||||
var LastContextNode, StartContextNode, ContextNode: TCodeTreeNode;
|
var LastContextNode, StartContextNode, ContextNode: TCodeTreeNode;
|
||||||
IsForward: boolean;
|
IsForward: boolean;
|
||||||
IdentifierFoundResult: TIdentifierFoundResult;
|
IdentifierFoundResult: TIdentifierFoundResult;
|
||||||
ParentsNodeCache: TCodeTreeNodeCache;
|
LastNodeCache: TCodeTreeNodeCache;
|
||||||
NearestNodeCacheEntry: PCodeTreeNodeCacheEntry;
|
LastCacheEntry: PCodeTreeNodeCacheEntry;
|
||||||
|
|
||||||
function FindInNodeCache: boolean;
|
function FindInNodeCache: boolean;
|
||||||
var Node: TCodeTreeNode;
|
var
|
||||||
|
NodeCache: TCodeTreeNodeCache;
|
||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
Node:=ContextNode.Parent;
|
NodeCache:=GetNodeCache(ContextNode,false);
|
||||||
if (Node<>nil) and (Node.Desc in [ctnClassPublic,ctnClassPrivate,
|
if (NodeCache<>LastNodeCache) then begin
|
||||||
ctnClassProtected,ctnClassPublished])
|
// NodeCache changed -> search nearest cache entry for the identifier
|
||||||
then
|
LastNodeCache:=NodeCache;
|
||||||
Node:=Node.Parent;
|
if NodeCache<>nil then begin
|
||||||
if (Node<>nil) and (Node.Cache<>nil) then begin
|
LastCacheEntry:=NodeCache.FindNearest(Params.identifier,
|
||||||
// parent node has a cache object
|
ContextNode.StartPos,ContextNode.EndPos,
|
||||||
if (Node.Cache is TCodeTreeNodeCache) then begin
|
not (fdfSearchForward in Params.Flags));
|
||||||
// parent has node cache
|
end else
|
||||||
// -> search if result already in cache
|
LastCacheEntry:=nil;
|
||||||
if ParentsNodeCache<>TCodeTreeNodeCache(Node.Cache) then begin
|
end;
|
||||||
// parent cache changed -> search new nearest node
|
if (LastCacheEntry<>nil)
|
||||||
ParentsNodeCache:=TCodeTreeNodeCache(Node.Cache);
|
and (LastCacheEntry^.CleanStartPos<ContextNode.EndPos)
|
||||||
NearestNodeCacheEntry:=ParentsNodeCache.FindNearest(
|
and (LastCacheEntry^.CleanEndPos>ContextNode.StartPos)
|
||||||
Params.Identifier,
|
then begin
|
||||||
ContextNode.StartPos,ContextNode.EndPos,
|
// cached result found
|
||||||
not (fdfSearchForward in Params.Flags));
|
Params.SetResult(LastCacheEntry);
|
||||||
end;
|
{$IFDEF ShowNodeCache}
|
||||||
if (NearestNodeCacheEntry<>nil)
|
writeln(':::: TFindDeclarationTool.FindIdentifierInContext.FindInNodeCache');
|
||||||
and (NearestNodeCacheEntry^.CleanStartPos<ContextNode.EndPos)
|
writeln(' Ident=',GetIdentifier(Params.Identifier),
|
||||||
and (NearestNodeCacheEntry^.CleanEndPos>ContextNode.StartPos) then begin
|
' ContextNode=',ContextNode.DescAsString,
|
||||||
// cached result found
|
' Self=',MainFilename);
|
||||||
Params.SetResult(NearestNodeCacheEntry);
|
if (Params.NewNode<>nil) then
|
||||||
Result:=true;
|
writeln(' NewTool=',Params.NewCodeTool.MainFilename,
|
||||||
exit;
|
' NewNode=',Params.NewNode.DescAsString);
|
||||||
end;
|
{$ENDIF}
|
||||||
end;
|
Result:=true;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -828,14 +841,13 @@ begin
|
|||||||
ContextNode:=Params.ContextNode;
|
ContextNode:=Params.ContextNode;
|
||||||
StartContextNode:=ContextNode;
|
StartContextNode:=ContextNode;
|
||||||
Result:=false;
|
Result:=false;
|
||||||
|
if ContextNode=nil then begin
|
||||||
if ContextNode<>nil then begin
|
RaiseException('[TFindDeclarationTool.FindIdentifierInContext] '
|
||||||
|
+' internal error: Params.ContextNode=nil');
|
||||||
// initialize cache search
|
end;
|
||||||
ParentsNodeCache:=nil;
|
try
|
||||||
NearestNodeCacheEntry:=nil;
|
LastNodeCache:=nil;
|
||||||
|
LastCacheEntry:=nil;
|
||||||
// search ...
|
|
||||||
repeat
|
repeat
|
||||||
{$IFDEF ShowTriedContexts}
|
{$IFDEF ShowTriedContexts}
|
||||||
writeln('[TFindDeclarationTool.FindIdentifierInContext] A Ident=',
|
writeln('[TFindDeclarationTool.FindIdentifierInContext] A Ident=',
|
||||||
@ -849,8 +861,10 @@ if (ContextNode.Desc=ctnClass) then
|
|||||||
writeln(' ContextNode.LastChild=',ContextNode.LastChild<>nil);
|
writeln(' ContextNode.LastChild=',ContextNode.LastChild<>nil);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
// search in cache
|
// search in cache
|
||||||
Result:=FindInNodeCache;
|
if FindInNodeCache then begin
|
||||||
if Result then exit;
|
Result:=(Params.NewNode<>nil);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
// search identifier in current context
|
// search identifier in current context
|
||||||
LastContextNode:=ContextNode;
|
LastContextNode:=ContextNode;
|
||||||
@ -864,6 +878,9 @@ if (ContextNode.Desc=ctnClass) then
|
|||||||
ctnRecordType, ctnRecordCase, ctnRecordVariant,
|
ctnRecordType, ctnRecordCase, ctnRecordVariant,
|
||||||
ctnParameterList:
|
ctnParameterList:
|
||||||
begin
|
begin
|
||||||
|
// these nodes build a parent-child relationship. But in pascal
|
||||||
|
// they just define a range and not a context.
|
||||||
|
// -> search in all childs
|
||||||
if ContextNode.Desc=ctnClass then begin
|
if ContextNode.Desc=ctnClass then begin
|
||||||
// just-in-time parsing for class node
|
// just-in-time parsing for class node
|
||||||
BuildSubTreeForClass(ContextNode);
|
BuildSubTreeForClass(ContextNode);
|
||||||
@ -1093,9 +1110,19 @@ writeln('[TFindDeclarationTool.FindIdentifierInContext] Searching in Parent Con
|
|||||||
until false;
|
until false;
|
||||||
end;
|
end;
|
||||||
until ContextNode=nil;
|
until ContextNode=nil;
|
||||||
end else begin
|
|
||||||
// DeepestNode=nil -> ignore
|
finally
|
||||||
|
if Result and (not (fdfDoNotCache in Params.NewFlags)) then begin
|
||||||
|
// add result to caches
|
||||||
|
AddResultToNodeCaches(Params.Identifier,StartContextNode,ContextNode,
|
||||||
|
fdfSearchForward in Params.Flags,Params);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
// if we are here, the identifier was not found
|
||||||
|
// add result to cache
|
||||||
|
AddResultToNodeCaches(Params.Identifier,StartContextNode,ContextNode,
|
||||||
|
fdfSearchForward in Params.Flags,nil);
|
||||||
|
|
||||||
if fdfExceptionOnNotFound in Params.Flags then begin
|
if fdfExceptionOnNotFound in Params.Flags then begin
|
||||||
if Params.IdentifierTool.IsPCharInSrc(Params.Identifier) then
|
if Params.IdentifierTool.IsPCharInSrc(Params.Identifier) then
|
||||||
Params.IdentifierTool.MoveCursorToCleanPos(Params.Identifier);
|
Params.IdentifierTool.MoveCursorToCleanPos(Params.Identifier);
|
||||||
@ -1593,7 +1620,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
AddNodeToStack(@NodeStack,Result.Node);
|
AddNodeToStack(@NodeStack,Result.Node);
|
||||||
{$IFDEF ShowTriedContexts}
|
{$IFDEF ShowTriedContexts}
|
||||||
writeln('[TFindDeclarationTool.FindBaseTypeOfNode] LOOP Result=',Result.Node.DescAsString);
|
writeln('[TFindDeclarationTool.FindBaseTypeOfNode] LOOP Result=',Result.Node.DescAsString,' ',HexStr(Cardinal(Result.Node),8));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if (Result.Node.Desc in AllIdentifierDefinitions) then begin
|
if (Result.Node.Desc in AllIdentifierDefinitions) then begin
|
||||||
// instead of variable/const/type definition, return the type
|
// instead of variable/const/type definition, return the type
|
||||||
@ -1603,10 +1630,12 @@ writeln('[TFindDeclarationTool.FindBaseTypeOfNode] LOOP Result=',Result.Node.Des
|
|||||||
and ((Result.Node.SubDesc and ctnsForwardDeclaration)>0) then
|
and ((Result.Node.SubDesc and ctnsForwardDeclaration)>0) then
|
||||||
begin
|
begin
|
||||||
// search the real class
|
// search the real class
|
||||||
|
{$IFDEF ShowTriedContexts}
|
||||||
|
writeln('[TFindDeclarationTool.FindBaseTypeOfNode] Class is forward');
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
// ToDo: check for circles in ancestor chain
|
// ToDo: check for circles in ancestor chain
|
||||||
|
|
||||||
|
|
||||||
ClassIdentNode:=Result.Node.Parent;
|
ClassIdentNode:=Result.Node.Parent;
|
||||||
if (ClassIdentNode=nil) or (not (ClassIdentNode.Desc=ctnTypeDefinition))
|
if (ClassIdentNode=nil) or (not (ClassIdentNode.Desc=ctnTypeDefinition))
|
||||||
then begin
|
then begin
|
||||||
@ -1619,7 +1648,8 @@ writeln('[TFindDeclarationTool.FindBaseTypeOfNode] LOOP Result=',Result.Node.Des
|
|||||||
Params.SetIdentifier(Self,@Src[ClassIdentNode.StartPos],
|
Params.SetIdentifier(Self,@Src[ClassIdentNode.StartPos],
|
||||||
@CheckSrcIdentifier);
|
@CheckSrcIdentifier);
|
||||||
Params.Flags:=[fdfSearchInParentNodes,fdfSearchForward,
|
Params.Flags:=[fdfSearchInParentNodes,fdfSearchForward,
|
||||||
fdfIgnoreUsedUnits,fdfExceptionOnNotFound]
|
fdfIgnoreUsedUnits,fdfExceptionOnNotFound,
|
||||||
|
fdfIgnoreCurContextNode]
|
||||||
+(fdfGlobals*Params.Flags);
|
+(fdfGlobals*Params.Flags);
|
||||||
Params.ContextNode:=ClassIdentNode;
|
Params.ContextNode:=ClassIdentNode;
|
||||||
FindIdentifierInContext(Params);
|
FindIdentifierInContext(Params);
|
||||||
@ -2434,6 +2464,7 @@ writeln(DebugPrefix,'TFindDeclarationTool.FindIdentifierInInterface',
|
|||||||
// ToDo: build codetree for ppu, ppw, dcu files
|
// ToDo: build codetree for ppu, ppw, dcu files
|
||||||
|
|
||||||
// build tree for pascal source
|
// build tree for pascal source
|
||||||
|
ClearNodeCaches(false);
|
||||||
BuildTree(true);
|
BuildTree(true);
|
||||||
|
|
||||||
// search identifier in cache
|
// search identifier in cache
|
||||||
@ -3112,6 +3143,7 @@ writeln('[TFindDeclarationTool.CheckSrcIdentifier]',
|
|||||||
Params.IdentifierTool.ReadNextAtom;
|
Params.IdentifierTool.ReadNextAtom;
|
||||||
ExprInputList:=Params.IdentifierTool.CreateParamExprList(
|
ExprInputList:=Params.IdentifierTool.CreateParamExprList(
|
||||||
Params.IdentifierTool.CurPos.EndPos,Params);
|
Params.IdentifierTool.CurPos.EndPos,Params);
|
||||||
|
Params.Load(OldInput);
|
||||||
// create compatibility lists
|
// create compatibility lists
|
||||||
CompListSize:=SizeOf(TTypeCompatibility)*ExprInputList.Count;
|
CompListSize:=SizeOf(TTypeCompatibility)*ExprInputList.Count;
|
||||||
if CompListSize>0 then begin
|
if CompListSize>0 then begin
|
||||||
@ -3121,7 +3153,6 @@ writeln('[TFindDeclarationTool.CheckSrcIdentifier]',
|
|||||||
BestCompatibilityList:=nil;
|
BestCompatibilityList:=nil;
|
||||||
CurCompatibilityList:=nil;
|
CurCompatibilityList:=nil;
|
||||||
end;
|
end;
|
||||||
Params.Load(OldInput);
|
|
||||||
try
|
try
|
||||||
Include(Params.Flags,fdfFirstIdentFound);
|
Include(Params.Flags,fdfFirstIdentFound);
|
||||||
// check the first proc for compatibility
|
// check the first proc for compatibility
|
||||||
@ -3550,7 +3581,7 @@ begin
|
|||||||
exit;
|
exit;
|
||||||
end else begin
|
end else begin
|
||||||
// this is the first check in this GlobalWriteLockStep
|
// this is the first check in this GlobalWriteLockStep
|
||||||
FLastNodecachesGlobalWriteLockStep:=GlobalWriteLockStep;
|
FLastNodeCachesGlobalWriteLockStep:=GlobalWriteLockStep;
|
||||||
// proceed normally ...
|
// proceed normally ...
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -3561,6 +3592,10 @@ begin
|
|||||||
FFirstNodeCache:=NodeCache.Next;
|
FFirstNodeCache:=NodeCache.Next;
|
||||||
NodeCacheMemManager.DisposeNode(NodeCache);
|
NodeCacheMemManager.DisposeNode(NodeCache);
|
||||||
end;
|
end;
|
||||||
|
if FRootNodeCache<>nil then begin
|
||||||
|
NodeCacheMemManager.DisposeNode(FRootNodeCache);
|
||||||
|
FRootNodeCache:=nil;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFindDeclarationTool.ConsistencyCheck: integer;
|
function TFindDeclarationTool.ConsistencyCheck: integer;
|
||||||
@ -3588,6 +3623,102 @@ begin
|
|||||||
ClearNodeCaches(false);
|
ClearNodeCaches(false);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFindDeclarationTool.GetNodeCache(Node: TCodeTreeNode;
|
||||||
|
CreateIfNotExists: boolean): TCodeTreeNodeCache;
|
||||||
|
begin
|
||||||
|
while (Node<>nil) and (not (Node.Desc in AllNodeCacheDescs)) do
|
||||||
|
Node:=Node.Parent;
|
||||||
|
if Node<>nil then begin
|
||||||
|
if (Node.Cache=nil) and CreateIfNotExists then
|
||||||
|
CreateNewNodeCache(Node);
|
||||||
|
if (Node.Cache<>nil) and (Node.Cache is TCodeTreeNodeCache) then
|
||||||
|
Result:=TCodeTreeNodeCache(Node.Cache)
|
||||||
|
else
|
||||||
|
Result:=nil;
|
||||||
|
end else begin
|
||||||
|
if (FRootNodeCache=nil) and CreateIfNotExists then
|
||||||
|
FRootNodeCache:=CreateNewNodeCache(nil);
|
||||||
|
Result:=FRootNodeCache;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TFindDeclarationTool.AddResultToNodeCaches(Identifier: PChar;
|
||||||
|
StartNode, EndNode: TCodeTreeNode; SearchedForward: boolean;
|
||||||
|
Params: TFindDeclarationParams);
|
||||||
|
var Node: TCodeTreeNode;
|
||||||
|
CurNodeCache, LastNodeCache: TCodeTreeNodeCache;
|
||||||
|
CleanStartPos, CleanEndPos: integer;
|
||||||
|
NewNode: TCodeTreeNode;
|
||||||
|
NewTool: TPascalParserTool;
|
||||||
|
NewCleanPos: integer;
|
||||||
|
begin
|
||||||
|
{$IFDEF ShowNodeCache}
|
||||||
|
write('TFindDeclarationTool.AddResultToNodeCaches ',
|
||||||
|
' Ident=',GetIdentifier(Identifier),
|
||||||
|
' StartNode=',StartNode.DescAsString,'="',copy(Src,StartNode.StartPos,12),'"');
|
||||||
|
if EndNode<>nil then
|
||||||
|
write(' EndNode=',EndNode.DescAsString,'="',copy(Src,EndNode.StartPos,12),'"')
|
||||||
|
else
|
||||||
|
write(' EndNode=nil');
|
||||||
|
write(' SearchedForward=',SearchedForward);
|
||||||
|
writeln('');
|
||||||
|
writeln(' Self=',MainFilename);
|
||||||
|
if Params<>nil then begin
|
||||||
|
writeln(' NewNode=',Params.NewNode.DescAsString,
|
||||||
|
' NewTool=',Params.NewCodeTool.MainFilename);
|
||||||
|
end else begin
|
||||||
|
writeln(' NOT FOUND');
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
Node:=StartNode;
|
||||||
|
LastNodeCache:=nil;
|
||||||
|
if Params<>nil then begin
|
||||||
|
NewNode:=Params.NewNode;
|
||||||
|
NewTool:=Params.NewCodeTool;
|
||||||
|
NewCleanPos:=Params.NewCleanPos;
|
||||||
|
end else begin
|
||||||
|
NewNode:=nil;
|
||||||
|
NewTool:=nil;
|
||||||
|
end;
|
||||||
|
CleanStartPos:=StartNode.StartPos;
|
||||||
|
CleanEndPos:=StartNode.EndPos;
|
||||||
|
if EndNode<>nil then begin
|
||||||
|
if EndNode.StartPos<CleanStartPos then
|
||||||
|
CleanStartPos:=EndNode.StartPos;
|
||||||
|
if EndNode.EndPos>CleanEndPos then
|
||||||
|
CleanEndPos:=EndNode.EndPos;
|
||||||
|
end else begin
|
||||||
|
if not SearchedForward then
|
||||||
|
CleanStartPos:=1
|
||||||
|
else
|
||||||
|
CleanEndPos:=SrcLen+1;
|
||||||
|
end;
|
||||||
|
while (Node<>nil) do begin
|
||||||
|
if (Node.Desc in AllNodeCacheDescs) then begin
|
||||||
|
if (Node.Cache=nil) then
|
||||||
|
CreateNewNodeCache(Node);
|
||||||
|
if (Node.Cache is TCodeTreeNodeCache) then begin
|
||||||
|
CurNodeCache:=TCodeTreeNodeCache(Node.Cache);
|
||||||
|
if LastNodeCache<>CurNodeCache then begin
|
||||||
|
CurNodeCache.Add(Identifier,CleanStartPos,CleanEndPos,
|
||||||
|
NewNode,NewTool,NewCleanPos);
|
||||||
|
LastNodeCache:=CurNodeCache;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Node:=Node.Parent;
|
||||||
|
if (EndNode<>nil) and (Node=EndNode.Parent) then break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TFindDeclarationTool.CreateNewNodeCache(
|
||||||
|
Node: TCodeTreeNode): TCodeTreeNodeCache;
|
||||||
|
begin
|
||||||
|
Result:=TCodeTreeNodeCache.Create(Node);
|
||||||
|
Result.Next:=FFirstNodeCache;
|
||||||
|
FFirstNodeCache:=Result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{ TFindDeclarationParams }
|
{ TFindDeclarationParams }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user