I'm finally revising this problem I had over a month ago with find references not working. I'm going to just post this code here and see if you see anything strange (most of it is from your example code).
What happens is that the unit graph seems to be incomplete if the units are in another directory and I use -Fu via FPCOptions (if supply no FPCOptions then it fails completely). If I take the units out of the directory the graph is complete and all references are found. Strangely it DOES find the first unit but none after that. Bugs or misuse? ============ FPC$ /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/TestCodeTools main program: /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/test.pas Found identifier: TSomeType 4 in unit graph searching /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/units/utypes.pas... searching /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/units/utypes.pas... searching /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/test.pas... searching /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/units/utypes.pas... found: /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/units/utypes.pas @ 10,3 found: /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/units/utypes.pas @ 12,24 found: /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/units/utypes.pas @ 16,24 found: /Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools/test/test.pas @ 11,6 ============ {$mode objfpc} program test; uses ugenconst, uother, utypes; {$include hidden.inc} var c: TSomeClass; t: TSomeType = HIDDEN_VALUE; begin t := TSomeValue; DoThis(t); PrintType(t); end. ============ {$mode objfpc}{$H+} program TestCodeTools; uses SysUtils, Classes, DateUtils, fpjson, fpjsonrtti, CodeToolManager, CodeToolsConfig, CodeCache, IdentCompletionTool, BasicCodeTools, CodeTree, FindDeclarationTool, PascalParserTool, KeywordFuncLists, DefineTemplates, LazFileUtils, Laz_AVL_Tree,CTUnitGraph; procedure InitCodeTools(Switches: array of string); var CodeToolsOptions: TCodeToolsOptions; Switch: String; begin CodeToolsOptions := TCodeToolsOptions.Create; with CodeToolsOptions do begin //FPCSrcDir := '/usr/local/share/fpcsrc'; //FPCPath := '/usr/local/lib/fpc/3.0.4/ppcx64'; InitWithEnvironmentVariables; for Switch in Switches do FPCOptions := FPCOptions + switch + ' '; end; with CodeToolBoss do begin Init(CodeToolsOptions); IdentifierList.SortForHistory := True; IdentifierList.SortForScope := True; end; end; procedure CheckSyntax(Code: TCodeBuffer); var Tool: TCodeTool; begin if not CodeToolBoss.Explore(Code,Tool,true) then if CodeToolBoss.ErrorCode <> nil then writeln('Syntax Error -> '+CodeToolBoss.ErrorCode.FileName+': "'+CodeToolBoss.ErrorMessage+'" @ '+IntToStr(CodeToolBoss.ErrorLine)+':'+IntToStr(CodeToolBoss.ErrorColumn)) else writeln('Syntax Error -> '+CodeToolBoss.ErrorMessage); end; procedure FindReferences(Filename, MainFilename: String; Y, X: Integer); var DeclCode, StartSrcCode, Code: TCodeBuffer; ListOfPCodeXYPosition: TFPList; DeclX, DeclY, DeclTopLine, i: Integer; Identifier: string; Graph: TUsesGraph; Cache: TFindIdentifierReferenceCache; TreeOfPCodeXYPosition: TAVLTree; ANode, Node: TAVLTreeNode; CodePos: PCodeXYPosition; Files: TStringList; Completed: boolean; UGUnit: TUGUnit; begin // Step 1: load the file StartSrcCode:=CodeToolBoss.LoadFile(Filename,false,false); CheckSyntax(StartSrcCode); // Step 2: find the main declaration if not CodeToolBoss.FindMainDeclaration(StartSrcCode, X,Y, DeclCode,DeclX,DeclY,DeclTopLine) then begin writeln('FindMainDeclaration failed in '+StartSrcCode.FileName+' at '+IntToStr(Y)+':'+IntToStr(X)); ExitCode:=-1; exit; end; CheckSyntax(DeclCode); // Step 3: get identifier CodeToolBoss.GetIdentifierAt(DeclCode,DeclX,DeclY,Identifier); writeln('Found identifier: ',Identifier); // Step 4: collect all modules of program Files:=TStringList.Create; ListOfPCodeXYPosition:=nil; TreeOfPCodeXYPosition:=nil; Cache:=nil; try Files.Add(DeclCode.Filename); if CompareFilenames(DeclCode.Filename,StartSrcCode.Filename)<>0 then Files.Add(DeclCode.Filename); // parse all used units Graph:=CodeToolBoss.CreateUsesGraph; try Graph.AddStartUnit(MainFilename); Graph.AddTargetUnit(DeclCode.Filename); Graph.Parse(true,Completed); Node:=Graph.FilesTree.FindLowest; while Node<>nil do begin UGUnit:=TUGUnit(Node.Data); Files.Add(UGUnit.Filename); Node:=Node.Successor; end; finally Graph.Free; end; // Step 5: find references in all files writeln(Files.count, ' in unit graph'); for i:=0 to Files.Count-1 do begin writeln('searching ', Files[i], '...'); Code:=CodeToolBoss.LoadFile(Files[i],true,false); if Code=nil then begin writeln('unable to load "',Files[i],'"'); continue; end; // check Syntax CheckSyntax(Code); // search references CodeToolBoss.FreeListOfPCodeXYPosition(ListOfPCodeXYPosition); if not CodeToolBoss.FindReferences( DeclCode,DeclX,DeclY, Code, true, ListOfPCodeXYPosition, Cache) then begin writeln('FindReferences failed in "'+Code.Filename+'"'); continue; end; if ListOfPCodeXYPosition=nil then continue; // In order to show all references after any parser error, they are // collected in a tree if TreeOfPCodeXYPosition=nil then TreeOfPCodeXYPosition:=CodeToolBoss.CreateTreeOfPCodeXYPosition; CodeToolBoss.AddListToTreeOfPCodeXYPosition(ListOfPCodeXYPosition, TreeOfPCodeXYPosition,true,false); end; // Step 6: show references if TreeOfPCodeXYPosition=nil then begin // No references found exit; end; ANode:=TreeOfPCodeXYPosition.FindHighest; while ANode<>nil do begin CodePos:=PCodeXYPosition(ANode.Data); writeln(' found: ', CodePos^.Code.Filename, ' @ ', CodePos^.Y, ',',CodePos^.X); ANode:=TreeOfPCodeXYPosition.FindPrecessor(ANode); end; finally Files.Free; CodeToolBoss.FreeListOfPCodeXYPosition(ListOfPCodeXYPosition); CodeToolBoss.FreeTreeOfPCodeXYPosition(TreeOfPCodeXYPosition); Cache.Free; end; end; var Path, ProgramPath: String; begin ChDir('/Users/ryanjoseph/Developer/Projects/FPC/TestCodeTools'); InitCodeTools([ '-Fu'+ExpandFileName('./test/units'), '-Fi'+ExpandFileName('./test/include') ]); ProgramPath := ExpandFileName('./test/test.pas'); Path := ProgramPath; writeln('main program: ', ProgramPath); FindReferences(Path, ProgramPath, 11, 13); end. Regards, Ryan Joseph _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal