codetools: simplified gathering helpers, patch #28794 from Ondrej Pokorny

git-svn-id: trunk@49991 -
This commit is contained in:
mattias 2015-10-08 10:09:12 +00:00
parent 3cabc3eba0
commit bd020c787f
2 changed files with 244 additions and 242 deletions

View File

@ -560,7 +560,6 @@ begin
end; end;
Params:=TFindDeclarationParams.Create(Self,ContextNode); Params:=TFindDeclarationParams.Create(Self,ContextNode);
try try
FindHelpersInContext(Params);
Params.SetIdentifier(Self,@TypeName[1],nil); Params.SetIdentifier(Self,@TypeName[1],nil);
Params.Flags:=[fdfExceptionOnNotFound,fdfSearchInParentNodes]; Params.Flags:=[fdfExceptionOnNotFound,fdfSearchInParentNodes];
//DebugLn(['TEventsCodeTool.FindMethodTypeInfo TypeName=',TypeName,' MainFilename=',MainFilename]); //DebugLn(['TEventsCodeTool.FindMethodTypeInfo TypeName=',TypeName,' MainFilename=',MainFilename]);

View File

@ -2524,234 +2524,236 @@ begin
Result:=false; Result:=false;
ActivateGlobalWriteLock; ActivateGlobalWriteLock;
InitCollectIdentifiers(CursorPos,IdentifierList);
IdentStartXY:=FindIdentifierStartPos(CursorPos);
if CheckCursorInCompilerDirective(IdentStartXY) then exit(true);
ParseSourceTillCollectionStart(IdentStartXY,CleanCursorPos,CursorNode,
IdentStartPos,IdentEndPos);
Params:=TFindDeclarationParams.Create(Self,CursorNode);
try try
FindHelpersInContext(Params); InitCollectIdentifiers(CursorPos,IdentifierList);
if CleanCursorPos=0 then ; IdentStartXY:=FindIdentifierStartPos(CursorPos);
if IdentStartPos>0 then begin if CheckCursorInCompilerDirective(IdentStartXY) then exit(true);
MoveCursorToCleanPos(IdentStartPos);
ReadNextAtom;
CurrentIdentifierList.StartAtom:=CurPos;
end;
// find context ParseSourceTillCollectionStart(IdentStartXY,CleanCursorPos,CursorNode,
{$IFDEF CTDEBUG} IdentStartPos,IdentEndPos);
DebugLn('TIdentCompletionTool.GatherIdentifiers B', Params:=TFindDeclarationParams.Create(Self,CursorNode);
' CleanCursorPos=',CleanPosToStr(CleanCursorPos), try
' IdentStartPos=',CleanPosToStr(IdentStartPos),' IdentEndPos=',CleanPosToStr(IdentEndPos), if CleanCursorPos=0 then ;
' Ident=',copy(Src,IdentStartPos,IdentEndPos-IdentStartPos)); if IdentStartPos>0 then begin
{$ENDIF} MoveCursorToCleanPos(IdentStartPos);
GatherContext:=CreateFindContext(Self,CursorNode);
CurrentIdentifierList.NewMemberVisibility:=GetClassVisibility(CursorNode);
if CursorNode.Desc in [ctnUsesSection,ctnUseUnit] then begin
GatherUnitNames;
MoveCursorToCleanPos(IdentEndPos);
ReadNextAtom;
if (CurPos.Flag=cafWord) and (not UpAtomIs('IN')) then begin
// add comma
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsEndComma];
end;
end else if (CursorNode.Desc in AllSourceTypes)
and (PositionsInSameLine(Src,CursorNode.StartPos,IdentStartPos)) then begin
GatherSourceNames(GatherContext);
end else begin
FindCollectionContext(Params,IdentStartPos,CursorNode,
ExprType,ContextExprStartPos,StartInSubContext);
GatherContext := ExprType.Context;
// find class and ancestors if existing (needed for protected identifiers)
if GatherContext.Tool = Self then
FindContextClassAndAncestors(IdentStartXY, FICTClassAndAncestors);
CursorContext:=CreateFindContext(Self,CursorNode);
GatherContextKeywords(CursorContext,IdentStartPos,Beautifier);
// check for incomplete context
// context bracket level
CurrentIdentifierList.StartBracketLvl:=
GetBracketLvl(Src,CursorNode.StartPos,IdentStartPos,
Scanner.NestedComments);
if CursorNode.Desc in AllPascalStatements then begin
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartInStatement];
end;
// context in front of
StartPosOfVariable:=FindStartOfTerm(IdentStartPos,NodeTermInType(CursorNode));
if StartPosOfVariable>0 then begin
if StartPosOfVariable=IdentStartPos then begin
// cursor is at start of an operand
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartOfOperand];
end else begin
MoveCursorToCleanPos(IdentStartPos);
ReadPriorAtom;
if CurPos.Flag=cafPoint then
// cursor is behind a point
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartIsSubIdent];
end;
MoveCursorToCleanPos(StartPosOfVariable);
ReadPriorAtom;
CurrentIdentifierList.StartAtomInFront:=CurPos;
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags)
then begin
// check if LValue
if (CurPos.Flag in [cafSemicolon,cafEnd,cafColon])
or UpAtomIs('BEGIN')
or UpAtomIs('TRY') or UpAtomIs('FINALLY') or UpAtomIs('EXCEPT')
or UpAtomIs('FOR') or UpAtomIs('DO') or UpAtomIs('THEN')
or UpAtomIs('REPEAT') or UpAtomIs('ASM') or UpAtomIs('ELSE')
then begin
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartOfStatement];
end;
// check if expression
if UpAtomIs('IF') or UpAtomIs('CASE') or UpAtomIs('WHILE')
or UpAtomIs('UNTIL')
then begin
// todo: check at start of expression, not only in front of variable
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfIsExpression, ilcfDontAllowProcedures];
end;
// check if procedure is allowed
if CurPos.Flag in [cafComma, cafRoundBracketOpen, cafEdgedBracketOpen, cafEqual, cafOtherOperator] then
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfDontAllowProcedures];
end;
end;
// context behind
if (IdentEndPos<SrcLen) then begin
MoveCursorToCleanPos(IdentEndPos);
//debugln(['TIdentCompletionTool.GatherIdentifiers "',dbgstr(Src,IdentStartPos,IdentEndPos-IdentStartPos),'"']);
InFrontOfDirective:=(CurPos.StartPos<SrcLen) and (Src[CurPos.StartPos]='{')
and (Src[CurPos.StartPos+1]='$');
ReadNextAtom; ReadNextAtom;
CurrentIdentifierList.StartAtom:=CurPos;
end;
// check end of line // find context
if (not InFrontOfDirective) {$IFDEF CTDEBUG}
and (CursorPos.Code.LineColIsOutside(CursorPos.Y,CursorPos.X) DebugLn('TIdentCompletionTool.GatherIdentifiers B',
or (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos))) ' CleanCursorPos=',CleanPosToStr(CleanCursorPos),
then ' IdentStartPos=',CleanPosToStr(IdentStartPos),' IdentEndPos=',CleanPosToStr(IdentEndPos),
' Ident=',copy(Src,IdentStartPos,IdentEndPos-IdentStartPos));
{$ENDIF}
GatherContext:=CreateFindContext(Self,CursorNode);
CurrentIdentifierList.NewMemberVisibility:=GetClassVisibility(CursorNode);
if CursorNode.Desc in [ctnUsesSection,ctnUseUnit] then begin
GatherUnitNames;
MoveCursorToCleanPos(IdentEndPos);
ReadNextAtom;
if (CurPos.Flag=cafWord) and (not UpAtomIs('IN')) then begin
// add comma
CurrentIdentifierList.ContextFlags:= CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfEndOfLine]; CurrentIdentifierList.ContextFlags+[ilcfNeedsEndComma];
CurrentIdentifierList.StartAtomBehind:=CurPos;
// check if a semicolon is needed or forbidden at the end
if InFrontOfDirective
or (CurrentIdentifierList.StartBracketLvl>0)
or (CurPos.Flag in [cafSemicolon, cafEqual, cafColon, cafComma,
cafPoint, cafRoundBracketOpen, cafRoundBracketClose,
cafEdgedBracketOpen, cafEdgedBracketClose])
or ((CurPos.Flag in [cafWord,cafNone])
and (UpAtomIs('ELSE')
or UpAtomIs('THEN')
or UpAtomIs('DO')
or UpAtomIs('TO')
or UpAtomIs('OF')
or WordIsBinaryOperator.DoItCaseInsensitive(Src,
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos)))
then begin
// do not add semicolon
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNoEndSemicolon];
end; end;
// check if in statement end else if (CursorNode.Desc in AllSourceTypes)
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags) then and (PositionsInSameLine(Src,CursorNode.StartPos,IdentStartPos)) then begin
begin GatherSourceNames(GatherContext);
// check if a semicolon is needed at the end end else begin
if (not (ilcfNoEndSemicolon in CurrentIdentifierList.ContextFlags)) FindCollectionContext(Params,IdentStartPos,CursorNode,
then begin ExprType,ContextExprStartPos,StartInSubContext);
// check if a semicolon is needed at the end
if (CurPos.Flag in [cafEnd]) GatherContext := ExprType.Context;
or WordIsBlockKeyWord.DoItCaseInsensitive(Src, // find class and ancestors if existing (needed for protected identifiers)
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos) if GatherContext.Tool = Self then
or ((CurPos.Flag=cafWord) FindContextClassAndAncestors(IdentStartXY, FICTClassAndAncestors);
and (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos)))
then begin CursorContext:=CreateFindContext(Self,CursorNode);
// add semicolon GatherContextKeywords(CursorContext,IdentStartPos,Beautifier);
// check for incomplete context
// context bracket level
CurrentIdentifierList.StartBracketLvl:=
GetBracketLvl(Src,CursorNode.StartPos,IdentStartPos,
Scanner.NestedComments);
if CursorNode.Desc in AllPascalStatements then begin
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartInStatement];
end;
// context in front of
StartPosOfVariable:=FindStartOfTerm(IdentStartPos,NodeTermInType(CursorNode));
if StartPosOfVariable>0 then begin
if StartPosOfVariable=IdentStartPos then begin
// cursor is at start of an operand
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartOfOperand];
end else begin
MoveCursorToCleanPos(IdentStartPos);
ReadPriorAtom;
if CurPos.Flag=cafPoint then
// cursor is behind a point
CurrentIdentifierList.ContextFlags:= CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsEndSemicolon]; CurrentIdentifierList.ContextFlags+[ilcfStartIsSubIdent];
end;
MoveCursorToCleanPos(StartPosOfVariable);
ReadPriorAtom;
CurrentIdentifierList.StartAtomInFront:=CurPos;
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags)
then begin
// check if LValue
if (CurPos.Flag in [cafSemicolon,cafEnd,cafColon])
or UpAtomIs('BEGIN')
or UpAtomIs('TRY') or UpAtomIs('FINALLY') or UpAtomIs('EXCEPT')
or UpAtomIs('FOR') or UpAtomIs('DO') or UpAtomIs('THEN')
or UpAtomIs('REPEAT') or UpAtomIs('ASM') or UpAtomIs('ELSE')
then begin
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfStartOfStatement];
end;
// check if expression
if UpAtomIs('IF') or UpAtomIs('CASE') or UpAtomIs('WHILE')
or UpAtomIs('UNTIL')
then begin
// todo: check at start of expression, not only in front of variable
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfIsExpression, ilcfDontAllowProcedures];
end;
// check if procedure is allowed
if CurPos.Flag in [cafComma, cafRoundBracketOpen, cafEdgedBracketOpen, cafEqual, cafOtherOperator] then
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfDontAllowProcedures];
end;
end;
// context behind
if (IdentEndPos<SrcLen) then begin
MoveCursorToCleanPos(IdentEndPos);
//debugln(['TIdentCompletionTool.GatherIdentifiers "',dbgstr(Src,IdentStartPos,IdentEndPos-IdentStartPos),'"']);
InFrontOfDirective:=(CurPos.StartPos<SrcLen) and (Src[CurPos.StartPos]='{')
and (Src[CurPos.StartPos+1]='$');
ReadNextAtom;
// check end of line
if (not InFrontOfDirective)
and (CursorPos.Code.LineColIsOutside(CursorPos.Y,CursorPos.X)
or (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos)))
then
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfEndOfLine];
CurrentIdentifierList.StartAtomBehind:=CurPos;
// check if a semicolon is needed or forbidden at the end
if InFrontOfDirective
or (CurrentIdentifierList.StartBracketLvl>0)
or (CurPos.Flag in [cafSemicolon, cafEqual, cafColon, cafComma,
cafPoint, cafRoundBracketOpen, cafRoundBracketClose,
cafEdgedBracketOpen, cafEdgedBracketClose])
or ((CurPos.Flag in [cafWord,cafNone])
and (UpAtomIs('ELSE')
or UpAtomIs('THEN')
or UpAtomIs('DO')
or UpAtomIs('TO')
or UpAtomIs('OF')
or WordIsBinaryOperator.DoItCaseInsensitive(Src,
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos)))
then begin
// do not add semicolon
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNoEndSemicolon];
end;
// check if in statement
if (ilcfStartInStatement in CurrentIdentifierList.ContextFlags) then
begin
// check if a semicolon is needed at the end
if (not (ilcfNoEndSemicolon in CurrentIdentifierList.ContextFlags))
then begin
// check if a semicolon is needed at the end
if (CurPos.Flag in [cafEnd])
or WordIsBlockKeyWord.DoItCaseInsensitive(Src,
CurPos.StartPos,CurPos.EndPos-CurPos.StartPos)
or ((CurPos.Flag=cafWord)
and (not PositionsInSameLine(Src,IdentEndPos,CurPos.StartPos)))
then begin
// add semicolon
CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsEndSemicolon];
end;
end; end;
end; end;
end; // check missing 'do' after 'with'
// check missing 'do' after 'with' if CurrentIdentifierList.StartUpAtomInFrontIs('WITH')
if CurrentIdentifierList.StartUpAtomInFrontIs('WITH') and (not CurrentIdentifierList.StartUpAtomBehindIs('DO'))
and (not CurrentIdentifierList.StartUpAtomBehindIs('DO')) and (CurrentIdentifierList.StartBracketLvl=0)
and (CurrentIdentifierList.StartBracketLvl=0) and (not (CurrentIdentifierList.StartAtomBehind.Flag in
and (not (CurrentIdentifierList.StartAtomBehind.Flag in [cafComma,cafPoint,cafRoundBracketOpen,cafEdgedBracketOpen]))
[cafComma,cafPoint,cafRoundBracketOpen,cafEdgedBracketOpen])) and (not CurrentIdentifierList.StartUpAtomBehindIs('^'))
and (not CurrentIdentifierList.StartUpAtomBehindIs('^')) then
then CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsDo];
end else begin
// end of source
CurrentIdentifierList.ContextFlags:= CurrentIdentifierList.ContextFlags:=
CurrentIdentifierList.ContextFlags+[ilcfNeedsDo]; CurrentIdentifierList.ContextFlags+[ilcfEndOfLine];
end else begin end;
// end of source
CurrentIdentifierList.ContextFlags:= // search and gather identifiers in context
CurrentIdentifierList.ContextFlags+[ilcfEndOfLine]; if (GatherContext.Tool<>nil) and (GatherContext.Node<>nil) then begin
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers D CONTEXT: ',
GatherContext.Tool.MainFilename,
' ',GatherContext.Node.DescAsString,
' "',StringToPascalConst(copy(GatherContext.Tool.Src,GatherContext.Node.StartPos,50)),'"');
{$ENDIF}
// gather all identifiers in context
Params.ContextNode:=GatherContext.Node;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
if (Params.ContextNode.Desc=ctnInterface) and StartInSubContext then
Include(Params.Flags,fdfIgnoreUsedUnits);
if not StartInSubContext then
Include(Params.Flags,fdfSearchInParentNodes);
if Params.ContextNode.Desc in AllClasses then
Exclude(Params.Flags,fdfSearchInParentNodes);
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers F');
{$ENDIF}
CurrentIdentifierList.Context:=GatherContext;
if GatherContext.Node.Desc=ctnIdentifier then
Params.Flags:=Params.Flags+[fdfIgnoreCurContextNode];
GatherContext.Tool.FindIdentifierInContext(Params);
end else
if ExprType.Desc in xtAllIdentPredefinedTypes then
begin
// gather all identifiers in cursor context for basic types (strings etc.)
Params.ContextNode:=CursorNode;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
CurrentIdentifierList.Context:=GatherContext;
FindIdentifierInBasicTypeHelpers(ExprType.Desc, Params);
end;
// check for procedure/method declaration context
CheckProcedureDeclarationContext;
// add useful identifiers
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers G');
{$ENDIF}
GatherUsefulIdentifiers(IdentStartPos,CursorContext,GatherContext);
end; end;
// search and gather identifiers in context Result:=true;
if (GatherContext.Tool<>nil) and (GatherContext.Node<>nil) then begin finally
{$IFDEF CTDEBUG} FreeListOfPFindContext(FICTClassAndAncestors);
DebugLn('TIdentCompletionTool.GatherIdentifiers D CONTEXT: ', FreeAndNil(FIDCTFoundPublicProperties);
GatherContext.Tool.MainFilename, Params.Free;
' ',GatherContext.Node.DescAsString, ClearIgnoreErrorAfter;
' "',StringToPascalConst(copy(GatherContext.Tool.Src,GatherContext.Node.StartPos,50)),'"');
{$ENDIF}
// gather all identifiers in context
Params.ContextNode:=GatherContext.Node;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
if (Params.ContextNode.Desc=ctnInterface) and StartInSubContext then
Include(Params.Flags,fdfIgnoreUsedUnits);
if not StartInSubContext then
Include(Params.Flags,fdfSearchInParentNodes);
if Params.ContextNode.Desc in AllClasses then
Exclude(Params.Flags,fdfSearchInParentNodes);
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers F');
{$ENDIF}
CurrentIdentifierList.Context:=GatherContext;
if GatherContext.Node.Desc=ctnIdentifier then
Params.Flags:=Params.Flags+[fdfIgnoreCurContextNode];
GatherContext.Tool.FindIdentifierInContext(Params);
end else
if ExprType.Desc in xtAllIdentPredefinedTypes then
begin
// gather all identifiers in cursor context for basic types (strings etc.)
Params.ContextNode:=CursorNode;
Params.SetIdentifier(Self,nil,@CollectAllIdentifiers);
Params.Flags:=[fdfSearchInAncestors,fdfCollect,fdfFindVariable,fdfSearchInHelpers];
CurrentIdentifierList.Context:=GatherContext;
FindIdentifierInBasicTypeHelpers(ExprType.Desc, Params);
end;
// check for procedure/method declaration context
CheckProcedureDeclarationContext;
// add useful identifiers
{$IFDEF CTDEBUG}
DebugLn('TIdentCompletionTool.GatherIdentifiers G');
{$ENDIF}
GatherUsefulIdentifiers(IdentStartPos,CursorContext,GatherContext);
end; end;
Result:=true;
finally finally
FreeListOfPFindContext(FICTClassAndAncestors);
FreeAndNil(FIDCTFoundPublicProperties);
Params.Free;
ClearIgnoreErrorAfter;
DeactivateGlobalWriteLock; DeactivateGlobalWriteLock;
CurrentIdentifierList:=nil; CurrentIdentifierList:=nil;
end; end;
@ -2937,43 +2939,44 @@ begin
CurrentIdentifierContexts:=CodeContexts; CurrentIdentifierContexts:=CodeContexts;
ActivateGlobalWriteLock; ActivateGlobalWriteLock;
Params:=TFindDeclarationParams.Create;//FindHelpersInContext called later
try try
InitCollectIdentifiers(CursorPos,IdentifierList); InitCollectIdentifiers(CursorPos,IdentifierList);
ParseSourceTillCollectionStart(CursorPos,CleanCursorPos,CursorNode, ParseSourceTillCollectionStart(CursorPos,CleanCursorPos,CursorNode,
IdentStartPos,IdentEndPos); IdentStartPos,IdentEndPos);
Params.ContextNode:=CursorNode; Params:=TFindDeclarationParams.Create(Self, CursorNode);
FindHelpersInContext(Params); try
if IdentStartPos=0 then ; if IdentStartPos=0 then ;
if IdentEndPos=0 then ; if IdentEndPos=0 then ;
// find class and ancestors if existing (needed for protected identifiers) // find class and ancestors if existing (needed for protected identifiers)
FindContextClassAndAncestors(CursorPos,FICTClassAndAncestors); FindContextClassAndAncestors(CursorPos,FICTClassAndAncestors);
if CursorNode<>nil then begin if CursorNode<>nil then begin
if not CheckContextIsParameter(Result) then begin if not CheckContextIsParameter(Result) then begin
DebugLn(['TIdentCompletionTool.FindCodeContext cursor not at parameter']); DebugLn(['TIdentCompletionTool.FindCodeContext cursor not at parameter']);
exit; exit;
end;
end; end;
end;
if CurrentIdentifierContexts=nil then begin if CurrentIdentifierContexts=nil then begin
// create default // create default
AddCollectionContext(Self,CursorNode); AddCollectionContext(Self,CursorNode);
end; end;
Result:=true; Result:=true;
finally
if Result then begin
CodeContexts:=CurrentIdentifierContexts;
CurrentIdentifierContexts:=nil;
end else begin
FreeAndNil(CurrentIdentifierContexts);
end;
FreeListOfPFindContext(FICTClassAndAncestors);
FreeAndNil(FIDCTFoundPublicProperties);
Params.Free;
ClearIgnoreErrorAfter;
end;
finally finally
if Result then begin
CodeContexts:=CurrentIdentifierContexts;
CurrentIdentifierContexts:=nil;
end else begin
FreeAndNil(CurrentIdentifierContexts);
end;
FreeListOfPFindContext(FICTClassAndAncestors);
FreeAndNil(FIDCTFoundPublicProperties);
Params.Free;
ClearIgnoreErrorAfter;
DeactivateGlobalWriteLock; DeactivateGlobalWriteLock;
FreeAndNil(CurrentIdentifierList); FreeAndNil(CurrentIdentifierList);
end; end;