diff --git a/components/codetools/codecompletiontool.pas b/components/codetools/codecompletiontool.pas index f90280d107..652a2a0377 100644 --- a/components/codetools/codecompletiontool.pas +++ b/components/codetools/codecompletiontool.pas @@ -88,7 +88,7 @@ uses FileProcs, CodeToolsStrConsts, StdCodeTools, CodeTree, CodeAtom, CodeCache, CustomCodeTool, PascalParserTool, MethodJumpTool, FindDeclarationTool, KeywordFuncLists, CodeToolsStructs, BasicCodeTools, - LinkScanner, SourceChanger, CodeGraph, + LinkScanner, SourceChanger, CodeGraph, PascalReaderTool, {$IFDEF EnableCodeCompleteTemplates} CodeCompletionTemplater, {$ENDIF} @@ -140,7 +140,7 @@ type FSetPropertyVariablename: string; FSetPropertyVariableIsPrefix: Boolean; FSetPropertyVariableUseConst: Boolean; - FJumpToProcName: string; + FJumpToProcHead: TPascalMethodHeader; NewClassSectionIndent: array[TPascalClassSection] of integer; NewClassSectionInsertPos: array[TPascalClassSection] of integer; fFullTopLvlName: string;// used by OnTopLvlIdentifierFound @@ -457,13 +457,13 @@ begin end; // ToDo: check ancestor procs too // search in current class - Result:=(FindProcNode(FCompletingFirstEntryNode,NameAndParamsUpCase,[phpInUpperCase])<>nil); + Result:=(FindProcNode(FCompletingFirstEntryNode,NameAndParamsUpCase,mgMethod,[phpInUpperCase])<>nil); end; procedure TCodeCompletionCodeTool.SetCodeCompleteClassNode(const AClassNode: TCodeTreeNode); begin FreeClassInsertionList; - FJumpToProcName:=''; + FJumpToProcHead.Name:=''; FCodeCompleteClassNode:=AClassNode; if CodeCompleteClassNode=nil then begin FCompletingFirstEntryNode:=nil; @@ -1500,7 +1500,8 @@ begin MemSizeString(FSetPropertyVariablename) +PtrUInt(SizeOf(FSetPropertyVariableIsPrefix)) +PtrUInt(SizeOf(FSetPropertyVariableUseConst)) - +MemSizeString(FJumpToProcName) + +MemSizeString(FJumpToProcHead.Name) + +PtrUInt(SizeOf(FJumpToProcHead.Group)) +length(NewClassSectionIndent)*SizeOf(integer) +length(NewClassSectionInsertPos)*SizeOf(integer) +MemSizeString(fFullTopLvlName)); @@ -8349,8 +8350,9 @@ procedure TCodeCompletionCodeTool.GuessProcDefBodyMapping(ProcDefNodes, NewNodeExt.Node:=ProcNode; NewNodeExt.Txt:=ExtractProcName(ProcNode,[phpWithoutClassName]); NewNodeExt.Data:=NodeExt; + NewNodeExt.Flags:=Integer(ExtractProcedureGroup(ProcNode)); if Result=nil then - Result:=TAVLTree.Create(@CompareCodeTreeNodeExt); + Result:=TAVLTree.Create(@CompareCodeTreeNodeExtMethodHeaders); Result.Add(NewNodeExt); end; AVLNodeExt:=NodeExtTree.FindSuccessor(AVLNodeExt); @@ -8544,15 +8546,16 @@ var {$ENDIF} ProcCode:=Beauty.BeautifyProc(ProcCode,Indent,ANodeExt.ExtTxt3=''); FSourceChangeCache.Replace(gtEmptyLine,gtEmptyLine,InsertPos,InsertPos,ProcCode); - if FJumpToProcName='' then begin + if FJumpToProcHead.Name='' then begin // remember one proc body to jump to after the completion - FJumpToProcName:=ANodeExt.Txt; - if System.Pos('.',FJumpToProcName)<1 then - FJumpToProcName:=TheClassName+'.'+FJumpToProcName; - if FJumpToProcName[length(FJumpToProcName)]<>';' then - FJumpToProcName:=FJumpToProcName+';'; + FJumpToProcHead.Name:=ANodeExt.Txt; + FJumpToProcHead.Group:=TPascalMethodGroup(ANodeExt.Flags); + if System.Pos('.',FJumpToProcHead.Name)<1 then + FJumpToProcHead.Name:=TheClassName+'.'+FJumpToProcHead.Name; + if FJumpToProcHead.Name[length(FJumpToProcHead.Name)]<>';' then + FJumpToProcHead.Name:=FJumpToProcHead.Name+';'; {$IFDEF CTDEBUG} - DebugLn('CreateMissingClassProcBodies FJumpToProcName="',FJumpToProcName,'"'); + DebugLn('CreateMissingClassProcBodies FJumpToProcHead.Name="',FJumpToProcHead.Name,'"'); {$ENDIF} end; end; @@ -8615,7 +8618,9 @@ var if NextAVLNode<>nil then begin ANodeExt:=TCodeTreeNodeExtension(AnAVLNode.Data); ANodeExt2:=TCodeTreeNodeExtension(NextAVLNode.Data); - if CompareTextIgnoringSpace(ANodeExt.Txt,ANodeExt2.Txt,false)=0 then + if SameMethodHeaders(ANodeExt.Txt, TPascalMethodGroup(ANodeExt.Flags), + ANodeExt2.Txt, TPascalMethodGroup(ANodeExt2.Flags)) + then begin // proc redefined -> error if ANodeExt.Node.StartPos>ANodeExt2.Node.StartPos then begin @@ -8937,7 +8942,7 @@ begin begin // search alphabetically nearest proc body ExistingNode:=ProcBodyNodes.FindNearest(MissingNode.Data); - cmp:=CompareCodeTreeNodeExt(ExistingNode.Data,MissingNode.Data); + cmp:=CompareCodeTreeNodeExtMethodHeaders(ExistingNode.Data,MissingNode.Data); if (cmp<0) then begin AnAVLNode:=ProcBodyNodes.FindSuccessor(ExistingNode); if AnAVLNode<>nil then begin @@ -9043,9 +9048,9 @@ begin FreeClassInsertionList; end; - if FJumpToProcName<>'' then begin + if FJumpToProcHead.Name<>'' then begin {$IFDEF CTDEBUG} - DebugLn('TCodeCompletionCodeTool.ApplyChangesAndJumpToFirstNewProc Jump to new proc body ... "',FJumpToProcName,'"'); + DebugLn('TCodeCompletionCodeTool.ApplyChangesAndJumpToFirstNewProc Jump to new proc body ... "',FJumpToProcHead.Name,'"'); {$ENDIF} // there was a new proc body // -> find it and jump to @@ -9061,9 +9066,9 @@ begin FCodeCompleteClassNode:=FindClassNode(CursorNode,CurClassName,true,false); if CodeCompleteClassNode=nil then RaiseException('oops, I lost your class'); - ProcNode:=FindProcNode(CursorNode,FJumpToProcName,[phpInUpperCase,phpIgnoreForwards]); + ProcNode:=FindProcNode(CursorNode,FJumpToProcHead,[phpInUpperCase,phpIgnoreForwards]); if ProcNode=nil then begin - debugln(['TCodeCompletionCodeTool.ApplyChangesAndJumpToFirstNewProc Proc="',FJumpToProcName,'"']); + debugln(['TCodeCompletionCodeTool.ApplyChangesAndJumpToFirstNewProc Proc="',FJumpToProcHead.Name,'"']); RaiseException(ctsNewProcBodyNotFound); end; Result:=FindJumpPointInProcNode(ProcNode,NewPos,NewTopLine); diff --git a/components/codetools/extractproctool.pas b/components/codetools/extractproctool.pas index 96ead59d83..1d7884a44a 100644 --- a/components/codetools/extractproctool.pas +++ b/components/codetools/extractproctool.pas @@ -43,7 +43,7 @@ interface uses Classes, SysUtils, math, FileProcs, CodeToolsStrConsts, CodeTree, CodeAtom, - CodeCache, CustomCodeTool, + CodeCache, CustomCodeTool, PascalReaderTool, PascalParserTool, CodeCompletionTool, KeywordFuncLists, BasicCodeTools, LinkScanner, AVL_Tree, SourceChanger, FindDeclarationTool; @@ -843,7 +843,7 @@ var else ProcHead:=''; ProcHead:=ProcHead+ProcName+BaseParamList; - ConflictProcNode:=FindProcNode(ContextNode,ProcHead, + ConflictProcNode:=FindProcNode(ContextNode,ProcHead,mgMethod, ShortProcFormat+[phpIgnoreForwards]); Result:=ConflictProcNode<>nil; if Result then begin diff --git a/components/codetools/finddeclarationtool.pas b/components/codetools/finddeclarationtool.pas index d181853c4f..d35237bb59 100644 --- a/components/codetools/finddeclarationtool.pas +++ b/components/codetools/finddeclarationtool.pas @@ -9517,6 +9517,12 @@ begin exit; end; + if FoundContext.Tool.NodeIsClassConstructorOrDestructor(FoundContext.Node) then + begin + Result:=ifrProceedSearch; + Exit; + end; + if (not (fdfCollect in Params.Flags)) and CallHasEmptyParamsAndFoundProcFits then begin // call has brackets without params (e.g. writeln() ) diff --git a/components/codetools/identcompletiontool.pas b/components/codetools/identcompletiontool.pas index 10b9892964..cf533f4417 100644 --- a/components/codetools/identcompletiontool.pas +++ b/components/codetools/identcompletiontool.pas @@ -1171,6 +1171,8 @@ begin Ident:=@FoundContext.Tool.Src[FoundContext.Node.StartPos]; ctnProcedure,ctnProcedureHead: + //do not list class constructors and destructors + if not FoundContext.Tool.NodeIsClassConstructorOrDestructor(FoundContext.Node) then begin Ident:=FoundContext.Tool.GetProcNameIdentifier(FoundContext.Node); NewItem := CurrentIdentifierList.FindIdentifier(Ident,true); diff --git a/components/codetools/methodjumptool.pas b/components/codetools/methodjumptool.pas index 2a971f5f9a..8f87c9381d 100644 --- a/components/codetools/methodjumptool.pas +++ b/components/codetools/methodjumptool.pas @@ -42,7 +42,7 @@ uses {$ENDIF} Classes, SysUtils, FileProcs, LazFileUtils, CodeTree, PascalParserTool, StdCodeTools, KeywordFuncLists, BasicCodeTools, - LinkScanner, CodeCache, AVL_Tree; + LinkScanner, CodeCache, PascalReaderTool, AVL_Tree; type @@ -274,16 +274,16 @@ const // search for a proc node with same name and jump to difference in param list // returns true on jumped, false if no target proc found var - SearchedProcHead: string; + SearchedProcHead: TPascalMethodHeader; ProcNode: TCodeTreeNode; begin Result:=false; if SearchForProcNode=nil then exit; - SearchedProcHead:=ExtractProcHead(SearchForProcNode,SearchForProcAttr); + SearchedProcHead:=ExtractProcHeadWithGroup(SearchForProcNode,SearchForProcAttr); {$IFDEF CTDEBUG} - DebugLn('TMethodJumpingCodeTool.FindJumpPoint.FindBestProcNode Searching ',SearchForProcNode.DescAsString,' "',SearchedProcHead,'" ',ProcHeadAttributesToStr(SearchForProcAttr)); + DebugLn('TMethodJumpingCodeTool.FindJumpPoint.FindBestProcNode Searching ',SearchForProcNode.DescAsString,' "',SearchedProcHead.Head,'" ',ProcHeadAttributesToStr(SearchForProcAttr)); {$ENDIF} - if SearchedProcHead='' then exit; + if SearchedProcHead.Name='' then exit; ProcNode:=FindProcNode(StartNode,SearchedProcHead,SearchInProcAttr); {$IFDEF CTDEBUG} DebugLn('TMethodJumpingCodeTool.FindJumpPoint.FindBestProcNode Found:',dbgs(ProcNode<>nil)); @@ -301,11 +301,11 @@ const phpWithComments]; SearchForProcAttr:=SearchForProcAttr+[phpWithoutBrackets, phpWithoutParamList]; - SearchedProcHead:=ExtractProcHead(SearchForProcNode,SearchForProcAttr); + SearchedProcHead:=ExtractProcHeadWithGroup(SearchForProcNode,SearchForProcAttr); {$IFDEF CTDEBUG} - DebugLn('TMethodJumpingCodeTool.FindJumpPoint.FindBestProcNode Searching without params "',SearchedProcHead,'"'); + DebugLn('TMethodJumpingCodeTool.FindJumpPoint.FindBestProcNode Searching without params "',SearchedProcHead.Name,'"'); {$ENDIF} - if SearchedProcHead='' then exit; + if SearchedProcHead.Name='' then exit; ProcNode:=FindProcNode(StartNode,SearchedProcHead,SearchForProcAttr); {$IFDEF CTDEBUG} DebugLn('TMethodJumpingCodeTool.FindJumpPoint.FindBestProcNode Found:',dbgs(ProcNode<>nil)); @@ -789,7 +789,7 @@ var CurProcName: string; CurClassName: String; begin //debugln(['TMethodJumpingCodeTool.GatherProcNodes START']); - Result:=TAVLTree.Create(@CompareCodeTreeNodeExt); + Result:=TAVLTree.Create(@CompareCodeTreeNodeExtMethodHeaders); if (StartNode=nil) or (StartNode.Parent=nil) then exit; ANode:=StartNode; while (ANode<>nil) do begin @@ -825,6 +825,7 @@ begin with NewNodeExt do begin Node:=ANode; Txt:=CurProcName; + Flags:=Ord(ExtractProcedureGroup(ANode)); end; Result.Add(NewNodeExt); end; @@ -961,7 +962,7 @@ function TMethodJumpingCodeTool.FindSubProcPath(SubProcPath: TStrings; Result:=nil; if (PathIndex>SubProcPath.Count) or (StartNode=nil) then exit; ProcHead:=SubProcPath[PathIndex]; - ProcNode:=FindProcNode(StartNode,ProcHead,Attr); + ProcNode:=FindProcNode(StartNode,ProcHead,mgMethod,Attr); //DebugLn('TMethodJumpingCodeTool.SearchSubProcPath A ProcHead="',ProcHead,'" Found=',dbgs(ProcNode<>nil)); if ProcNode=nil then exit; if PathIndex=SubProcPath.Count-1 then begin diff --git a/components/codetools/pascalreadertool.pas b/components/codetools/pascalreadertool.pas index 25d603d8c6..dd54415922 100644 --- a/components/codetools/pascalreadertool.pas +++ b/components/codetools/pascalreadertool.pas @@ -57,6 +57,15 @@ type epriInDirective ); + //the scope groups of pascal methods. + //please note that Destructor is principally a method and thus is not listed here -> you cannot define "procedure Destroy;" and "destructor Destroy" in one class + TPascalMethodGroup = (mgMethod, mgConstructor, mgClassConstructor, mgClassDestructor); + + TPascalMethodHeader = record + Name: string; + Group: TPascalMethodGroup; + end; + TOnEachPRIdentifier = procedure(Sender: TPascalParserTool; IdentifierCleanPos: integer; Range: TEPRIRange; Node: TCodeTreeNode; Data: Pointer; var Abort: boolean) of object; @@ -121,6 +130,8 @@ type Attr: TProcHeadAttributes): string; function ExtractProcHead(ProcNode: TCodeTreeNode; Attr: TProcHeadAttributes): string; + function ExtractProcHeadWithGroup(ProcNode: TCodeTreeNode; + Attr: TProcHeadAttributes): TPascalMethodHeader; function ExtractProcedureHeader(CursorPos: TCodeXYPosition; Attributes: TProcHeadAttributes; var ProcHead: string): boolean; function ExtractClassNameOfProcNode(ProcNode: TCodeTreeNode; @@ -129,7 +140,10 @@ type ProcSpec: TProcedureSpecifier): boolean; function GetProcNameIdentifier(ProcNode: TCodeTreeNode): PChar; function FindProcNode(StartNode: TCodeTreeNode; const AProcHead: string; - Attr: TProcHeadAttributes): TCodeTreeNode; + AProcSpecType: TPascalMethodGroup; + Attr: TProcHeadAttributes): TCodeTreeNode; overload; + function FindProcNode(StartNode: TCodeTreeNode; const AProcHead: TPascalMethodHeader; + Attr: TProcHeadAttributes): TCodeTreeNode; overload; function FindCorrespondingProcNode(ProcNode: TCodeTreeNode; Attr: TProcHeadAttributes = [phpWithoutClassKeyword,phpWithoutClassName] ): TCodeTreeNode; @@ -138,6 +152,7 @@ type ): TCodeTreeNode; function FindProcBody(ProcNode: TCodeTreeNode): TCodeTreeNode; function ProcBodyIsEmpty(ProcNode: TCodeTreeNode): boolean; + function ExtractProcedureGroup(ProcNode: TCodeTreeNode): TPascalMethodGroup; procedure MoveCursorToFirstProcSpecifier(ProcNode: TCodeTreeNode); function MoveCursorToProcSpecifier(ProcNode: TCodeTreeNode; ProcSpec: TProcedureSpecifier): boolean; @@ -156,6 +171,7 @@ type function NodeIsMethodBody(ProcNode: TCodeTreeNode): boolean; function GetMethodOfBody(Node: TCodeTreeNode): TCodeTreeNode; function NodeIsFunction(ProcNode: TCodeTreeNode): boolean; + function NodeIsClassConstructorOrDestructor(ProcNode: TCodeTreeNode): boolean; function NodeIsConstructor(ProcNode: TCodeTreeNode): boolean; function NodeIsDestructor(ProcNode: TCodeTreeNode): boolean; function NodeIsForwardProc(ProcNode: TCodeTreeNode): boolean; @@ -267,8 +283,54 @@ type procedure CalcMemSize(Stats: TCTMemStats); override; end; +function CompareMethodHeaders(const Method1Name: string; Method1Group: TPascalMethodGroup; + const Method2Name: string; Method2Group: TPascalMethodGroup): Integer; overload; +function CompareMethodHeaders(const Method1Head: TPascalMethodHeader; const Method2Head: TPascalMethodHeader): Integer; overload; +function SameMethodHeaders(const Method1Name: string; Method1Group: TPascalMethodGroup; + const Method2Name: string; Method2Group: TPascalMethodGroup): Boolean; overload; +function SameMethodHeaders(const Method1Head: TPascalMethodHeader; const Method2Head: TPascalMethodHeader): Boolean; overload; +function CompareCodeTreeNodeExtMethodHeaders(NodeData1, NodeData2: pointer): integer; + implementation +function CompareMethodHeaders(const Method1Name: string; + Method1Group: TPascalMethodGroup; const Method2Name: string; + Method2Group: TPascalMethodGroup): Integer; +begin + Result := (Ord(Method1Group) - Ord(Method2Group)); + if Result <> 0 then exit; + Result := CompareTextIgnoringSpace(Method1Name,Method2Name,false); +end; + +function CompareMethodHeaders(const Method1Head: TPascalMethodHeader; + const Method2Head: TPascalMethodHeader): Integer; +begin + Result := CompareMethodHeaders(Method1Head.Name, Method1Head.Group, + Method2Head.Name, Method2Head.Group); +end; + +function SameMethodHeaders(const Method1Name: string; + Method1Group: TPascalMethodGroup; const Method2Name: string; + Method2Group: TPascalMethodGroup): Boolean; +begin + Result := CompareMethodHeaders(Method1Name, Method1Group, Method2Name, Method2Group) = 0; +end; + +function SameMethodHeaders(const Method1Head: TPascalMethodHeader; + const Method2Head: TPascalMethodHeader): Boolean; +begin + Result := CompareMethodHeaders(Method1Head, Method2Head) = 0; +end; + +function CompareCodeTreeNodeExtMethodHeaders(NodeData1, NodeData2: pointer): integer; +var + NodeExt1: TCodeTreeNodeExtension absolute NodeData1; + NodeExt2: TCodeTreeNodeExtension absolute NodeData2; +begin + Result:=CompareMethodHeaders(NodeExt1.Txt,TPascalMethodGroup(NodeExt1.Flags),NodeExt2.Txt,TPascalMethodGroup(NodeExt2.Flags)); +end; + + { TPascalReaderTool } procedure TPascalReaderTool.RaiseStrConstExpected; @@ -667,6 +729,13 @@ begin Result:=Result+';'; end; +function TPascalReaderTool.ExtractProcHeadWithGroup(ProcNode: TCodeTreeNode; + Attr: TProcHeadAttributes): TPascalMethodHeader; +begin + Result.Name := ExtractProcHead(ProcNode, Attr); + Result.Group := ExtractProcedureGroup(ProcNode); +end; + function TPascalReaderTool.ExtractProcedureHeader(CursorPos: TCodeXYPosition; Attributes: TProcHeadAttributes; var ProcHead: string): boolean; var @@ -842,14 +911,15 @@ begin end; function TPascalReaderTool.FindProcNode(StartNode: TCodeTreeNode; - const AProcHead: string; Attr: TProcHeadAttributes): TCodeTreeNode; + const AProcHead: TPascalMethodHeader; Attr: TProcHeadAttributes): TCodeTreeNode; // search in all next brothers for a Procedure Node with the Name ProcName // if there are no further brothers and the parent is a section node // ( e.g. 'interface', 'implementation', ...) or a class visibility node // (e.g. 'public', 'private', ...) then the search will continue in the next // section -var CurProcHead: string; +var InClass: Boolean; + CurProcHead: TPascalMethodHeader; begin Result:=StartNode; InClass:=FindClassOrInterfaceNode(StartNode)<>nil; @@ -860,10 +930,11 @@ begin and (not ((phpIgnoreProcsWithBody in Attr) and (FindProcBody(Result)<>nil))) then begin - CurProcHead:=ExtractProcHead(Result,Attr); + CurProcHead:=ExtractProcHeadWithGroup(Result,Attr); //DebugLn(['TPascalReaderTool.FindProcNode B "',CurProcHead,'" =? "',AProcHead,'" Result=',CompareTextIgnoringSpace(CurProcHead,AProcHead,false)]); - if (CurProcHead<>'') - and (CompareTextIgnoringSpace(CurProcHead,AProcHead,false)=0) then + if (CurProcHead.Name<>'') and + SameMethodHeaders(AProcHead, CurProcHead) + then exit; end; end; @@ -875,12 +946,23 @@ begin end; end; +function TPascalReaderTool.FindProcNode(StartNode: TCodeTreeNode; + const AProcHead: string; AProcSpecType: TPascalMethodGroup; + Attr: TProcHeadAttributes): TCodeTreeNode; +var + ProcHead: TPascalMethodHeader; +begin + ProcHead.Name := AProcHead; + ProcHead.Group := AProcSpecType; + Result := FindProcNode(StartNode, ProcHead, Attr); +end; + function TPascalReaderTool.FindCorrespondingProcNode(ProcNode: TCodeTreeNode; Attr: TProcHeadAttributes): TCodeTreeNode; var ClassNode: TCodeTreeNode; StartNode: TCodeTreeNode; - ProcHead: String; + ProcHead: TPascalMethodHeader; begin Result:=nil; // get ctnProcedure @@ -924,7 +1006,7 @@ begin end; if StartNode=nil then exit; - ProcHead:=ExtractProcHead(ProcNode,Attr); + ProcHead:=ExtractProcHeadWithGroup(ProcNode,Attr); //debugln('TPascalReaderTool.FindCorrespondingProcNode StartNode=',StartNode.DescAsString,' ProcHead=',dbgstr(ProcHead),' ',dbgs(Attr),' ',StartNode.DescAsString); Result:=FindProcNode(StartNode,ProcHead,Attr); if Result=ProcNode then begin @@ -2405,6 +2487,28 @@ begin Result:=ctnNone; end; +function TPascalReaderTool.ExtractProcedureGroup(ProcNode: TCodeTreeNode + ): TPascalMethodGroup; +begin + Result:=mgMethod; + if (ProcNode=nil) then exit; + if ProcNode.Desc=ctnProcedureHead then + ProcNode:=ProcNode.Parent; + if ProcNode.Desc<>ctnProcedure then exit; + MoveCursorToNodeStart(ProcNode); + ReadNextAtom; + if UpAtomIs('CLASS') then + begin + ReadNextAtom; + if UpAtomIs('CONSTRUCTOR') then + Result := mgClassConstructor; + if UpAtomIs('DESTRUCTOR') then + Result := mgClassDestructor; + end else + if UpAtomIs('CONSTRUCTOR') then + Result := mgConstructor +end; + function TPascalReaderTool.PositionInSourceName(CleanPos: integer): boolean; var NamePos: TAtomPosition; @@ -2733,6 +2837,12 @@ begin Result:=true; end; +function TPascalReaderTool.NodeIsClassConstructorOrDestructor( + ProcNode: TCodeTreeNode): boolean; +begin + Result := ExtractProcedureGroup(ProcNode) in [mgClassConstructor, mgClassDestructor]; +end; + function TPascalReaderTool.NodeIsForwardType(TypeNode: TCodeTreeNode): boolean; begin Result:=false;