diff --git a/.gitattributes b/.gitattributes index 202c84fa54..4e4ad453b1 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1012,6 +1012,7 @@ components/codetools/tests/fpctests/tchlp52.pp svneol=native#text/plain components/codetools/tests/fpctests/tchlp53.pp svneol=native#text/plain components/codetools/tests/fpctests/tchlp6.pp svneol=native#text/plain components/codetools/tests/fpctests/tchlp7.pp svneol=native#text/plain +components/codetools/tests/fpctests/uchlp12.pp svneol=native#text/plain components/codetools/tests/laztests/README.txt svneol=native#text/plain components/codetools/tests/laztests/bug28861_unit1.pas svneol=native#text/plain components/codetools/tests/laztests/bug28861_unit2.pas svneol=native#text/plain diff --git a/components/codetools/finddeclarationtool.pas b/components/codetools/finddeclarationtool.pas index 23077a0f55..4e1b6bef3b 100644 --- a/components/codetools/finddeclarationtool.pas +++ b/components/codetools/finddeclarationtool.pas @@ -893,9 +893,9 @@ type // ancestors function FindClassAndAncestors(ClassNode: TCodeTreeNode; - out ListOfPFindContext: TFPList; ExceptionOnNotFound: boolean + var ListOfPFindContext: TFPList; ExceptionOnNotFound: boolean ): boolean; // without interfaces, recursive - function FindContextClassAndAncestors(const CursorPos: TCodeXYPosition; + function FindContextClassAndAncestorsAndExtendedClassOfHelper(const CursorPos: TCodeXYPosition; var ListOfPFindContext: TFPList): boolean; // without interfaces function FindAncestorOfClass(ClassNode: TCodeTreeNode; Params: TFindDeclarationParams; FindClassContext: boolean): boolean; // returns false for TObject, IInterface, IUnknown @@ -4950,7 +4950,7 @@ begin end; function TFindDeclarationTool.FindClassAndAncestors(ClassNode: TCodeTreeNode; - out ListOfPFindContext: TFPList; ExceptionOnNotFound: boolean): boolean; + var ListOfPFindContext: TFPList; ExceptionOnNotFound: boolean): boolean; var Params: TFindDeclarationParams; @@ -4979,7 +4979,6 @@ var begin {$IFDEF CheckNodeTool}CheckNodeTool(ClassNode);{$ENDIF} Result:=false; - ListOfPFindContext:=nil; if (ClassNode=nil) or (not (ClassNode.Desc in AllClasses)) or (ClassNode.Parent=nil) or (not (ClassNode.Parent.Desc in [ctnTypeDefinition,ctnGenericType])) then @@ -5076,14 +5075,14 @@ begin end; end; -function TFindDeclarationTool.FindContextClassAndAncestors( - const CursorPos: TCodeXYPosition; var ListOfPFindContext: TFPList - ): boolean; +function TFindDeclarationTool.FindContextClassAndAncestorsAndExtendedClassOfHelper + (const CursorPos: TCodeXYPosition; var ListOfPFindContext: TFPList): boolean; // returns a list of nodes of AllClasses (ctnClass, ...) var CleanCursorPos: integer; ANode: TCodeTreeNode; ClassNode: TCodeTreeNode; + ExtendedClassExpr: TExpressionType; begin Result:=false; ListOfPFindContext:=nil; @@ -5107,6 +5106,15 @@ begin if not FindClassAndAncestors(ClassNode,ListOfPFindContext,true) then exit; + //find extended class node + ExtendedClassExpr := FindExtendedExprOfHelper(ClassNode); + if ((ExtendedClassExpr.Desc=xtContext) and (ExtendedClassExpr.Context.Tool<>nil) and + (ExtendedClassExpr.Context.Node<>nil) and (ExtendedClassExpr.Context.Node.Desc=ctnClass)) then + begin + if not ExtendedClassExpr.Context.Tool.FindClassAndAncestors(ExtendedClassExpr.Context.Node,ListOfPFindContext,true) + then exit; + end; + //debugln('TFindDeclarationTool.FindContextClassAndAncestors List: ',ListOfPFindContextToStr(ListOfPFindContext)); finally diff --git a/components/codetools/identcompletiontool.pas b/components/codetools/identcompletiontool.pas index 824cd124fc..d649835739 100644 --- a/components/codetools/identcompletiontool.pas +++ b/components/codetools/identcompletiontool.pas @@ -355,7 +355,7 @@ type FBeautifier: TBeautifyCodeOptions; FLastGatheredIdentParent: TCodeTreeNode; FLastGatheredIdentLevel: integer; - FICTClassAndAncestors: TFPList;// list of PCodeXYPosition + FICTClassAndAncestorsAndExtClassOfHelper: TFPList;// list of PCodeXYPosition FIDCTFoundPublicProperties: TAVLTree;// tree of PChar (pointing to the // property names in source) FIDTFoundMethods: TAVLTree;// tree of TCodeTreeNodeExtension Txt=clean text @@ -1009,7 +1009,7 @@ var FoundClassContext: TFindContext; begin Result:=false; - if FICTClassAndAncestors<>nil then begin + if (FICTClassAndAncestorsAndExtClassOfHelper<>nil) then begin // start of the identifier completion is in a method or class // => all protected ancestor classes are allowed as well. CurClassNode:=FoundContext.Node; @@ -1018,8 +1018,8 @@ var CurClassNode:=CurClassNode.Parent; if CurClassNode=nil then exit; FoundClassContext:=CreateFindContext(Params.NewCodeTool,CurClassNode); - if IndexOfFindContext(FICTClassAndAncestors,@FoundClassContext)>=0 then begin - // this class node is the class or one of the ancestors of the class + if IndexOfFindContext(FICTClassAndAncestorsAndExtClassOfHelper,@FoundClassContext)>=0 then begin + // this class node is the class or one of the ancestors of the class or extended class of the helper+ancestors // of the start context of the identifier completion exit(true); end; @@ -2576,7 +2576,9 @@ begin GatherContext := ExprType.Context; // find class and ancestors if existing (needed for protected identifiers) if GatherContext.Tool = Self then - FindContextClassAndAncestors(IdentStartXY, FICTClassAndAncestors); + begin + FindContextClassAndAncestorsAndExtendedClassOfHelper(IdentStartXY, FICTClassAndAncestorsAndExtClassOfHelper); + end; CursorContext:=CreateFindContext(Self,CursorNode); GatherContextKeywords(CursorContext,IdentStartPos,Beautifier); @@ -2756,7 +2758,7 @@ begin Result:=true; finally - FreeListOfPFindContext(FICTClassAndAncestors); + FreeListOfPFindContext(FICTClassAndAncestorsAndExtClassOfHelper); FreeAndNil(FIDCTFoundPublicProperties); Params.Free; ClearIgnoreErrorAfter; @@ -2959,7 +2961,7 @@ begin if IdentEndPos=0 then ; // find class and ancestors if existing (needed for protected identifiers) - FindContextClassAndAncestors(CursorPos,FICTClassAndAncestors); + FindContextClassAndAncestorsAndExtendedClassOfHelper(CursorPos,FICTClassAndAncestorsAndExtClassOfHelper); if CursorNode<>nil then begin if not CheckContextIsParameter(Result) then begin @@ -2981,7 +2983,7 @@ begin end else begin FreeAndNil(CurrentIdentifierContexts); end; - FreeListOfPFindContext(FICTClassAndAncestors); + FreeListOfPFindContext(FICTClassAndAncestorsAndExtClassOfHelper); FreeAndNil(FIDCTFoundPublicProperties); Params.Free; ClearIgnoreErrorAfter; @@ -3324,9 +3326,9 @@ var m: PtrUint; begin inherited CalcMemSize(Stats); - if FICTClassAndAncestors<>nil then - Stats.Add('TIdentCompletionTool.ClassAndAncestors', - FICTClassAndAncestors.Count*(SizeOf(TAVLTreeNode)+SizeOf(TCodeXYPosition))); + if FICTClassAndAncestorsAndExtClassOfHelper<>nil then + Stats.Add('TIdentCompletionTool.ClassAndAncestorsAndExtClassOfHelper', + FICTClassAndAncestorsAndExtClassOfHelper.Count*(SizeOf(TAVLTreeNode)+SizeOf(TCodeXYPosition))); if FIDCTFoundPublicProperties<>nil then Stats.Add('TIdentCompletionTool.FoundPublicProperties', FIDCTFoundPublicProperties.Count*SizeOf(TAVLTreeNode)); diff --git a/components/codetools/tests/fpctests/tchlp14.pp b/components/codetools/tests/fpctests/tchlp14.pp index 585a82a593..ddd323ee2b 100644 --- a/components/codetools/tests/fpctests/tchlp14.pp +++ b/components/codetools/tests/fpctests/tchlp14.pp @@ -18,7 +18,7 @@ type function TTestHelper.AccessTest: Integer; begin - Result := Test3; + Result := Test3{declaration:uchlp12.TTest.test3}; end; begin diff --git a/components/codetools/tests/fpctests/tchlp15.pp b/components/codetools/tests/fpctests/tchlp15.pp index e391a85a5c..4b8f8ed36b 100644 --- a/components/codetools/tests/fpctests/tchlp15.pp +++ b/components/codetools/tests/fpctests/tchlp15.pp @@ -18,7 +18,7 @@ type function TTestHelper.AccessTest: Integer; begin - Result := Test4; + Result := Test4{declaration:uchlp12.TTest.test4}; end; begin diff --git a/components/codetools/tests/fpctests/uchlp12.pp b/components/codetools/tests/fpctests/uchlp12.pp new file mode 100644 index 0000000000..141274a85c --- /dev/null +++ b/components/codetools/tests/fpctests/uchlp12.pp @@ -0,0 +1,36 @@ +unit uchlp12; + +{$ifdef fpc} + {$mode delphi} +{$endif} + +interface + +type +{$M+} + TTest = class + private + function GetTest6: Integer; + strict private + Test1: Integer; + private + Test2: Integer; + strict protected + Test3: Integer; + protected + Test4: Integer; + public + Test5: Integer; + published + property Test6: Integer read GetTest6; + end; +{$M-} + +implementation + +function TTest.GetTest6: Integer; +begin + Result := 0; +end; + +end.