codetools: fixed search in ancestor and search ancestor

git-svn-id: trunk@48317 -
This commit is contained in:
mattias 2015-03-12 23:11:19 +00:00
parent aa474f5750
commit d48e548ada

View File

@ -2754,6 +2754,7 @@ var
LastCacheEntry: PCodeTreeNodeCacheEntry; LastCacheEntry: PCodeTreeNodeCacheEntry;
SearchRangeFlags: TNodeCacheEntryFlags; SearchRangeFlags: TNodeCacheEntryFlags;
NodeCacheEntryFlags: TNodeCacheEntryFlags; NodeCacheEntryFlags: TNodeCacheEntryFlags;
Flags: TFindDeclarationFlags;
procedure InitNodesAndCacheAccess; procedure InitNodesAndCacheAccess;
@ -2773,16 +2774,17 @@ var
FirstSearchedNode:=nil; FirstSearchedNode:=nil;
LastSearchedNode:=nil; LastSearchedNode:=nil;
SearchRangeFlags:=[]; SearchRangeFlags:=[];
if fdfSearchInParentNodes in Params.Flags then Flags:=Params.Flags;
if fdfSearchInParentNodes in Flags then
Include(SearchRangeFlags,ncefSearchedInParents); Include(SearchRangeFlags,ncefSearchedInParents);
if fdfSearchInAncestors in Params.Flags then if fdfSearchInAncestors in Flags then
Include(SearchRangeFlags,ncefSearchedInAncestors); Include(SearchRangeFlags,ncefSearchedInAncestors);
LastNodeCache:=nil; LastNodeCache:=nil;
LastCacheEntry:=nil; LastCacheEntry:=nil;
NodeCacheEntryFlags:=[]; NodeCacheEntryFlags:=[];
if fdfSearchInParentNodes in Params.Flags then if fdfSearchInParentNodes in Flags then
Include(NodeCacheEntryFlags,ncefSearchedInParents); Include(NodeCacheEntryFlags,ncefSearchedInParents);
if fdfSearchInAncestors in Params.Flags then if fdfSearchInAncestors in Flags then
Include(NodeCacheEntryFlags,ncefSearchedInAncestors); Include(NodeCacheEntryFlags,ncefSearchedInAncestors);
end; end;
@ -2792,7 +2794,7 @@ var
begin begin
Result:=false; Result:=false;
// the node cache is identifier based // the node cache is identifier based
if ([fdfCollect,fdfExtractOperand]*Params.Flags<>[]) then exit; if ([fdfCollect,fdfExtractOperand]*Flags<>[]) then exit;
NodeCache:=GetNodeCache(ContextNode,false); NodeCache:=GetNodeCache(ContextNode,false);
if (NodeCache<>LastNodeCache) then begin if (NodeCache<>LastNodeCache) then begin
@ -2801,7 +2803,7 @@ var
if NodeCache<>nil then begin if NodeCache<>nil then begin
LastCacheEntry:=NodeCache.FindNearest(Params.Identifier, LastCacheEntry:=NodeCache.FindNearest(Params.Identifier,
ContextNode.StartPos,ContextNode.EndPos, ContextNode.StartPos,ContextNode.EndPos,
not (fdfSearchForward in Params.Flags)); not (fdfSearchForward in Flags));
end else end else
LastCacheEntry:=nil; LastCacheEntry:=nil;
end; end;
@ -2842,7 +2844,7 @@ var
if not Found then exit; if not Found then exit;
FindIdentifierInContext:=true; FindIdentifierInContext:=true;
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then if fdfCollect in Flags then
raise Exception.Create('fdfCollect must never return true'); raise Exception.Create('fdfCollect must never return true');
{$ENDIF} {$ENDIF}
{$IFDEF ShowFoundIdentifier} {$IFDEF ShowFoundIdentifier}
@ -2850,7 +2852,7 @@ var
Params.WriteDebugReport; Params.WriteDebugReport;
{$ENDIF} {$ENDIF}
if (FirstSearchedNode=nil) then exit; if (FirstSearchedNode=nil) then exit;
if ([fdfDoNotCache,fdfCollect,fdfExtractOperand]*Params.Flags<>[]) then exit; if ([fdfDoNotCache,fdfCollect,fdfExtractOperand]*Flags<>[]) then exit;
if ([fodDoNotCache]*Params.NewFlags<>[]) then exit; if ([fodDoNotCache]*Params.NewFlags<>[]) then exit;
if (Params.OnIdentifierFound<>@CheckSrcIdentifier) then exit; if (Params.OnIdentifierFound<>@CheckSrcIdentifier) then exit;
if (Params.FoundProc<>nil) then exit; // do not cache proc searches if (Params.FoundProc<>nil) then exit; // do not cache proc searches
@ -2864,7 +2866,7 @@ var
exit; exit;
end; end;
AddResultToNodeCaches(FirstSearchedNode,EndNode, AddResultToNodeCaches(FirstSearchedNode,EndNode,
fdfSearchForward in Params.Flags,Params,SearchRangeFlags); fdfSearchForward in Flags,Params,SearchRangeFlags);
end; end;
function CheckResult(NewResult, CallOnIdentifierFound: boolean): boolean; function CheckResult(NewResult, CallOnIdentifierFound: boolean): boolean;
@ -2890,13 +2892,13 @@ var
var IdentFoundResult: TIdentifierFoundResult; var IdentFoundResult: TIdentifierFoundResult;
begin begin
Result:=true; Result:=true;
FindIdentifierInContext:=NewResult and (not (fdfCollect in Params.Flags)); FindIdentifierInContext:=NewResult and (not (fdfCollect in Flags));
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then begin if fdfCollect in Flags then begin
DebugLn('[TFindDeclarationTool.FindIdentifierInContext.CheckResult] COLLECT CheckResult Ident=', DebugLn('[TFindDeclarationTool.FindIdentifierInContext.CheckResult] COLLECT CheckResult Ident=',
'"',GetIdentifier(Params.Identifier),'"', '"',GetIdentifier(Params.Identifier),'"',
' File="',ExtractFilename(MainFilename)+'"', ' File="',ExtractFilename(MainFilename)+'"',
' Flags=[',dbgs(Params.Flags)+']', ' Flags=[',dbgs(Flags)+']',
' NewResult=',DbgS(NewResult), ' NewResult=',DbgS(NewResult),
' CallOnIdentifierFound=',DbgS(CallOnIdentifierFound)); ' CallOnIdentifierFound=',DbgS(CallOnIdentifierFound));
end; end;
@ -2908,14 +2910,14 @@ var
Params.WriteDebugReport; Params.WriteDebugReport;
{$ENDIF} {$ENDIF}
if fdfExtractOperand in Params.Flags then if fdfExtractOperand in Flags then
case Params.NewNode.Desc of case Params.NewNode.Desc of
ctnVarDefinition, ctnConstDefinition: ctnVarDefinition, ctnConstDefinition:
with Params do with Params do
AddOperandPart(GetIdentifier(@NewCodeTool.Src[NewNode.StartPos])); AddOperandPart(GetIdentifier(@NewCodeTool.Src[NewNode.StartPos]));
ctnProperty,ctnGlobalProperty: ctnProperty,ctnGlobalProperty:
begin begin
if fdfPropertyResolving in Params.Flags then begin if fdfPropertyResolving in Flags then begin
if not PropNodeIsTypeLess(Params.NewNode) if not PropNodeIsTypeLess(Params.NewNode)
and ReadTilGetterOfProperty(Params.NewNode) then begin and ReadTilGetterOfProperty(Params.NewNode) then begin
// continue searching of getter // continue searching of getter
@ -2935,7 +2937,7 @@ var
'"',GetIdentifier(Params.Identifier),'"', '"',GetIdentifier(Params.Identifier),'"',
' StartContext="',StartContextNode.DescAsString,'" "',copy(Src,StartContextNode.StartPos,20),'"', ' StartContext="',StartContextNode.DescAsString,'" "',copy(Src,StartContextNode.StartPos,20),'"',
' File="',ExtractFilename(MainFilename)+'"', ' File="',ExtractFilename(MainFilename)+'"',
' Flags=[',dbgs(Params.Flags),']' ' Flags=[',dbgs(Flags),']'
]);} ]);}
IdentFoundResult:=Params.NewCodeTool.DoOnIdentifierFound(Params, IdentFoundResult:=Params.NewCodeTool.DoOnIdentifierFound(Params,
@ -2948,7 +2950,7 @@ var
Result:=IdentFoundResult<>ifrProceedSearch; Result:=IdentFoundResult<>ifrProceedSearch;
if IdentFoundResult<>ifrAbortSearch then exit; if IdentFoundResult<>ifrAbortSearch then exit;
end else begin end else begin
if fdfCollect in Params.Flags then if fdfCollect in Flags then
Result:=false; Result:=false;
CacheResult(true,ContextNode); CacheResult(true,ContextNode);
exit; exit;
@ -2966,7 +2968,7 @@ var
end; end;
FindIdentifierInContext:=true; FindIdentifierInContext:=true;
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then if fdfCollect in Flags then
raise Exception.Create('fdfCollect must never return true'); raise Exception.Create('fdfCollect must never return true');
{$ENDIF} {$ENDIF}
Params.SetResult(Params.FoundProc^.Context.Tool, Params.SetResult(Params.FoundProc^.Context.Tool,
@ -2978,9 +2980,9 @@ var
exit; exit;
end; end;
// identifier was not found // identifier was not found
if not (fdfExceptionOnNotFound in Params.Flags) then exit; if not (fdfExceptionOnNotFound in Flags) then exit;
if (Params.Identifier<>nil) if (Params.Identifier<>nil)
and not (fdfExceptionOnPredefinedIdent in Params.Flags) and not (fdfExceptionOnPredefinedIdent in Flags)
and WordIsPredefinedIdentifier.DoItCaseInsensitive(Params.Identifier) and WordIsPredefinedIdentifier.DoItCaseInsensitive(Params.Identifier)
then begin then begin
Params.SetResult(nil,nil); Params.SetResult(nil,nil);
@ -2996,7 +2998,7 @@ var
procedure MoveContextNodeToChildren; procedure MoveContextNodeToChildren;
begin begin
if (ContextNode.LastChild<>nil) then begin if (ContextNode.LastChild<>nil) then begin
if not (fdfSearchForward in Params.Flags) then begin if not (fdfSearchForward in Flags) then begin
RaiseLastErrorIfInFrontOfCleanedPos(ContextNode.EndPos); RaiseLastErrorIfInFrontOfCleanedPos(ContextNode.EndPos);
ContextNode:=ContextNode.LastChild; ContextNode:=ContextNode.LastChild;
end else end else
@ -3015,7 +3017,7 @@ var
if (Node=nil) or (Node.Desc<>ctnGenericParams) then exit; if (Node=nil) or (Node.Desc<>ctnGenericParams) then exit;
Node:=Node.FirstChild; Node:=Node.FirstChild;
while Node<>nil do begin while Node<>nil do begin
if (fdfCollect in Params.Flags) if (fdfCollect in Flags)
or CompareSrcIdentifiers(Node.StartPos,Params.Identifier) or CompareSrcIdentifiers(Node.StartPos,Params.Identifier)
then begin then begin
{$IFDEF ShowTriedIdentifiers} {$IFDEF ShowTriedIdentifiers}
@ -3024,7 +3026,7 @@ var
// identifier found // identifier found
Params.SetResult(Self,Node); Params.SetResult(Self,Node);
Result:=CheckResult(true,true); Result:=CheckResult(true,true);
if not (fdfCollect in Params.Flags) then if not (fdfCollect in Flags) then
exit; exit;
end; end;
Node:=Node.NextBrother; Node:=Node.NextBrother;
@ -3052,7 +3054,7 @@ var
if NameNode=nil then exit; if NameNode=nil then exit;
end; end;
if (fdfCollect in Params.Flags) if (fdfCollect in Flags)
or CompareSrcIdentifiers(NameNode.StartPos,Params.Identifier) or CompareSrcIdentifiers(NameNode.StartPos,Params.Identifier)
then begin then begin
{$IFDEF ShowTriedIdentifiers} {$IFDEF ShowTriedIdentifiers}
@ -3061,8 +3063,8 @@ var
// identifier found // identifier found
Params.SetResult(Self,ContextNode); Params.SetResult(Self,ContextNode);
Result:=CheckResult(true,true); Result:=CheckResult(true,true);
if not (fdfCollect in Params.Flags) then begin if not (fdfCollect in Flags) then begin
if (fdfSkipClassForward in Params.Flags) if (fdfSkipClassForward in Flags)
and (ContextNode.FirstChild<>nil) and (ContextNode.FirstChild<>nil)
and (ContextNode.FirstChild.Desc in AllClasses) and (ContextNode.FirstChild.Desc in AllClasses)
and ((ctnsForwardDeclaration and ContextNode.FirstChild.SubDesc)<>0) and ((ctnsForwardDeclaration and ContextNode.FirstChild.SubDesc)<>0)
@ -3099,7 +3101,7 @@ var
// false if search should continue // false if search should continue
begin begin
Result:=false; Result:=false;
if (fdfCollect in Params.Flags) if (fdfCollect in Flags)
or CompareSrcIdentifiers(ContextNode.StartPos,Params.Identifier) or CompareSrcIdentifiers(ContextNode.StartPos,Params.Identifier)
then begin then begin
{$IFDEF ShowTriedIdentifiers} {$IFDEF ShowTriedIdentifiers}
@ -3108,7 +3110,7 @@ var
// identifier found // identifier found
Params.SetResult(Self,ContextNode); Params.SetResult(Self,ContextNode);
Result:=CheckResult(true,true); Result:=CheckResult(true,true);
if not (fdfCollect in Params.Flags) then begin if not (fdfCollect in Flags) then begin
exit; exit;
end; end;
end; end;
@ -3119,7 +3121,7 @@ var
Result:=false; Result:=false;
if ContextNode.FirstChild=nil then exit; if ContextNode.FirstChild=nil then exit;
//debugln('SearchInOnBlockDefinition B ',GetIdentifier(@Src[ContextNode.StartPos])); //debugln('SearchInOnBlockDefinition B ',GetIdentifier(@Src[ContextNode.StartPos]));
if (fdfCollect in Params.Flags) if (fdfCollect in Flags)
or CompareSrcIdentifiers(ContextNode.FirstChild.StartPos,Params.Identifier) or CompareSrcIdentifiers(ContextNode.FirstChild.StartPos,Params.Identifier)
then begin then begin
{$IFDEF ShowTriedIdentifiers} {$IFDEF ShowTriedIdentifiers}
@ -3128,7 +3130,7 @@ var
// identifier found // identifier found
Params.SetResult(Self,ContextNode.FirstChild); Params.SetResult(Self,ContextNode.FirstChild);
Result:=CheckResult(true,true); Result:=CheckResult(true,true);
if not (fdfCollect in Params.Flags) then if not (fdfCollect in Flags) then
exit; exit;
end; end;
end; end;
@ -3145,17 +3147,17 @@ var
ReadNextAtom; // read keyword ReadNextAtom; // read keyword
if (SrcNode.Desc=ctnProgram) and (not UpAtomIs('PROGRAM')) then exit; if (SrcNode.Desc=ctnProgram) and (not UpAtomIs('PROGRAM')) then exit;
ReadNextAtom; // read name ReadNextAtom; // read name
if (fdfCollect in Params.Flags) if (fdfCollect in Flags)
or CompareSrcIdentifiers(CurPos.StartPos,Params.Identifier) then or CompareSrcIdentifiers(CurPos.StartPos,Params.Identifier) then
begin begin
// identifier found // identifier found
{$IFDEF ShowTriedIdentifiers} {$IFDEF ShowTriedIdentifiers}
if not (fdfCollect in Params.Flags) then if not (fdfCollect in Flags) then
DebugLn(' Source Name Identifier found="',GetIdentifier(Params.Identifier),'"'); DebugLn(' Source Name Identifier found="',GetIdentifier(Params.Identifier),'"');
{$ENDIF} {$ENDIF}
Params.SetResult(Self,SrcNode,CurPos.StartPos); Params.SetResult(Self,SrcNode,CurPos.StartPos);
Result:=CheckResult(true,true); Result:=CheckResult(true,true);
if not (fdfCollect in Params.Flags) then if not (fdfCollect in Flags) then
exit; exit;
end; end;
end; end;
@ -3165,7 +3167,7 @@ var
Result:=false; Result:=false;
if SearchInSourceName then if SearchInSourceName then
exit(true); exit(true);
if (not (fdfIgnoreUsedUnits in Params.Flags)) if (not (fdfIgnoreUsedUnits in Flags))
and FindIdentifierInHiddenUsedUnits(Params) then begin and FindIdentifierInHiddenUsedUnits(Params) then begin
Result:=CheckResult(true,false); Result:=CheckResult(true,false);
end; end;
@ -3177,13 +3179,13 @@ var
// false if search should continue // false if search should continue
begin begin
Result:=false; Result:=false;
if (fdfCollect in Params.Flags) if (fdfCollect in Flags)
or (Params.Identifier[0]<>'[') then begin or (Params.Identifier[0]<>'[') then begin
MoveCursorToNodeStart(ContextNode); MoveCursorToNodeStart(ContextNode);
ReadNextAtom; // read keyword 'property' ReadNextAtom; // read keyword 'property'
if UpAtomIs('CLASS') then ReadNextAtom; if UpAtomIs('CLASS') then ReadNextAtom;
ReadNextAtom; // read name ReadNextAtom; // read name
if (fdfCollect in Params.Flags) if (fdfCollect in Flags)
or CompareSrcIdentifiers(CurPos.StartPos,Params.Identifier) then begin or CompareSrcIdentifiers(CurPos.StartPos,Params.Identifier) then begin
// identifier found // identifier found
{$IFDEF ShowTriedIdentifiers} {$IFDEF ShowTriedIdentifiers}
@ -3206,9 +3208,9 @@ var
Result:=true; Result:=true;
if (not ContextNode.HasAsParent(StartContextNode)) then begin if (not ContextNode.HasAsParent(StartContextNode)) then begin
// searching in a prior node, will leave the start context // searching in a prior node, will leave the start context
if (not (fdfSearchInParentNodes in Params.Flags)) then begin if (not (fdfSearchInParentNodes in Flags)) then begin
// searching in any parent context is not permitted // searching in any parent context is not permitted
if not ((fdfSearchInAncestors in Params.Flags) if not ((fdfSearchInAncestors in Flags)
and (ContextNode.Desc in AllClasses)) then begin and (ContextNode.Desc in AllClasses)) then begin
// even searching in ancestors contexts is not permitted // even searching in ancestors contexts is not permitted
// -> there is no prior context accessible any more // -> there is no prior context accessible any more
@ -3246,7 +3248,7 @@ var
if SearchInGenericParams(ContextNode.Parent) then begin if SearchInGenericParams(ContextNode.Parent) then begin
FindIdentifierInContext:=true; FindIdentifierInContext:=true;
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then if fdfCollect in Flags then
raise Exception.Create('fdfCollect must never return true'); raise Exception.Create('fdfCollect must never return true');
{$ENDIF} {$ENDIF}
exit(AbortNoCacheResult); exit(AbortNoCacheResult);
@ -3254,7 +3256,7 @@ var
end; end;
if (ContextNode.Desc in (AllClasses-[ctnRecordType])) then begin if (ContextNode.Desc in (AllClasses-[ctnRecordType])) then begin
if (fdfSearchInAncestors in Params.Flags) then begin if (fdfSearchInAncestors in Flags) then begin
// after searching in a class definition, search in its ancestors // after searching in a class definition, search in its ancestors
// ToDo: check for cycles in ancestors // ToDo: check for cycles in ancestors
@ -3265,7 +3267,7 @@ var
if Result then begin if Result then begin
FindIdentifierInContext:=true; FindIdentifierInContext:=true;
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then if fdfCollect in Flags then
raise Exception.Create('fdfCollect must never return true'); raise Exception.Create('fdfCollect must never return true');
{$ENDIF} {$ENDIF}
exit(AbortNoCacheResult); exit(AbortNoCacheResult);
@ -3273,24 +3275,29 @@ var
end; end;
// if this was a nested class, the identifier can be in the ancestors // if this was a nested class, the identifier can be in the ancestors
// of the enclosing class // of the enclosing class
Params.Flags:=Params.Flags+[fdfSearchInAncestors]; Flags:=Flags+[fdfSearchInAncestors];
end else if ContextNode.Desc=ctnClassInheritance then begin
if (StartContextNode=ContextNode)
or StartContextNode.HasAsParent(ContextNode) then
// searching an ancestor => don't search within ancestors
Exclude(Flags,fdfSearchInAncestors);
end; end;
if (ContextNode=StartContextNode) if (ContextNode=StartContextNode)
and (not (fdfSearchInParentNodes in Params.Flags)) then begin and (not (fdfSearchInParentNodes in Flags)) then begin
// startcontext completed => not searching in parents or ancestors // startcontext completed => not searching in parents or ancestors
ContextNode:=nil; ContextNode:=nil;
exit(Proceed); exit(Proceed);
end; end;
if ((not (fdfSearchForward in Params.Flags)) if ((not (fdfSearchForward in Flags))
and (ContextNode.PriorBrother<>nil)) and (ContextNode.PriorBrother<>nil))
or ((fdfSearchForward in Params.Flags) or ((fdfSearchForward in Flags)
and (ContextNode.NextBrother<>nil) and (ContextNode.NextBrother<>nil)
and (ContextNode.NextBrother.Desc<>ctnImplementation)) then and (ContextNode.NextBrother.Desc<>ctnImplementation)) then
begin begin
// search next in prior/next brother // search next in prior/next brother
if not (fdfSearchForward in Params.Flags) then if not (fdfSearchForward in Flags) then
ContextNode:=ContextNode.PriorBrother ContextNode:=ContextNode.PriorBrother
else begin else begin
RaiseLastErrorIfInFrontOfCleanedPos(ContextNode.NextBrother.EndPos); RaiseLastErrorIfInFrontOfCleanedPos(ContextNode.NextBrother.EndPos);
@ -3332,7 +3339,7 @@ var
break; break;
end; end;
end else if (ContextNode.Parent<>nil) end else if (ContextNode.Parent<>nil)
and ((fdfSearchInParentNodes in Params.Flags) and ((fdfSearchInParentNodes in Flags)
or (ContextNode.HasAsParent(StartContextNode))) then or (ContextNode.HasAsParent(StartContextNode))) then
begin begin
// search next in parent // search next in parent
@ -3383,7 +3390,7 @@ var
if Result then begin if Result then begin
FindIdentifierInContext:=true; FindIdentifierInContext:=true;
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then if fdfCollect in Flags then
raise Exception.Create('fdfCollect must never return true'); raise Exception.Create('fdfCollect must never return true');
{$ENDIF} {$ENDIF}
exit(AbortNoCacheResult); exit(AbortNoCacheResult);
@ -3410,23 +3417,23 @@ begin
'"'+GetIdentifier(Params.Identifier)+'"', '"'+GetIdentifier(Params.Identifier)+'"',
' Context="'+ContextNode.DescAsString+'" "'+StringToPascalConst(copy(Src,ContextNode.StartPos,20)),'"', ' Context="'+ContextNode.DescAsString+'" "'+StringToPascalConst(copy(Src,ContextNode.StartPos,20)),'"',
' at '+CleanPosToStr(ContextNode.StartPos,true), ' at '+CleanPosToStr(ContextNode.StartPos,true),
' Flags=['+dbgs(Params.Flags)+']' ' Flags=['+dbgs(Flags)+']'
); );
{$ELSE} {$ELSE}
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then begin if fdfCollect in Flags then begin
DebugLn(['[TFindDeclarationTool.FindIdentifierInContext] COLLECT Start Ident=', DebugLn(['[TFindDeclarationTool.FindIdentifierInContext] COLLECT Start Ident=',
'"',GetIdentifier(Params.Identifier),'"', '"',GetIdentifier(Params.Identifier),'"',
' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"', ' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"',
' at '+CleanPosToStr(ContextNode.StartPos,true), ' at '+CleanPosToStr(ContextNode.StartPos,true),
' Flags=[',dbgs(Params.Flags),']' ' Flags=[',dbgs(Flags),']'
]); ]);
end; end;
{$ENDIF} {$ENDIF}
{$ENDIF} {$ENDIF}
if (ContextNode.Desc=ctnInterface) if (ContextNode.Desc=ctnInterface)
and (fdfIgnoreUsedUnits in Params.Flags) then begin and (fdfIgnoreUsedUnits in Flags) then begin
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedContexts}
DebugLn(['TFindDeclarationTool.FindIdentifierInContext searching in interface of ',MainFilename]); DebugLn(['TFindDeclarationTool.FindIdentifierInContext searching in interface of ',MainFilename]);
{$ENDIF} {$ENDIF}
@ -3442,22 +3449,22 @@ begin
DebugLn('[TFindDeclarationTool.FindIdentifierInContext] Loop Ident=', DebugLn('[TFindDeclarationTool.FindIdentifierInContext] Loop Ident=',
'"',GetIdentifier(Params.Identifier),'"', '"',GetIdentifier(Params.Identifier),'"',
' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"', ' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"',
' Flags=[',dbgs(Params.Flags),']' ' Flags=[',dbgs(Flags),']'
); );
{$ELSE} {$ELSE}
{$IFDEF ShowCollect} {$IFDEF ShowCollect}
if fdfCollect in Params.Flags then begin if fdfCollect in Flags then begin
DebugLn('[TFindDeclarationTool.FindIdentifierInContext] COLLECT Loop Ident=', DebugLn('[TFindDeclarationTool.FindIdentifierInContext] COLLECT Loop Ident=',
'"',GetIdentifier(Params.Identifier),'"', '"',GetIdentifier(Params.Identifier),'"',
' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"', ' Context="',ContextNode.DescAsString,'" "',copy(Src,ContextNode.StartPos,20),'"',
' Flags=[',dbgs(Params.Flags),']' ' Flags=[',dbgs(Flags),']'
); );
end; end;
{$ENDIF} {$ENDIF}
{$ENDIF} {$ENDIF}
// search identifier in current context // search identifier in current context
LastContextNode:=ContextNode; LastContextNode:=ContextNode;
if not (fdfIgnoreCurContextNode in Params.Flags) then begin if not (fdfIgnoreCurContextNode in Flags) then begin
// search in cache // search in cache
if FindInNodeCache then begin if FindInNodeCache then begin
if CheckResult(Params.NewNode<>nil,Params.NewNode<>nil) then if CheckResult(Params.NewNode<>nil,Params.NewNode<>nil) then
@ -3484,9 +3491,6 @@ begin
// -> search in all children // -> search in all children
MoveContextNodeToChildren; MoveContextNodeToChildren;
ctnClassInheritance:
Params.Flags:=Params.Flags-[fdfSearchInAncestors];
ctnTypeDefinition, ctnVarDefinition, ctnConstDefinition, ctnTypeDefinition, ctnVarDefinition, ctnConstDefinition,
ctnGenericType, ctnGlobalProperty: ctnGenericType, ctnGlobalProperty:
if SearchInTypeVarConstGlobPropDefinition then exit; if SearchInTypeVarConstGlobPropDefinition then exit;
@ -3561,6 +3565,7 @@ begin
end; end;
end else begin end else begin
Exclude(Params.Flags,fdfIgnoreCurContextNode); Exclude(Params.Flags,fdfIgnoreCurContextNode);
Exclude(Flags,fdfIgnoreCurContextNode);
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedContexts}
DebugLn('[TFindDeclarationTool.FindIdentifierInContext] IgnoreCurContext '); DebugLn('[TFindDeclarationTool.FindIdentifierInContext] IgnoreCurContext ');
{$ENDIF} {$ENDIF}
@ -3586,12 +3591,12 @@ begin
end;} end;}
// if we are here, the identifier was not found and there was no error // if we are here, the identifier was not found and there was no error
if (FirstSearchedNode<>nil) and (Params.FoundProc=nil) if (FirstSearchedNode<>nil) and (Params.FoundProc=nil)
and ([fdfCollect,fdfExtractOperand]*Params.Flags=[]) then begin and ([fdfCollect,fdfExtractOperand]*Flags=[]) then begin
// add result to cache // add result to cache
Params.NewNode:=nil; Params.NewNode:=nil;
Params.NewCodeTool:=nil; Params.NewCodeTool:=nil;
AddResultToNodeCaches(FirstSearchedNode,LastSearchedNode, AddResultToNodeCaches(FirstSearchedNode,LastSearchedNode,
fdfSearchForward in Params.Flags,Params,SearchRangeFlags); fdfSearchForward in Flags,Params,SearchRangeFlags);
end; end;
CheckResult(false,false); CheckResult(false,false);
end; end;
@ -5797,6 +5802,14 @@ var
AncestorStartPos: LongInt; AncestorStartPos: LongInt;
ExprType: TExpressionType; ExprType: TExpressionType;
Params: TFindDeclarationParams; Params: TFindDeclarationParams;
procedure RaiseExpected(const Expected: string);
begin
MoveCursorToCleanPos(AncestorStartPos);
ReadNextAtom;
RaiseExceptionFmt(ctsStrExpectedButAtomFound,[Expected,ExtractNode(IdentifierNode,[])]);
end;
begin begin
{$IFDEF CheckNodeTool}CheckNodeTool(IdentifierNode);{$ENDIF} {$IFDEF CheckNodeTool}CheckNodeTool(IdentifierNode);{$ENDIF}
if (IdentifierNode=nil) if (IdentifierNode=nil)
@ -5829,7 +5842,7 @@ begin
Params:=TFindDeclarationParams.Create; Params:=TFindDeclarationParams.Create;
try try
Params.Flags:=fdfDefaultForExpressions-[fdfSearchInAncestors]; Params.Flags:=fdfDefaultForExpressions-[fdfSearchInAncestors];
Params.ContextNode:=InheritanceNode; Params.ContextNode:=IdentifierNode;
if CurPos.Flag in [cafRoundBracketClose,cafComma] then begin if CurPos.Flag in [cafRoundBracketClose,cafComma] then begin
// simple identifier // simple identifier
{$IFDEF ShowTriedContexts} {$IFDEF ShowTriedContexts}
@ -5847,47 +5860,41 @@ begin
DebugLn(['[TFindDeclarationTool.FindAncestorOfClass] ', DebugLn(['[TFindDeclarationTool.FindAncestorOfClass] ',
' search complex ancestor class = "',ExtractNode(IdentifierNode,[]),'" for class "',ExtractClassName(ClassNode,false),'"']); ' search complex ancestor class = "',ExtractNode(IdentifierNode,[]),'" for class "',ExtractClassName(ClassNode,false),'"']);
{$ENDIF} {$ENDIF}
Params.Flags:=fdfDefaultForExpressions-[fdfSearchInAncestors]; if not FindClassContext then
Params.Flags:=Params.Flags+[fdfFindVariable];
ExprType:=FindExpressionTypeOfTerm(IdentifierNode.StartPos,IdentifierNode.EndPos,Params,false); ExprType:=FindExpressionTypeOfTerm(IdentifierNode.StartPos,IdentifierNode.EndPos,Params,false);
if ExprType.Desc=xtContext then if ExprType.Desc<>xtContext then
AncestorContext:=ExprType.Context RaiseExpected('type');
else AncestorContext:=ExprType.Context
AncestorContext:=CleanFindContext;
end; end;
finally finally
Params.Free; Params.Free;
end; end;
// check result
if (AncestorContext.Node=nil)
or (not (AncestorContext.Node.Desc in [ctnTypeDefinition,ctnGenericType])) then
begin
MoveCursorToCleanPos(AncestorStartPos);
ReadNextAtom;
RaiseExceptionFmt(ctsStrExpectedButAtomFound,['type',GetAtom]);
end;
// search ancestor class context
if FindClassContext then begin if FindClassContext then begin
Params:=TFindDeclarationParams.Create; // search ancestor class context
try if (AncestorContext.Node.Desc in [ctnTypeDefinition,ctnGenericType]) then
Params.Flags:=fdfDefaultForExpressions+[fdfFindChildren]; begin
AncestorContext:=AncestorContext.Tool.FindBaseTypeOfNode(Params,AncestorContext.Node); Params:=TFindDeclarationParams.Create;
try
// check result Params.Flags:=fdfDefaultForExpressions+[fdfFindChildren];
if not (AncestorContext.Node.Desc in AllClasses) then begin AncestorContext:=AncestorContext.Tool.FindBaseTypeOfNode(Params,AncestorContext.Node);
MoveCursorToCleanPos(AncestorStartPos); finally
ReadNextAtom; Params.Free;
RaiseExceptionFmt(ctsStrExpectedButAtomFound,['class',GetAtom]);
end; end;
if AncestorContext.Node=ClassNode then begin
MoveCursorToCleanPos(AncestorStartPos);
ReadNextAtom;
RaiseException('cycle detected');
end;
finally
Params.Free;
end; end;
// check result
if not (AncestorContext.Node.Desc in AllClasses) then
RaiseExpected('class');
if AncestorContext.Node=ClassNode then begin
MoveCursorToCleanPos(AncestorStartPos);
ReadNextAtom;
RaiseException('cycle detected');
end;
end else begin
// check if class identifier
if (not (AncestorContext.Node.Desc in [ctnTypeDefinition,ctnGenericType])) then
RaiseExpected('type');
end; end;
ResultParams.SetResult(AncestorContext); ResultParams.SetResult(AncestorContext);
@ -6076,7 +6083,7 @@ function TFindDeclarationTool.FindIdentifierInAncestors(
begin begin
Params.Save(OldInput); Params.Save(OldInput);
Params.ContextNode:=AncestorClassNode; Params.ContextNode:=AncestorClassNode;
Params.Flags:=Params.Flags-[fdfIgnoreCurContextNode,fdfSearchInParentNodes]; Params.Flags:=Params.Flags-[fdfIgnoreCurContextNode,fdfSearchInParentNodes]+[fdfSearchInAncestors];
Result:=AncestorTool.FindIdentifierInContext(Params); Result:=AncestorTool.FindIdentifierInContext(Params);
Params.Load(OldInput,true); Params.Load(OldInput,true);
end; end;