From 3e5a744e2d9546e86f56647c3e4a51fe244e2dca Mon Sep 17 00:00:00 2001 From: mattias Date: Tue, 5 May 2009 18:02:20 +0000 Subject: [PATCH] codetools: find declaratuion: added flag to skip forward class git-svn-id: trunk@19814 - --- components/codetools/codetoolmanager.pas | 12 ++- components/codetools/customcodetool.pas | 21 ----- components/codetools/finddeclarationtool.pas | 92 +++++++++++++++++--- components/codetools/identcompletiontool.pas | 12 +-- components/codetools/stdcodetools.pas | 2 +- ide/main.pp | 8 +- 6 files changed, 101 insertions(+), 46 deletions(-) diff --git a/components/codetools/codetoolmanager.pas b/components/codetools/codetoolmanager.pas index aedace2f04..fe2109be00 100644 --- a/components/codetools/codetoolmanager.pas +++ b/components/codetools/codetoolmanager.pas @@ -364,7 +364,8 @@ type // find declaration function FindDeclaration(Code: TCodeBuffer; X,Y: integer; out NewCode: TCodeBuffer; - out NewX, NewY, NewTopLine: integer): boolean; + out NewX, NewY, NewTopLine: integer; + Flags: TFindSmartFlags = DefaultFindSmartFlags): boolean; function FindDeclarationOfIdentifier(Code: TCodeBuffer; X,Y: integer; Identifier: PChar; out NewCode: TCodeBuffer; @@ -1708,10 +1709,13 @@ end; function TCodeToolManager.FindDeclaration(Code: TCodeBuffer; X,Y: integer; out NewCode: TCodeBuffer; - out NewX, NewY, NewTopLine: integer): boolean; + out NewX, NewY, NewTopLine: integer; + Flags: TFindSmartFlags): boolean; var CursorPos: TCodeXYPosition; NewPos: TCodeXYPosition; + NewTool: TFindDeclarationTool; + NewNode: TCodeTreeNode; begin Result:=false; {$IFDEF CTDEBUG} @@ -1729,11 +1733,13 @@ begin DebugLn('TCodeToolManager.FindDeclaration NOT HANDLING EXCEPTIONS'); RaiseUnhandableExceptions:=true; {$ENDIF} - Result:=FCurCodeTool.FindDeclaration(CursorPos,NewPos,NewTopLine); + Result:=FCurCodeTool.FindDeclaration(CursorPos,Flags,NewTool,NewNode, + NewPos,NewTopLine); if Result then begin NewX:=NewPos.X; NewY:=NewPos.Y; NewCode:=NewPos.Code; + if (NewTool=nil) and (NewNode<>nil) then ; {$IFDEF CTDEBUG} debugln(['TCodeToolManager.FindDeclaration ',DbgsCXY(NewPos)]); {$ENDIF} diff --git a/components/codetools/customcodetool.pas b/components/codetools/customcodetool.pas index 35b8506d54..a6d9de6856 100644 --- a/components/codetools/customcodetool.pas +++ b/components/codetools/customcodetool.pas @@ -277,8 +277,6 @@ type const AnUpperIdent: string): integer; function CompareSrcIdentifiers( CleanStartPos1, CleanStartPos2: integer): boolean; - function CompareSrcIdentifier(CleanStartPos: integer; - const Identifier: string): boolean; function CompareSrcIdentifiers(Identifier1, Identifier2: PChar): boolean; function CompareSrcIdentifiers(CleanStartPos: integer; AnIdentifier: PChar): boolean; @@ -2453,25 +2451,6 @@ begin {$ENDIF} end; -function TCustomCodeTool.CompareSrcIdentifier(CleanStartPos: integer; - const Identifier: string): boolean; -var IdentPos, Len: integer; -begin - Result:=false; - Len:=length(Identifier); - if (CleanStartPos<1) or (CleanStartPos>SrcLen-Len+1) or (Identifier='') then - exit; - IdentPos:=1; - while (IdentPos<=Len) and (IsIdentChar[Src[CleanStartPos]]) do begin - if UpChars[Identifier[IdentPos]]<>UpperSrc[CleanStartPos] then - exit; - inc(IdentPos); - inc(CleanStartPos); - end; - Result:=(IdentPos>Len) - and ((CleanStartPos>Srclen) or (not IsIdentChar[Src[CleanStartPos]])); -end; - function TCustomCodeTool.CompareSrcIdentifiers(Identifier1, Identifier2: PChar ): boolean; begin diff --git a/components/codetools/finddeclarationtool.pas b/components/codetools/finddeclarationtool.pas index 9bec382f3a..9398d84eee 100644 --- a/components/codetools/finddeclarationtool.pas +++ b/components/codetools/finddeclarationtool.pas @@ -165,6 +165,7 @@ type // instead return the variable declaration fdfFunctionResult, // if function is found, return result type fdfFindChilds, // search the class of a 'class of' + fdfSkipClassForward, // when a class forward was found search the class fdfCollect, // return every reachable identifier fdfTopLvlResolving, // set, when searching for an identifier of the @@ -197,6 +198,7 @@ const 'fdfFindVariable', 'fdfFunctionResult', 'fdfFindChilds', + 'fdfSkipClassForward', 'fdfCollect', 'fdfTopLvlResolving', 'fdfDoNotCache' @@ -517,7 +519,8 @@ type TFindSmartFlag = ( fsfIncludeDirective, // search for include file fsfFindMainDeclaration, // stop if already on a declaration - fsfSearchSourceName // if searching for a unit name, return the source name node + fsfSearchSourceName, // if searching for a unit name, return the source name node + fsfSkipClassForward // when a forward class was found, jump further to the class ); TFindSmartFlags = set of TFindSmartFlag; @@ -532,7 +535,7 @@ type TFindDeclarationListFlags = set of TFindDeclarationListFlag; const - AllFindSmartFlags = [fsfIncludeDirective]; + DefaultFindSmartFlags = [fsfIncludeDirective]; type //---------------------------------------------------------------------------- @@ -653,6 +656,7 @@ type Params: TFindDeclarationParams; FindClassContext: boolean): boolean; function FindForwardIdentifier(Params: TFindDeclarationParams; var IsForward: boolean): boolean; + function FindNonForwardClass(Params: TFindDeclarationParams): boolean; function FindExpressionResultType(Params: TFindDeclarationParams; StartPos, EndPos: integer): TExpressionType; function FindCodeToolForUsedUnit(UnitNameAtom, @@ -1135,7 +1139,7 @@ var NewTool: TFindDeclarationTool; NewNode: TCodeTreeNode; begin - Result:=FindDeclaration(CursorPos,AllFindSmartFlags,NewTool,NewNode, + Result:=FindDeclaration(CursorPos,DefaultFindSmartFlags,NewTool,NewNode, NewPos,NewTopLine); end; @@ -1222,6 +1226,13 @@ var CleanCursorPos: integer; end; end; + procedure CheckIfCursorInTypeNode; + begin + if (CursorNode.Desc in AllIdentifierDefinitions) + and (fsfSkipClassForward in SearchSmartFlags) then + Exclude(SearchSmartFlags,fsfSkipClassForward); + end; + procedure CheckIfCursorInClassNode; begin if SkipChecks then exit; @@ -1402,6 +1413,7 @@ begin SearchForward:=false; CheckIfCursorOnAForwardDefinedClass; CheckIfCursorInClassNode; + CheckIfCursorInTypeNode; CheckIfCursorInBeginNode; CheckIfCursorInProcNode; CheckIfCursorInPropertyNode; @@ -1426,6 +1438,8 @@ begin Params.Flags:=[fdfSearchInParentNodes,fdfExceptionOnNotFound, fdfExceptionOnPredefinedIdent, fdfTopLvlResolving,fdfSearchInAncestors]; + if fsfSkipClassForward in SearchSmartFlags then + Include(Params.Flags,fdfSkipClassForward); if not DirectSearch then begin // ToDo: DirtySrc Result:=FindDeclarationOfIdentAtParam(Params); @@ -1718,7 +1732,7 @@ function TFindDeclarationTool.FindNameInUsesSection(UsesNode: TCodeTreeNode; begin Result:=UsesNode.FirstChild; while (Result<>nil) - and (not CompareSrcIdentifier(Result.StartPos,PChar(UnitName))) do + and (not CompareSrcIdentifiers(Result.StartPos,PChar(UnitName))) do Result:=Result.NextBrother; end; @@ -1976,7 +1990,7 @@ var NodeStr: String; begin Result:=''; - if FindDeclaration(CursorPos,AllFindSmartFlags, + if FindDeclaration(CursorPos,DefaultFindSmartFlags, NewTool,NewNode,NewPos,NewTopLine) then begin { Examples: @@ -2178,6 +2192,7 @@ function TFindDeclarationTool.FindDeclarationOfIdentAtParam( var StartPos, EndPos: integer; ExprType: TExpressionType; + SkipForward: boolean; begin {$IFDEF CTDEBUG} DebugLn('[TFindDeclarationTool.FindDeclarationOfIdentAtParam] Identifier=', @@ -2199,11 +2214,14 @@ begin ReadTilBracketClose(true); EndPos:=CurPos.EndPos; end; + SkipForward:=fdfSkipClassForward in Params.Flags; Include(Params.Flags,fdfFindVariable); ExprType:=FindExpressionTypeOfVariable(StartPos,EndPos,Params,false); if (ExprType.Desc<>xtContext) then begin Params.SetResult(CleanFindContext); end; + if SkipForward and (Params.NewNode<>nil) then + Params.NewCodeTool.FindNonForwardClass(Params); {$IFDEF CTDEBUG} DbgOut('[TFindDeclarationTool.FindDeclarationOfIdentAtParam] Ident=', '"',GetIdentifier(Params.Identifier),'" '); @@ -2533,8 +2551,16 @@ var // identifier found Params.SetResult(Self,ContextNode); Result:=CheckResult(true,true); - if not (fdfCollect in Params.Flags) then + if not (fdfCollect in Params.Flags) then begin + if (fdfSkipClassForward in Params.Flags) + and (ContextNode.FirstChild<>nil) + and (ContextNode.FirstChild.Desc in [ctnClass,ctnClassInheritance]) + and ((ctnsForwardDeclaration and ContextNode.FirstChild.SubDesc)<>0) + then begin + FindNonForwardClass(Params); + end; exit; + end; end; // search for enums Params.ContextNode:=ContextNode; @@ -3565,7 +3591,7 @@ begin CurCursorPos:=CursorPos; CurTool:=Self; try - while CurTool.FindDeclaration(CurCursorPos,AllFindSmartFlags + while CurTool.FindDeclaration(CurCursorPos,DefaultFindSmartFlags +[fsfSearchSourceName], NewTool,NewNode,NewPos,NewTopLine) do begin @@ -4533,13 +4559,13 @@ begin end; if ClassNode.Desc=ctnClass then begin // if this class is not TObject, TObject is class ancestor - SearchBaseClass:=not CompareSrcIdentifier(ClassIdentNode.StartPos,'TObject'); + SearchBaseClass:=not CompareSrcIdentifiers(ClassIdentNode.StartPos,'TObject'); end else begin // Delphi has as default interface IInterface // FPC has as default interface IUnknown and an alias IInterface = IUnknown SearchBaseClass:= - (not CompareSrcIdentifier(ClassIdentNode.StartPos,'IInterface')) - and (not CompareSrcIdentifier(ClassIdentNode.StartPos,'IUnknown')); + (not CompareSrcIdentifiers(ClassIdentNode.StartPos,'IInterface')) + and (not CompareSrcIdentifiers(ClassIdentNode.StartPos,'IUnknown')); end; if not SearchBaseClass then exit; @@ -4748,6 +4774,48 @@ begin Params.Load(OldInput,true); end; +function TFindDeclarationTool.FindNonForwardClass(Params: TFindDeclarationParams + ): boolean; +var + Node: TCodeTreeNode; +begin + Result:=false; + Node:=Params.NewNode; + if Node.Desc=ctnGenericType then begin + Node:=Node.FirstChild; + if Node=nil then exit; + end else if Node.Desc<>ctnTypeDefinition then + exit; + Node:=Node.FirstChild; + if (Node=nil) + or (not (Node.Desc in [ctnClass,ctnClassInterface])) + or ((ctnsForwardDeclaration and Node.SubDesc)=0) then + exit; + Node:=Params.NewNode; + repeat + //DebugLn(['TFindDeclarationTool.FindNonForwardClass Node=',dbgstr(copy(Src,Node.StartPos,20))]); + if Node.NextBrother<>nil then + Node:=Node.NextBrother + else if (Node.Parent=nil) + or (not (Node.Parent.Desc in AllDefinitionSections)) then + break + else begin + Node:=Node.Parent.NextBrother; + while (Node<>nil) + and ((Node.FirstChild=nil) or (not (Node.Desc in AllDefinitionSections))) + do + Node:=Node.NextBrother; + if Node=nil then break; + Node:=Node.FirstChild; + end; + if CompareSrcIdentifiers(Node.StartPos,Params.Identifier) then begin + Params.SetResult(Self,Node,Node.StartPos); + Result:=true; + exit; + end; + until false; +end; + function TFindDeclarationTool.FindIdentifierInWithVarContext( WithVarNode: TCodeTreeNode; Params: TFindDeclarationParams): boolean; { this function is internally used by FindIdentifierInContext } @@ -5981,7 +6049,7 @@ var IdentFound:=false; if (ExprType.Context.Node<>nil) and (ExprType.Context.Node.Desc in AllPascalStatements) then begin - if CompareSrcIdentifier(CurAtom.StartPos,'SELF') then begin + if CompareSrcIdentifiers(CurAtom.StartPos,'SELF') then begin // SELF in a method is the object itself // -> check if in a method or nested proc of a method ProcNode:=ExprType.Context.Node; @@ -5998,7 +6066,7 @@ var ExprType.Context:=CreateFindContext(Params); IdentFound:=true; end; - end else if CompareSrcIdentifier(CurAtom.StartPos,'RESULT') then begin + end else if CompareSrcIdentifiers(CurAtom.StartPos,'RESULT') then begin // RESULT has a special meaning in a function // -> check if in a function ProcNode:=ExprType.Context.Node.GetNodeOfType(ctnProcedure); diff --git a/components/codetools/identcompletiontool.pas b/components/codetools/identcompletiontool.pas index c3513211a8..317de79253 100644 --- a/components/codetools/identcompletiontool.pas +++ b/components/codetools/identcompletiontool.pas @@ -1453,26 +1453,26 @@ begin if (CurrentContexts.ProcName='') then exit; FoundContext.Tool.MoveCursorToProcName(FoundContext.Node,true); //DebugLn(['TIdentCompletionTool.CollectAllContexts ProcName=',GetIdentifier(@FoundContext.Tool.Src[FoundContext.Tool.CurPos.StartPos])]); - if not FoundContext.Tool.CompareSrcIdentifier( + if not FoundContext.Tool.CompareSrcIdentifiers( FoundContext.Tool.CurPos.StartPos, - CurrentContexts.ProcName) + PChar(CurrentContexts.ProcName)) then exit; end; ctnProperty: begin if (CurrentContexts.ProcName='') then exit; FoundContext.Tool.MoveCursorToPropName(FoundContext.Node); - if not FoundContext.Tool.CompareSrcIdentifier( + if not FoundContext.Tool.CompareSrcIdentifiers( FoundContext.Tool.CurPos.StartPos, - CurrentContexts.ProcName) + PChar(CurrentContexts.ProcName)) then exit; end; ctnVarDefinition: begin if (CurrentContexts.ProcName='') then exit; - if not FoundContext.Tool.CompareSrcIdentifier( + if not FoundContext.Tool.CompareSrcIdentifiers( FoundContext.Node.StartPos, - CurrentContexts.ProcName) + PChar(CurrentContexts.ProcName)) then exit; end; else diff --git a/components/codetools/stdcodetools.pas b/components/codetools/stdcodetools.pas index cf8813b9b5..671b9cd98a 100644 --- a/components/codetools/stdcodetools.pas +++ b/components/codetools/stdcodetools.pas @@ -3560,7 +3560,7 @@ begin ANode:=ANode.FirstChild; while ANode<>nil do begin if (ANode.Desc=ctnConstDefinition) - and CompareSrcIdentifier(ANode.StartPos,ResStrIdentifier) then begin + and CompareSrcIdentifiers(ANode.StartPos,PChar(ResStrIdentifier)) then begin Result:=true; exit; end; diff --git a/ide/main.pp b/ide/main.pp index 0a4d14bef2..d6853cb69a 100644 --- a/ide/main.pp +++ b/ide/main.pp @@ -77,7 +77,7 @@ uses LResources, StdCtrls, Forms, Buttons, Menus, FileUtil, Controls, GraphType, HelpIntfs, Graphics, ExtCtrls, Dialogs, InterfaceBase, LDockCtrl, UTF8Process, // codetools - LinkScanner, BasicCodeTools, AVL_Tree, Laz_XMLCfg, + FindDeclarationTool, LinkScanner, BasicCodeTools, AVL_Tree, Laz_XMLCfg, CodeToolsStructs, CodeToolManager, CodeCache, DefineTemplates, // synedit SynEditKeyCmds, @@ -12578,8 +12578,10 @@ begin //DebugLn(['TMainIDE.DoFindDeclarationAtCaret LogCaretXY=',dbgs(LogCaretXY),' SynEdit.Log=',dbgs(ActiveSrcEdit.EditorComponent.LogicalCaretXY),' SynEdit.Caret=',dbgs(ActiveSrcEdit.EditorComponent.CaretXY)]); if CodeToolBoss.FindDeclaration(ActiveUnitInfo.Source, LogCaretXY.X,LogCaretXY.Y, - NewSource,NewX,NewY,NewTopLine) then - begin + NewSource,NewX,NewY,NewTopLine,DefaultFindSmartFlags + //+[fsfSkipClassForward] + ) + then begin //debugln(['TMainIDE.DoFindDeclarationAtCaret ',NewSource.Filename,' NewX=',Newx,',y=',NewY,' ',NewTopLine]); DoJumpToCodePos(ActiveSrcEdit, ActiveUnitInfo, NewSource, NewX, NewY, NewTopLine, true);