mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-25 17:49:05 +02:00
codetools: tests for star directory
This commit is contained in:
parent
a6696145cd
commit
427ba37baf
components/codetools
@ -384,6 +384,12 @@ type
|
||||
function GetNamespacesForDirectory(const Directory: string;
|
||||
UseCache: boolean = true): string;// value of macro #Namespaces
|
||||
|
||||
// simple global defines for tests and simple projects
|
||||
function GetGlobalDefines(CreateIfNotExists: boolean = true): TDefineTemplate;
|
||||
function SetGlobalPath(const DefName, Description, MacroName, SearchPath: string): TDefineTemplate;
|
||||
function SetGlobalUnitPath(const UnitPath: string): TDefineTemplate;
|
||||
function SetGlobalIncludePath(const IncludePath: string): TDefineTemplate;
|
||||
|
||||
// miscellaneous
|
||||
property OnGetMethodName: TOnGetMethodname read FOnGetMethodName
|
||||
write FOnGetMethodName;
|
||||
@ -1772,6 +1778,47 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.GetGlobalDefines(CreateIfNotExists: boolean
|
||||
): TDefineTemplate;
|
||||
begin
|
||||
Result:=DefineTree.FindDefineTemplateByName(StdDefTemplGlobal,true);
|
||||
if (Result=nil) and CreateIfNotExists then begin
|
||||
Result:=TDefineTemplate.Create(StdDefTemplGlobal,'Global definitions','','',da_Block);
|
||||
DefineTree.AddFirst(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.SetGlobalPath(const DefName, Description, MacroName,
|
||||
SearchPath: string): TDefineTemplate;
|
||||
var
|
||||
GlobalDef: TDefineTemplate;
|
||||
NewValue: String;
|
||||
begin
|
||||
GlobalDef:=GetGlobalDefines;
|
||||
Result:=GlobalDef.FindChildByName(DefName);
|
||||
NewValue:='$('+MacroName+');'+SearchPath;
|
||||
if Result=nil then begin
|
||||
Result:=TDefineTemplate.Create(DefName,Description,MacroName,
|
||||
NewValue,da_DefineRecurse);
|
||||
end else if Result.Value=NewValue then
|
||||
exit
|
||||
else
|
||||
Result.Value:=NewValue;
|
||||
DefineTree.ClearCache;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.SetGlobalUnitPath(const UnitPath: string
|
||||
): TDefineTemplate;
|
||||
begin
|
||||
Result:=SetGlobalPath('UnitPath','Unit search path',UnitPathMacroName,UnitPath);
|
||||
end;
|
||||
|
||||
function TCodeToolManager.SetGlobalIncludePath(const IncludePath: string
|
||||
): TDefineTemplate;
|
||||
begin
|
||||
Result:=SetGlobalPath('IncPath','Include search path',IncludePathMacroName,IncludePath);
|
||||
end;
|
||||
|
||||
procedure TCodeToolManager.FreeListOfPCodeXYPosition(var List: TFPList);
|
||||
begin
|
||||
CodeCache.FreeListOfPCodeXYPosition(List);
|
||||
|
@ -66,6 +66,7 @@ const
|
||||
ExternalMacroStart = ExprEval.ExternalMacroStart;
|
||||
|
||||
// Standard Template Names (do not translate them)
|
||||
StdDefTemplGlobal = 'Global';
|
||||
StdDefTemplFPC = 'Free Pascal Compiler';
|
||||
StdDefTemplFPCSrc = 'Free Pascal sources';
|
||||
StdDefTemplLazarusSources = 'Lazarus sources';
|
||||
@ -644,6 +645,7 @@ type
|
||||
procedure Move(SrcIndex, DestIndex: integer);
|
||||
property EnglishErrorMsgFilename: string
|
||||
read FEnglishErrorMsgFilename write SetEnglishErrorMsgFilename;
|
||||
|
||||
// FPC templates
|
||||
function CreateFPCTemplate(const CompilerPath, CompilerOptions,
|
||||
TestPascalFile: string;
|
||||
@ -6224,9 +6226,12 @@ begin
|
||||
end;
|
||||
|
||||
procedure TDefinePool.Delete(Index: integer);
|
||||
var
|
||||
Def: TDefineTemplate;
|
||||
begin
|
||||
Items[Index].Clear(true);
|
||||
Items[Index].Free;
|
||||
Def:=Items[Index];
|
||||
Def.Clear(true);
|
||||
Def.Free;
|
||||
FItems.Delete(Index);
|
||||
end;
|
||||
|
||||
|
@ -178,7 +178,7 @@ type
|
||||
const FileCase: TCTSearchFileCase): string; virtual; abstract;
|
||||
function FindIncludeFile(const IncFilename: string; AnyCase: boolean): string; virtual; abstract;
|
||||
function FindUnitSource(const AUnitName: string; AnyCase: boolean): string; virtual; abstract;
|
||||
property Directory: string read FDirectory;
|
||||
property Directory: string read FDirectory; // with trailing pathdelim
|
||||
property Pool: TCTDirectoryCachePool read FPool;
|
||||
end;
|
||||
|
||||
@ -201,8 +201,7 @@ type
|
||||
procedure AddToCache(const UnitSrc: TCTDirectoryUnitSources;
|
||||
const Search, Filename: string);
|
||||
public
|
||||
constructor Create(const TheDirectory: string;
|
||||
ThePool: TCTDirectoryCachePool);
|
||||
constructor Create(const TheDirectory: string; ThePool: TCTDirectoryCachePool);
|
||||
destructor Destroy; override;
|
||||
procedure CalcMemSize(Stats: TCTMemStats); override;
|
||||
procedure Reference;
|
||||
@ -211,23 +210,27 @@ type
|
||||
function IndexOfFileCaseSensitive(ShortFilename: PChar): integer; override;
|
||||
function FindFile(const ShortFilename: string;
|
||||
const FileCase: TCTSearchFileCase): string; override;
|
||||
function FindIncludeFile(const IncFilename: string; AnyCase: boolean
|
||||
): string; override;
|
||||
function FileAge(const ShortFilename: string): TCTFileAgeTime;
|
||||
function FileAttr(const ShortFilename: string): TCTDirectoryListingAttr;
|
||||
function FileSize(const ShortFilename: string): TCTDirectoryListingSize;
|
||||
// unit link (for fpc ppu files to fpc src file)
|
||||
function FindUnitLink(const AUnitName: string): string;
|
||||
function FindUnitInUnitSet(const AUnitName: string;
|
||||
SrcSearchRequiresPPU: boolean = true): string;
|
||||
function FindCompiledUnitInUnitSet(const AUnitName: string): string;
|
||||
function FindUnitInUnitSet(const AUnitName: string; SrcSearchRequiresPPU: boolean = true): string;
|
||||
// find unit source
|
||||
function FindUnitSource(const AUnitName: string; AnyCase: boolean): string; override;
|
||||
function FindUnitSourceInCleanSearchPath(const AUnitName,
|
||||
SearchPath: string; AnyCase: boolean): string; // search in unitpath
|
||||
function FindUnitSourceInCompletePath(var AUnitName, InFilename: string; // search in unitpath and unitpaths of output dirs
|
||||
AnyCase: boolean; FPCSrcSearchRequiresPPU: boolean = false;
|
||||
const AddNameSpaces: string = ''): string;
|
||||
function FindCompiledUnitInCompletePath(const AnUnitname: string;
|
||||
AnyCase: boolean): string;
|
||||
// find ppu/dcu file
|
||||
function FindCompiledUnitInUnitSet(const AUnitName: string): string;
|
||||
function FindCompiledUnitInCompletePath(const AnUnitname: string; AnyCase: boolean): string;
|
||||
// include files
|
||||
function FindIncludeFile(const IncFilename: string; AnyCase: boolean): string; override;
|
||||
function FindIncludeFileInPath(IncFilename: string; AnyCase: boolean): string;
|
||||
function FindIncludeFileInCleanPath(IncFilename, SearchPath: string; AnyCase: boolean): string;
|
||||
|
||||
procedure IterateFPCUnitsInSet(const Iterate: TCTOnIterateFile);
|
||||
procedure UpdateListing;
|
||||
procedure WriteListing;
|
||||
@ -239,7 +242,7 @@ type
|
||||
property Listing: TCTDirectoryListing read FListing;
|
||||
end;
|
||||
|
||||
{ TCTStarDirectoryCache }
|
||||
{ TCTStarDirectoryCache - a cache for a directory and its sub directories, e.g. searching in '/foo/**' }
|
||||
|
||||
TCTStarDirectoryCache = class(TCTDirectoryBaseCache)
|
||||
private
|
||||
@ -346,8 +349,10 @@ type
|
||||
const Iterate: TCTOnIterateFile);
|
||||
function FindDiskFilename(const Filename: string;
|
||||
{%H-}SearchCaseInsensitive: boolean = false): string; // using Pascal case insensitivity, not UTF-8
|
||||
function FindIncludeFileInDirectory(const Directory, IncFileName: string;
|
||||
function FindIncludeFileInDirectory(Directory, IncFileName: string;
|
||||
AnyCase: boolean = false): string;
|
||||
function FindIncludeFileInCompletePath(Directory, IncFilename: string;
|
||||
AnyCase: boolean = false): string;
|
||||
function FindUnitInDirectory(const Directory, AUnitName: string;
|
||||
AnyCase: boolean = false): string;
|
||||
function FindVirtualFile(const Filename: string): string;
|
||||
@ -378,7 +383,7 @@ function CompareCTDirectoryCaches(Data1, Data2: Pointer): integer;
|
||||
function CompareAnsiStringAndDirectoryCache(Dir, Cache: Pointer): integer;
|
||||
|
||||
function ComparePCharFirstCaseInsAThenCase(Data1, Data2: Pointer): integer; // insensitive ASCII then byte wise
|
||||
function ComparePCharCaseInsensitiveA(Data1, Data2: Pointer): integer; // insensitive ASCII
|
||||
function ComparePCharCaseInsensitiveASCII(Data1, Data2: Pointer): integer; // insensitive ASCII
|
||||
function ComparePCharCaseSensitive(Data1, Data2: Pointer): integer; // byte wise
|
||||
|
||||
// star directories
|
||||
@ -465,12 +470,12 @@ end;
|
||||
|
||||
function ComparePCharFirstCaseInsAThenCase(Data1, Data2: Pointer): integer;
|
||||
begin
|
||||
Result:=ComparePCharCaseInsensitiveA(Data1,Data2);
|
||||
Result:=ComparePCharCaseInsensitiveASCII(Data1,Data2);
|
||||
if Result=0 then
|
||||
Result:=ComparePCharCaseSensitive(Data1,Data2);
|
||||
end;
|
||||
|
||||
function ComparePCharCaseInsensitiveA(Data1, Data2: Pointer): integer;
|
||||
function ComparePCharCaseInsensitiveASCII(Data1, Data2: Pointer): integer;
|
||||
var
|
||||
p1: PChar absolute Data1;
|
||||
p2: PChar absolute Data2;
|
||||
@ -482,7 +487,7 @@ begin
|
||||
Result:=ord(FPUpChars[p1^])-ord(FPUpChars[p2^]);
|
||||
end;
|
||||
|
||||
function ComparePCharCaseInsensitiveA(Data1, Data2: Pointer; MaxCount: PtrInt): integer;
|
||||
function ComparePCharCaseInsensitiveASCII(Data1, Data2: Pointer; MaxCount: PtrInt): integer;
|
||||
var
|
||||
p1: PChar absolute Data1;
|
||||
p2: PChar absolute Data2;
|
||||
@ -543,6 +548,59 @@ begin
|
||||
until false;
|
||||
end;
|
||||
|
||||
function CheckLoUpCase(Find, Candidate: PChar; MaxCount: PtrInt): boolean;
|
||||
var
|
||||
i: PtrInt;
|
||||
CurFind, CurCandidate: PChar;
|
||||
c: Char;
|
||||
begin
|
||||
// check case sensitive
|
||||
CurFind:=Find;
|
||||
CurCandidate:=Candidate;
|
||||
i:=0;
|
||||
repeat
|
||||
if i=MaxCount then exit(true);
|
||||
if (CurFind^<>CurCandidate^) then break;
|
||||
if CurFind^=#0 then exit(true);
|
||||
inc(i);
|
||||
inc(CurFind);
|
||||
inc(CurCandidate);
|
||||
until false;
|
||||
|
||||
// check lowercase Find
|
||||
CurFind:=Find;
|
||||
CurCandidate:=Candidate;
|
||||
i:=0;
|
||||
repeat
|
||||
if i=MaxCount then exit(true);
|
||||
c:=CurFind^;
|
||||
case c of
|
||||
'A'..'Z':
|
||||
if ord(c)+32<>ord(CurCandidate^) then break;
|
||||
else if c<>CurCandidate^ then break;
|
||||
end;
|
||||
if CurFind^=#0 then exit(true);
|
||||
inc(i);
|
||||
inc(CurFind);
|
||||
inc(CurCandidate);
|
||||
until false;
|
||||
|
||||
// check uppercase Find
|
||||
CurFind:=Find;
|
||||
CurCandidate:=Candidate;
|
||||
i:=0;
|
||||
repeat
|
||||
if i=MaxCount then exit(true);
|
||||
if (FPUpChars[CurFind^]<>CurCandidate^) then break;
|
||||
if CurFind^=#0 then exit(true);
|
||||
inc(i);
|
||||
inc(CurFind);
|
||||
inc(CurCandidate);
|
||||
until false;
|
||||
|
||||
Result:=false;
|
||||
end;
|
||||
|
||||
function IsCTStarDirectory(const Directory: string; out p: integer
|
||||
): TCTStarDirectoryKind;
|
||||
var
|
||||
@ -598,7 +656,7 @@ begin
|
||||
ComparePCharCaseInsensitiveA(Pointer(TheUnitName),@UnitLinks[UnitLinkStart],UnitLinkLen)]);
|
||||
{$ENDIF}
|
||||
if (UnitLinkLen=length(TheUnitName))
|
||||
and (ComparePCharCaseInsensitiveA(Pointer(TheUnitName),@UnitLinks[UnitLinkStart],
|
||||
and (ComparePCharCaseInsensitiveASCII(Pointer(TheUnitName),@UnitLinks[UnitLinkStart],
|
||||
UnitLinkLen)=0)
|
||||
then begin
|
||||
// unit found -> parse filename
|
||||
@ -966,7 +1024,7 @@ begin
|
||||
while l<=r do begin
|
||||
m:=(l+r) shr 1;
|
||||
CurFilename:=@Files[FListing.Starts[m]+DirListNameOffset];
|
||||
cmp:=ComparePCharCaseInsensitiveA(ShortFilename,CurFilename);
|
||||
cmp:=ComparePCharCaseInsensitiveASCII(ShortFilename,CurFilename);
|
||||
if cmp>0 then
|
||||
l:=m+1
|
||||
else if cmp<0 then
|
||||
@ -1114,11 +1172,11 @@ end;
|
||||
function TCTDirectoryCache.FindIncludeFile(const IncFilename: string;
|
||||
AnyCase: boolean): string;
|
||||
var
|
||||
Files, CurFilename, IncExtP, CurExtP: PChar;
|
||||
Files, CurFilename, IncExtP, CurExtP, IncFilenameP: PChar;
|
||||
Starts: PInteger;
|
||||
l, r, m, first, cmp, Best: Integer;
|
||||
AUnitName: String;
|
||||
Fits: Boolean;
|
||||
Stop: Boolean;
|
||||
Ext, BestExt: TCTPascalIncExtType;
|
||||
begin
|
||||
Result:='';
|
||||
@ -1126,6 +1184,9 @@ begin
|
||||
//if (CompareText(AUnitName,DebugUnitName)=0) and (System.Pos(DebugDirPart,directory)>0) then
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFile IncName="',IncFilename,'" AnyCase=',dbgs(AnyCase),' Directory=',Directory);
|
||||
{$ENDIF}
|
||||
{$IFDEF CaseInsensitiveFilenames}
|
||||
AnyCase:=true;
|
||||
{$ENDIF}
|
||||
if IncFilename='' then exit;
|
||||
if Directory<>'' then begin
|
||||
UpdateListing;
|
||||
@ -1133,13 +1194,10 @@ begin
|
||||
if Files=nil then exit;
|
||||
Starts:=FListing.Starts;
|
||||
|
||||
// AnyCase:
|
||||
// search IncFilename
|
||||
// if IncFilename has no ext, then seach IncFilename.inc, IncFilename.pp, IncFilename.pas
|
||||
// not AnyCase:
|
||||
// search IncFilename
|
||||
// if IncFilename has no ext, then seach IncFilename.inc, IncFilename.pp, IncFilename.pas
|
||||
// first search IncFilename
|
||||
// if IncFilename has no ext, then seach IncFilename.inc, IncFilename.pp, IncFilename.pas
|
||||
|
||||
IncFilenameP:=PChar(IncFilename);
|
||||
l:=length(IncFilename);
|
||||
while (l>0) and (IncFilename[l]<>'.') do dec(l);
|
||||
if l>0 then begin
|
||||
@ -1187,54 +1245,41 @@ begin
|
||||
CurExtP:=CurFilename+length(AUnitname);
|
||||
{$IFDEF DebugDirCacheFindIncFile}
|
||||
//if (CompareText(AUnitName,DebugUnitName)=0) and (System.Pos(DebugDirPart,directory)>0) then
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFile NEXT "',CurFilename,'" ExtStart=',dbgstr(CurExt^));
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFile NEXT "',CurFilename,'" ExtStart=',dbgstr(CurExtP^));
|
||||
{$ENDIF}
|
||||
Fits:=false;
|
||||
Stop:=false;
|
||||
if IncExtP<>nil then begin
|
||||
// include file with extension
|
||||
if ComparePCharCaseInsensitiveA(CurExtP,IncExtP)=0 then
|
||||
Fits:=true;
|
||||
end else begin
|
||||
// include file without extension -> search without and default extension
|
||||
if (CurExtP^=#0) then begin
|
||||
Fits:=true;
|
||||
Ext:=pietNone;
|
||||
end else begin
|
||||
Ext:=IsPascalIncExt(IncExtP);
|
||||
Fits:=Ext>pietNone;
|
||||
end;
|
||||
end;
|
||||
if Fits then begin
|
||||
// the extension fits -> check case
|
||||
Result:=CurFilename;
|
||||
{$IFDEF DebugDirCacheFindIncFile}
|
||||
//if (CompareText(AUnitName,DebugUnitName)=0) and (System.Pos(DebugDirPart,directory)>0) then
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFile CHECKING CASE "',CurFilename,'"');
|
||||
{$ENDIF}
|
||||
if AnyCase then begin
|
||||
if ComparePCharCaseInsensitiveASCII(CurExtP,IncExtP)=0 then
|
||||
// any case with extension fits -> can't get any better
|
||||
Stop:=true;
|
||||
end else if CheckLoUpCase(IncFilenameP,CurFilename,length(IncFilename)+1) then
|
||||
Stop:=true; // mixed case with extension fits -> can't get any better
|
||||
end else begin
|
||||
// include file without extension -> search without and with default extension
|
||||
if (CurExtP^=#0) then begin
|
||||
if AnyCase or CheckLoUpCase(IncFilenameP,CurFilename,length(IncFilename)+1) then
|
||||
// file without extension fits a file without extension -> can't get any better
|
||||
Stop:=true;
|
||||
end else begin
|
||||
// check case platform dependent
|
||||
{$IFDEF CaseInsensitiveFilenames}
|
||||
{$ELSE}
|
||||
if (LeftStr(Result,length(AUnitName))<>AUnitName)
|
||||
and (Result<>lowercase(Result))
|
||||
and (Result<>uppercase(Result)) then
|
||||
Fits:=false;
|
||||
{$ENDIF}
|
||||
end;
|
||||
if Fits then begin
|
||||
if IncExtP<>nil then begin
|
||||
// include file with extension -> found
|
||||
exit;
|
||||
end else begin
|
||||
// include file without extension -> search best extension
|
||||
Ext:=IsPascalIncExt(CurExtP);
|
||||
if Ext>pietNone then begin
|
||||
// file without extension fits an include file with extension
|
||||
// Note: the compiler prefers file.inc over file.pas
|
||||
if (Best<0) or (BestExt>Ext) then begin
|
||||
Best:=m;
|
||||
BestExt:=Ext;
|
||||
if AnyCase or CheckLoUpCase(IncFilenameP,CurFilename,length(IncFilename)) then begin
|
||||
Best:=m;
|
||||
BestExt:=Ext;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if Stop then begin
|
||||
Best:=m;
|
||||
break;
|
||||
end;
|
||||
inc(m);
|
||||
end;
|
||||
if Best>=0 then begin
|
||||
@ -1256,6 +1301,71 @@ begin
|
||||
Result:='';
|
||||
end;
|
||||
|
||||
function TCTDirectoryCache.FindIncludeFileInPath(IncFilename: string;
|
||||
AnyCase: boolean): string;
|
||||
var
|
||||
HasPathDelims: Boolean;
|
||||
SearchPath: String;
|
||||
begin
|
||||
Result:='';
|
||||
{$IFDEF DebugDirCacheFindIncFile}
|
||||
//if (CompareText(AUnitName,DebugUnitName)=0) and (System.Pos(DebugDirPart,directory)>0) then
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFileInPath IncName="',IncFilename,'" AnyCase=',dbgs(AnyCase),' Directory=',Directory);
|
||||
{$ENDIF}
|
||||
if IncFilename='' then exit;
|
||||
|
||||
IncFilename:=ResolveDots(IncFilename);
|
||||
|
||||
HasPathDelims:=(System.Pos('/',IncFilename)>0) or (System.Pos('\',IncFilename)>0);
|
||||
if HasPathDelims then begin
|
||||
Result:=Pool.FindIncludeFileInCompletePath(Directory,IncFilename,AnyCase);
|
||||
exit;
|
||||
end;
|
||||
|
||||
SearchPath:=Strings[ctdcsIncludePath];
|
||||
Result:=FindIncludeFileInCleanPath(IncFilename,SearchPath,AnyCase);
|
||||
end;
|
||||
|
||||
function TCTDirectoryCache.FindIncludeFileInCleanPath(IncFilename,
|
||||
SearchPath: string; AnyCase: boolean): string;
|
||||
var
|
||||
StartPos, p: Integer;
|
||||
l: SizeInt;
|
||||
CurPath: String;
|
||||
IsAbsolute, HasPathDelims: Boolean;
|
||||
begin
|
||||
Result:='';
|
||||
HasPathDelims:=(System.Pos('/',IncFilename)>0) or (System.Pos('\',IncFilename)>0);
|
||||
if HasPathDelims then
|
||||
exit;
|
||||
|
||||
StartPos:=1;
|
||||
l:=length(SearchPath);
|
||||
while StartPos<=l do begin
|
||||
p:=StartPos;
|
||||
while (p<=l) and (SearchPath[p]<>';') do inc(p);
|
||||
CurPath:=Trim(copy(SearchPath,StartPos,p-StartPos));
|
||||
if CurPath<>'' then begin
|
||||
IsAbsolute:=FilenameIsAbsolute(CurPath);
|
||||
if (not IsAbsolute) and (Directory<>'') then begin
|
||||
CurPath:=Directory+CurPath;
|
||||
IsAbsolute:=true;
|
||||
end;
|
||||
//DebugLn('TCTDirectoryCache.FindIncludeFileInCleanPath CurPath="',CurPath,'"');
|
||||
if IsAbsolute then begin
|
||||
CurPath:=AppendPathDelim(CurPath);
|
||||
Result:=Pool.FindIncludeFileInDirectory(CurPath,IncFilename,AnyCase);
|
||||
end else if (CurPath='.') and (Directory='') then
|
||||
Result:=Pool.FindVirtualInclude(IncFilename)
|
||||
else
|
||||
Result:='';
|
||||
if Result<>'' then exit;
|
||||
end;
|
||||
StartPos:=p+1;
|
||||
end;
|
||||
Result:='';
|
||||
end;
|
||||
|
||||
function TCTDirectoryCache.FileAge(const ShortFilename: string): TCTFileAgeTime;
|
||||
var
|
||||
i: Integer;
|
||||
@ -1764,13 +1874,13 @@ end;
|
||||
function TCTStarDirectoryCache.FindIncludeFile(const IncFilename: string;
|
||||
AnyCase: boolean): string;
|
||||
var
|
||||
Files, CurFilename, IncExtP, CurExtP: PChar;
|
||||
Files, IncExtP, CurExtP, CurFilename, IncFilenameP: PChar;
|
||||
Starts: PInteger;
|
||||
l, r, m, first, cmp, DirIndex: TListingPosition;
|
||||
l, r, m, first, cmp: TListingPosition;
|
||||
AUnitName: String;
|
||||
Fits: Boolean;
|
||||
Ext, BestExt: TCTPascalIncExtType;
|
||||
BestDirIndex, Best: Integer;
|
||||
Best: Integer;
|
||||
Stop: Boolean;
|
||||
begin
|
||||
Result:='';
|
||||
{$IFDEF DebugDirCacheFindIncFile}
|
||||
@ -1783,6 +1893,7 @@ begin
|
||||
if Files=nil then exit;
|
||||
Starts:=FListing.Starts;
|
||||
|
||||
IncFilenameP:=PChar(IncFilename);
|
||||
l:=length(IncFilename);
|
||||
while (l>0) and (IncFilename[l]<>'.') do dec(l);
|
||||
if l>0 then begin
|
||||
@ -1817,7 +1928,6 @@ begin
|
||||
m:=first;
|
||||
// -> now find a filename with correct case and extension
|
||||
Best:=-1;
|
||||
BestDirIndex:=-1;
|
||||
BestExt:=high(TCTPascalIncExtType);
|
||||
while m<FListing.Count do begin
|
||||
CurFilename:=@Files[Starts[m]+SizeOf(TListingHeader)];
|
||||
@ -1830,61 +1940,41 @@ begin
|
||||
CurExtP:=CurFilename+length(AUnitname);
|
||||
{$IFDEF DebugDirCacheFindIncFile}
|
||||
//if (CompareText(AUnitName,DebugUnitName)=0) and (System.Pos(DebugDirPart,directory)>0) then
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFile NEXT "',CurFilename,'" ExtStart=',dbgstr(CurExt^));
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFile NEXT "',CurFilename,'" ExtStart=',dbgstr(CurExtP^));
|
||||
{$ENDIF}
|
||||
Fits:=false;
|
||||
Stop:=false;
|
||||
if IncExtP<>nil then begin
|
||||
// include file with extension
|
||||
if ComparePCharCaseInsensitiveA(CurExtP,IncExtP)=0 then
|
||||
Fits:=true;
|
||||
end else begin
|
||||
// include file without extension -> search without and default extension
|
||||
if (CurExtP^=#0) then begin
|
||||
Fits:=true;
|
||||
Ext:=pietNone;
|
||||
end else begin
|
||||
Ext:=IsPascalIncExt(IncExtP);
|
||||
Fits:=Ext>pietNone;
|
||||
end;
|
||||
end;
|
||||
if Fits then begin
|
||||
// the extension fits -> check case
|
||||
Result:=CurFilename;
|
||||
{$IFDEF DebugDirCacheFindIncFile}
|
||||
//if (CompareText(AUnitName,DebugUnitName)=0) and (System.Pos(DebugDirPart,directory)>0) then
|
||||
DebugLn('TCTDirectoryCache.FindIncludeFile CHECKING CASE "',CurFilename,'"');
|
||||
{$ENDIF}
|
||||
if AnyCase then begin
|
||||
if ComparePCharCaseInsensitiveASCII(CurExtP,IncExtP)=0 then
|
||||
// any case with extension fits -> can't get any better
|
||||
Stop:=true;
|
||||
end else if CheckLoUpCase(IncFilenameP,CurFilename,length(IncFilename)+1) then
|
||||
Stop:=true; // mixed case with extension fits -> can't get any better
|
||||
end else begin
|
||||
// include file without extension -> search without and with default extension
|
||||
if (CurExtP^=#0) then begin
|
||||
if AnyCase or CheckLoUpCase(IncFilenameP,CurFilename,length(IncFilename)+1) then
|
||||
// file without extension fits a file without extension -> can't get any better
|
||||
Stop:=true;
|
||||
end else begin
|
||||
// check case platform dependent
|
||||
{$IFDEF CaseInsensitiveFilenames}
|
||||
{$ELSE}
|
||||
if (LeftStr(Result,length(AUnitName))<>AUnitName)
|
||||
and (Result<>lowercase(Result))
|
||||
and (Result<>uppercase(Result)) then
|
||||
Fits:=false;
|
||||
{$ENDIF}
|
||||
end;
|
||||
if Fits then begin
|
||||
if IncExtP<>nil then begin
|
||||
// include file with extension -> found
|
||||
Result:=FListing.GetSubDirFilename(m);
|
||||
exit;
|
||||
end else begin
|
||||
// include file without extension
|
||||
// the first in inc path wins
|
||||
// filename.inc is better than filename.pas
|
||||
DirIndex:=FListing.GetSubDirIndex(m);
|
||||
if (Best<0)
|
||||
or (BestDirIndex>DirIndex)
|
||||
or ((BestDirIndex=DirIndex) and (BestExt>Ext)) then
|
||||
begin
|
||||
Best:=m;
|
||||
BestExt:=Ext;
|
||||
Ext:=IsPascalIncExt(CurExtP);
|
||||
if Ext>pietNone then begin
|
||||
// file without extension fits an include file with extension
|
||||
// Note: the compiler prefers file.inc over file.pas
|
||||
if (Best<0) or (BestExt>Ext) then begin
|
||||
if AnyCase or CheckLoUpCase(IncFilenameP,CurFilename,length(IncFilename)) then begin
|
||||
Best:=m;
|
||||
BestExt:=Ext;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if Stop then begin
|
||||
Best:=m;
|
||||
break;
|
||||
end;
|
||||
inc(m);
|
||||
end;
|
||||
if Best>=0 then begin
|
||||
@ -2012,7 +2102,7 @@ begin
|
||||
while l<=r do begin
|
||||
m:=(l+r) shr 1;
|
||||
CurFilename:=@Files[FListing.Starts[m]+SizeOf(TListingHeader)];
|
||||
cmp:=ComparePCharCaseInsensitiveA(ShortFilename,CurFilename);
|
||||
cmp:=ComparePCharCaseInsensitiveASCII(ShortFilename,CurFilename);
|
||||
if cmp>0 then
|
||||
l:=m+1
|
||||
else if cmp<0 then
|
||||
@ -2065,13 +2155,19 @@ var
|
||||
WorkingListingCount: integer;
|
||||
WorkingListingCapacity: integer;
|
||||
|
||||
procedure TraverseDir(const CurSubDir: string; SubDirIndex, Level: integer);
|
||||
procedure TraverseDir(const CurSubDir: string; Level: integer);
|
||||
var
|
||||
SubDirIndex: TListingPosition;
|
||||
Dir: TCTDirectoryCache;
|
||||
DirListing: TCTDirectoryListing;
|
||||
i, NewCapacity: Integer;
|
||||
WorkingItem: PWorkStarFileInfo;
|
||||
begin
|
||||
if Level=0 then
|
||||
SubDirIndex:=-1
|
||||
else
|
||||
SubDirIndex:=FListing.SubDirs.Add(CurSubDir);
|
||||
|
||||
Dir:=Pool.GetCache(Directory+CurSubDir,true,false);
|
||||
Dir.UpdateListing;
|
||||
DirListing:=Dir.Listing;
|
||||
@ -2086,7 +2182,7 @@ var
|
||||
if WorkingListingCapacity>0 then
|
||||
NewCapacity:=WorkingListingCapacity*2
|
||||
else
|
||||
NewCapacity:=256;
|
||||
NewCapacity:=128;
|
||||
ReAllocMem(WorkingListing,SizeOf(TWorkStarFileInfo)*NewCapacity);
|
||||
FillByte(WorkingListing[WorkingListingCount],
|
||||
SizeOf(TWorkStarFileInfo)*(NewCapacity-WorkingListingCapacity),0);
|
||||
@ -2108,8 +2204,10 @@ var
|
||||
for i:=0 to DirListing.Count-1 do begin
|
||||
if DirListing.GetAttr(i) and faDirectory=0 then continue;
|
||||
// add sub directory
|
||||
SubDirIndex:=FListing.SubDirs.Add(CurSubDir);
|
||||
TraverseDir(CurSubDir+PathDelim+DirListing.GetFilename(i),SubDirIndex,Level);
|
||||
if Level=1 then
|
||||
TraverseDir(DirListing.GetFilename(i),Level)
|
||||
else
|
||||
TraverseDir(CurSubDir+PathDelim+DirListing.GetFilename(i),Level);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2131,7 +2229,7 @@ begin
|
||||
WorkingListingCount:=0;
|
||||
WorkingListingCapacity:=0;
|
||||
try
|
||||
TraverseDir('',-1,0);
|
||||
TraverseDir('',0);
|
||||
|
||||
if WorkingListingCount=0 then exit;
|
||||
|
||||
@ -2175,11 +2273,11 @@ end;
|
||||
procedure TCTStarDirectoryCache.WriteListing;
|
||||
var
|
||||
i: Integer;
|
||||
Filename: PChar;
|
||||
Filename: String;
|
||||
begin
|
||||
writeln('TCTStarDirectoryCache.WriteListing Count=',FListing.Count,' Size=',FListing.Size);
|
||||
for i:=0 to FListing.Count-1 do begin
|
||||
Filename:=FListing.GetShortFilename(i);
|
||||
Filename:=FListing.GetSubDirFilename(i);
|
||||
writeln(i,' "',Filename,'"');
|
||||
end;
|
||||
end;
|
||||
@ -2285,7 +2383,7 @@ begin
|
||||
if (Index<0) or (Index>=Count) then
|
||||
RaiseIndexOutOfBounds;
|
||||
i:=PListingHeader(@Files[Starts[Index]])^.SubDirIndex;
|
||||
if i>=0 then
|
||||
if i<0 then
|
||||
Result:=''
|
||||
else
|
||||
Result:=SubDirs[i]+PathDelim;
|
||||
@ -2417,7 +2515,7 @@ begin
|
||||
if Node<>nil then begin
|
||||
Result:=TCTStarDirectoryCache(Node.Data);
|
||||
end else if CreateIfNotExists then begin
|
||||
Dir:=FindDiskFilename(Directory);
|
||||
Dir:=AppendPathDelim(FindDiskFilename(Directory));
|
||||
Result:=TCTStarDirectoryCache.Create(Dir,Kind,Self);
|
||||
FStarDirectories[Kind].Add(Result);
|
||||
end else
|
||||
@ -2647,7 +2745,7 @@ begin
|
||||
Result:=Cache.Directory+Result;
|
||||
end;
|
||||
|
||||
function TCTDirectoryCachePool.FindIncludeFileInDirectory(const Directory,
|
||||
function TCTDirectoryCachePool.FindIncludeFileInDirectory(Directory,
|
||||
IncFileName: string; AnyCase: boolean): string;
|
||||
var
|
||||
Cache: TCTDirectoryBaseCache;
|
||||
@ -2769,6 +2867,15 @@ begin
|
||||
Result:=Cache.FindUnitSourceInCompletePath(AUnitName,InFilename,AnyCase);
|
||||
end;
|
||||
|
||||
function TCTDirectoryCachePool.FindIncludeFileInCompletePath(Directory,
|
||||
IncFilename: string; AnyCase: boolean): string;
|
||||
var
|
||||
Cache: TCTDirectoryCache;
|
||||
begin
|
||||
Cache:=GetCache(Directory,true,false);
|
||||
Result:=Cache.FindIncludeFileInPath(IncFilename,AnyCase);
|
||||
end;
|
||||
|
||||
function TCTDirectoryCachePool.FindCompiledUnitInCompletePath(
|
||||
const Directory: string; var AnUnitname: string; AnyCase: boolean): string;
|
||||
var
|
||||
|
@ -806,11 +806,13 @@ type
|
||||
function IgnoreErrorAfterValid: boolean;
|
||||
function CleanPosIsAfterIgnorePos(CleanPos: integer): boolean;
|
||||
function LoadSourceCaseLoUp(const AFilename: string; AllowVirtual: boolean = false): TSourceLog;
|
||||
function LoadIncludeFile(const AFilename: string; AllowVirtual: boolean = false): TSourceLog;
|
||||
function LoadIncludeFile(
|
||||
const AFilename: string; // epxanded filename or virtual file
|
||||
AllowVirtual: boolean = false): TSourceLog; // trying different case and extensions, does not search in include path
|
||||
class function GetPascalCompiler(Evals: TExpressionEvaluator): TPascalCompiler;
|
||||
|
||||
function SearchIncludeFile(AFilename: string; out NewCode: TSourceLog;
|
||||
var MissingIncludeFile: TMissingIncludeFile): boolean;
|
||||
var MissingIncludeFile: TMissingIncludeFile): boolean; // search in includepath
|
||||
{$IFDEF GuessMisplacedIfdef}
|
||||
function GuessMisplacedIfdefEndif(StartCursorPos: integer;
|
||||
StartCode: pointer;
|
||||
@ -818,7 +820,6 @@ type
|
||||
out EndCode: Pointer): boolean;
|
||||
{$ENDIF}
|
||||
function GetHiddenUsedUnits: string; // comma separated
|
||||
property DirectoryCachePool: TCTDirectoryCachePool read FDirectoryCachePool write FDirectoryCachePool;
|
||||
|
||||
// global write lock
|
||||
procedure ActivateGlobalWriteLock;
|
||||
@ -829,6 +830,7 @@ type
|
||||
read FOnSetGlobalWriteLock write FOnSetGlobalWriteLock;
|
||||
|
||||
// properties
|
||||
property DirectoryCachePool: TCTDirectoryCachePool read FDirectoryCachePool write FDirectoryCachePool;
|
||||
property OnLoadSource: TOnLoadSource read FOnLoadSource write FOnLoadSource;
|
||||
property OnDeleteSource: TOnDeleteSource read FOnDeleteSource write FOnDeleteSource;
|
||||
property OnGetSourceStatus: TOnGetSourceStatus
|
||||
@ -4042,7 +4044,7 @@ end;
|
||||
function TLinkScanner.LoadIncludeFile(const AFilename: string;
|
||||
AllowVirtual: boolean): TSourceLog;
|
||||
var
|
||||
Path, FileNameOnly: string;
|
||||
Path, FileNameNoPath: string;
|
||||
SecondaryFileName: String;
|
||||
|
||||
function Search(const ShortFilename: string; var r: TSourceLog): boolean;
|
||||
@ -4070,15 +4072,15 @@ begin
|
||||
Path:=ResolveDots(ExtractFilePath(AFilename));
|
||||
if (not AllowVirtual) and not FilenameIsAbsolute(Path) then
|
||||
exit(nil);
|
||||
FileNameOnly:=ExtractFilename(AFilename);
|
||||
FileNameNoPath:=ExtractFilename(AFilename);
|
||||
|
||||
if Search(FileNameOnly,Result) then exit;
|
||||
if Search(FileNameNoPath,Result) then exit;
|
||||
|
||||
if ExtractFileExt(FileNameOnly)='' then begin
|
||||
if ExtractFileExt(FileNameNoPath)='' then begin
|
||||
// search with the default file extensions
|
||||
if Search(FileNameOnly+'.inc',Result) then exit;
|
||||
if Search(FileNameOnly+'.pp',Result) then exit;
|
||||
if Search(FileNameOnly+'.pas',Result) then exit;
|
||||
if Search(FileNameNoPath+'.inc',Result) then exit;
|
||||
if Search(FileNameNoPath+'.pp',Result) then exit;
|
||||
if Search(FileNameNoPath+'.pas',Result) then exit;
|
||||
end;
|
||||
|
||||
Result:=nil;
|
||||
@ -4107,8 +4109,6 @@ end;
|
||||
function TLinkScanner.SearchIncludeFile(AFilename: string; out
|
||||
NewCode: TSourceLog; var MissingIncludeFile: TMissingIncludeFile): boolean;
|
||||
var
|
||||
IncludePath: string;
|
||||
ExpFilename: string;
|
||||
HasPathDelims: Boolean;
|
||||
|
||||
procedure SetMissingIncludeFile;
|
||||
@ -4118,90 +4118,78 @@ var
|
||||
MissingIncludeFile.IncludePath:=Values.Variables[ExternalMacroStart+'INCPATH'];
|
||||
end;
|
||||
|
||||
function SearchPath(const APath, RelFilename: string): boolean;
|
||||
begin
|
||||
Result:=false;
|
||||
if APath='' then exit;
|
||||
{$IFDEF VerboseIncludeSearch}
|
||||
DebugLn('TLinkScanner.SearchPath CurIncPath="',APath,'" / "',RelFilename,'"');
|
||||
{$ENDIF}
|
||||
ExpFilename:=AppendPathDelim(APath)+RelFilename;
|
||||
if not FilenameIsAbsolute(ExpFilename) then
|
||||
ExpFilename:=ExtractFilePath(FMainSourceFilename)+ExpFilename;
|
||||
NewCode:=LoadIncludeFile(ExpFilename);
|
||||
Result:=NewCode<>nil;
|
||||
end;
|
||||
|
||||
function Search(const RelFilename: string): boolean;
|
||||
function Search(RelFilename: string): boolean;
|
||||
var
|
||||
IsVirtualUnit: Boolean;
|
||||
Dir, CurPath: String;
|
||||
PathStart, PathEnd: integer;
|
||||
AnyCase: Boolean;
|
||||
Dir, FoundFilename: String;
|
||||
begin
|
||||
Dir:=ExtractFilePath(FMainSourceFilename);
|
||||
IsVirtualUnit:=not FilenameIsAbsolute(Dir);
|
||||
if IsVirtualUnit then begin
|
||||
// main source is virtual -> allow virtual include file
|
||||
NewCode:=LoadIncludeFile(RelFilename,true);
|
||||
Result:=(NewCode<>nil);
|
||||
if Result then exit;
|
||||
end else begin
|
||||
// main source has absolute filename
|
||||
// -> search in directory of unit
|
||||
ExpFilename:=Dir+RelFilename;
|
||||
NewCode:=LoadIncludeFile(ExpFilename);
|
||||
Result:=(NewCode<>nil);
|
||||
if Result then exit;
|
||||
AnyCase:=Values.IsDefined('PAS2JS');
|
||||
|
||||
if HasPathDelims then begin
|
||||
// find an include file with a path e.g. 'foo/bar.inc'
|
||||
// -> search in 'foo/', do not search in include path
|
||||
if Dir='' then begin
|
||||
// searching in virtual directory is not yet supported
|
||||
exit(false);
|
||||
end;
|
||||
|
||||
Dir:=ResolveDots(Dir+ExtractFilePath(RelFilename));
|
||||
RelFilename:=ExtractFileName(RelFilename);
|
||||
FoundFilename:=DirectoryCachePool.FindIncludeFileInDirectory(Dir,RelFilename,AnyCase);
|
||||
if FoundFilename<>'' then begin
|
||||
{$IFDEF VerboseIncludeSearch}
|
||||
DebugLn('TLinkScanner.Search Filename="',AFilename,'" Found="',FoundFilename,'"');
|
||||
{$ENDIF}
|
||||
NewCode:=FOnLoadSource(Self,FoundFilename,true);
|
||||
if (NewCode<>nil) then
|
||||
exit(true);
|
||||
end;
|
||||
exit(false);
|
||||
end;
|
||||
|
||||
// search in dir of unit
|
||||
FoundFilename:=DirectoryCachePool.FindIncludeFileInDirectory(Dir,RelFilename,AnyCase);
|
||||
if FoundFilename<>'' then begin
|
||||
{$IFDEF VerboseIncludeSearch}
|
||||
DebugLn('TLinkScanner.Search Filename="',AFilename,'" Found="',FoundFilename,'"');
|
||||
{$ENDIF}
|
||||
NewCode:=FOnLoadSource(Self,FoundFilename,true);
|
||||
if (NewCode<>nil) then
|
||||
exit(true);
|
||||
end;
|
||||
|
||||
// search in include path
|
||||
FoundFilename:=DirectoryCachePool.FindIncludeFileInCompletePath(Dir,RelFilename,AnyCase);
|
||||
if FoundFilename<>'' then begin
|
||||
{$IFDEF VerboseIncludeSearch}
|
||||
DebugLn('TLinkScanner.Search Filename="',AFilename,'" Found="',FoundFilename,'"');
|
||||
{$ENDIF}
|
||||
NewCode:=FOnLoadSource(Self,FoundFilename,true);
|
||||
if (NewCode<>nil) then
|
||||
exit(true);
|
||||
end;
|
||||
|
||||
if not HasPathDelims then begin
|
||||
// file without path -> search in inc paths
|
||||
|
||||
if MissingIncludeFile=nil then
|
||||
IncludePath:=Values.Variables[ExternalMacroStart+'INCPATH']
|
||||
else
|
||||
IncludePath:=MissingIncludeFile.IncludePath;
|
||||
|
||||
{$IFDEF VerboseIncludeSearch}
|
||||
DebugLn('TLinkScanner.SearchIncludeFile IncPath="',IncludePath,'"');
|
||||
{$ENDIF}
|
||||
PathStart:=1;
|
||||
PathEnd:=PathStart;
|
||||
while PathEnd<=length(IncludePath) do begin
|
||||
if IncludePath[PathEnd]=';' then begin
|
||||
if PathEnd>PathStart then begin
|
||||
CurPath:=TrimFilename(copy(IncludePath,PathStart,PathEnd-PathStart));
|
||||
Result:=SearchPath(CurPath,RelFilename);
|
||||
if Result then exit;
|
||||
end;
|
||||
PathStart:=PathEnd+1;
|
||||
PathEnd:=PathStart;
|
||||
end else
|
||||
inc(PathEnd);
|
||||
end;
|
||||
if PathEnd>PathStart then begin
|
||||
CurPath:=TrimFilename(copy(IncludePath,PathStart,PathEnd-PathStart));
|
||||
Result:=SearchPath(CurPath,RelFilename);
|
||||
if Result then exit;
|
||||
end;
|
||||
|
||||
// then search the include file in directories defines in fpc.cfg (by -Fi option)
|
||||
if (not IsVirtualUnit) and OnFindIncFileInFPCSrcDir(Self,AFilename,ExpFilename) then
|
||||
// search the include file in directories defines in fpc.cfg (by -Fi option)
|
||||
if FilenameIsAbsolute(Dir)
|
||||
and Values.IsDefined('FPC')
|
||||
and OnFindIncFileInFPCSrcDir(Self,AFilename,FoundFilename) then
|
||||
begin
|
||||
NewCode:=FOnLoadSource(Self,ExpFilename,true);
|
||||
Result:=(NewCode<>nil);
|
||||
exit;
|
||||
NewCode:=FOnLoadSource(Self,FoundFilename,true);
|
||||
if NewCode<>nil then
|
||||
exit(true);
|
||||
end;
|
||||
end;
|
||||
|
||||
// search in directory of source of include directive
|
||||
// Note: fpc 3.2.2 does not do that
|
||||
// last: search in directory of source of include directive
|
||||
// Note: fpc 3.2.2 does not do that, but for codetools it is more convenient to find it
|
||||
if FilenameIsAbsolute(SrcFilename)
|
||||
and (CompareFilenames(SrcFilename,FMainSourceFilename)<>0) then begin
|
||||
ExpFilename:=ExtractFilePath(SrcFilename)+RelFilename;
|
||||
NewCode:=LoadIncludeFile(ExpFilename);
|
||||
Result:=(NewCode<>nil);
|
||||
if Result then exit;
|
||||
FoundFilename:=ExtractFilePath(SrcFilename)+RelFilename;
|
||||
NewCode:=LoadIncludeFile(FoundFilename);
|
||||
if NewCode<>nil then
|
||||
exit(true);
|
||||
end;
|
||||
|
||||
Result:=false;
|
||||
@ -4212,7 +4200,6 @@ begin
|
||||
DebugLn('TLinkScanner.SearchIncludeFile Filename="',AFilename,'"');
|
||||
{$ENDIF}
|
||||
NewCode:=nil;
|
||||
IncludePath:='';
|
||||
|
||||
// beware of 'dir/file.inc'
|
||||
HasPathDelims:=(System.Pos('/',AFilename)>0) or (System.Pos('\',AFilename)>0);
|
||||
|
@ -0,0 +1 @@
|
||||
var Green: word;
|
@ -0,0 +1 @@
|
||||
the correct include file is Green.inc, if this file is found there is a bug
|
@ -0,0 +1,7 @@
|
||||
unit Star.Green3;
|
||||
|
||||
interface
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
@ -0,0 +1,9 @@
|
||||
unit star.green1;
|
||||
|
||||
interface
|
||||
|
||||
uses star.green2;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
@ -0,0 +1,7 @@
|
||||
unit star.green2;
|
||||
|
||||
interface
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
1
components/codetools/tests/moduletests/star/readme.txt
Normal file
1
components/codetools/tests/moduletests/star/readme.txt
Normal file
@ -0,0 +1 @@
|
||||
duplicate
|
@ -0,0 +1,9 @@
|
||||
unit star.orange1;
|
||||
|
||||
interface
|
||||
|
||||
uses star.green1;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
@ -0,0 +1 @@
|
||||
duplicate
|
@ -0,0 +1,9 @@
|
||||
unit star.red1;
|
||||
|
||||
interface
|
||||
|
||||
uses star.green1;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
11
components/codetools/tests/moduletests/star/star.main.pas
Normal file
11
components/codetools/tests/moduletests/star/star.main.pas
Normal file
@ -0,0 +1,11 @@
|
||||
unit star.main;
|
||||
|
||||
interface
|
||||
|
||||
uses star.red1, star.green1, star.green2, star.orange1;
|
||||
|
||||
{$I green/Green.inc}
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
@ -328,13 +328,13 @@ procedure TTestBasicCodeTools.TestDateToCfgStr;
|
||||
Actual: String;
|
||||
ActualDate: TDateTime;
|
||||
begin
|
||||
Actual:=DateToCfgStr(Date,aFormat);
|
||||
Actual:=LazConfigStorage.DateToCfgStr(Date,aFormat);
|
||||
if Actual<>Expected then begin
|
||||
writeln(dbgsDiff(Expected,Actual));
|
||||
AssertEquals('DateToCfgStr failed: Format="'+aFormat+'"',Expected,Actual);
|
||||
exit;
|
||||
end;
|
||||
if (not CfgStrToDate(Actual,ActualDate,aFormat)) then begin
|
||||
if (not LazConfigStorage.CfgStrToDate(Actual,ActualDate,aFormat)) then begin
|
||||
AssertEquals('CfgStrToDate failed: Format="'+aFormat+'" Cfg="'+Actual+'"',false,true);
|
||||
exit;
|
||||
end;
|
||||
|
@ -58,12 +58,11 @@ unit TestFindDeclaration;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, contnrs,
|
||||
fpcunit, testregistry,
|
||||
FileProcs, LazFileUtils, LazLogger,
|
||||
CodeToolManager, ExprEval, CodeCache, BasicCodeTools,
|
||||
Classes, SysUtils, contnrs, fpcunit, testregistry, FileProcs, LazFileUtils,
|
||||
LazLogger, CodeToolManager, ExprEval, CodeCache, BasicCodeTools,
|
||||
CustomCodeTool, CodeTree, FindDeclarationTool, KeywordFuncLists,
|
||||
IdentCompletionTool, DefineTemplates, StrUtils, TestPascalParser;
|
||||
IdentCompletionTool, DefineTemplates, DirectoryCacher, StrUtils,
|
||||
TestPascalParser;
|
||||
|
||||
const
|
||||
MarkDecl = '#'; // a declaration, must be unique
|
||||
@ -139,12 +138,20 @@ type
|
||||
procedure TestFindDeclaration_ArrayMultiDimDot;
|
||||
procedure TestFindDeclaration_VarArgsOfType;
|
||||
procedure TestFindDeclaration_ProcRef;
|
||||
|
||||
// unit/include search
|
||||
procedure TestFindDeclaration_UnitSearch_CurrentDir;
|
||||
procedure TestFindDeclaration_UnitSearch_StarStar;
|
||||
procedure TestFindDeclaration_IncludeSearch_DirectiveWithPath;
|
||||
procedure TestFindDeclaration_IncludeSearch_StarStar;
|
||||
|
||||
// directives
|
||||
procedure TestFindDeclaration_DirectiveWithIn;
|
||||
|
||||
// test all files in directories:
|
||||
procedure TestFindDeclaration_FPCTests;
|
||||
procedure TestFindDeclaration_LazTests;
|
||||
procedure TestFindDeclaration_LazTestsBugs;
|
||||
procedure TestFindDeclaration_DirectiveWithIn;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -1262,19 +1269,120 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_FPCTests;
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_UnitSearch_StarStar;
|
||||
var
|
||||
StarDir, UnitPath, Expected, anUnitName, InFilename,
|
||||
FoundFilename: String;
|
||||
DirDef, UnitPathDef: TDefineTemplate;
|
||||
DirCache: TCTDirectoryCachePool;
|
||||
begin
|
||||
TestFiles('fpctests');
|
||||
StarDir:=ExpandFileNameUTF8(SetDirSeparators('moduletests/star'));
|
||||
|
||||
DirDef:=TDefineTemplate.Create('TTestFindDeclaration_UnitSearch','','',StarDir,da_Directory);
|
||||
try
|
||||
CodeToolBoss.DefineTree.Add(DirDef);
|
||||
UnitPathDef:=TDefineTemplate.Create('UnitPath','',UnitPathMacroName,DefinePathMacro+PathDelim+'**',da_DefineRecurse);
|
||||
DirDef.AddChild(UnitPathDef);
|
||||
CodeToolBoss.DefineTree.ClearCache;
|
||||
|
||||
// check unit path in some directories
|
||||
Expected:=StarDir+PathDelim+'**';
|
||||
|
||||
UnitPath:=CodeToolBoss.GetUnitPathForDirectory(StarDir);
|
||||
AssertEquals('unit path',Expected,UnitPath);
|
||||
|
||||
UnitPath:=CodeToolBoss.GetUnitPathForDirectory(StarDir+PathDelim+'green');
|
||||
AssertEquals('unit path',Expected,UnitPath);
|
||||
|
||||
DirCache:=CodeToolBoss.DirectoryCachePool;
|
||||
|
||||
// searching a lowercase unit
|
||||
anUnitName:='Star.Red1';
|
||||
InFilename:='';
|
||||
FoundFilename:=DirCache.FindUnitSourceInCompletePath(StarDir,anUnitName,InFilename);
|
||||
Expected:=StarDir+PathDelim+'red/star.red1.pas';
|
||||
AssertEquals('searching '+anUnitName,Expected,FoundFilename);
|
||||
|
||||
// searching a mixedcase unit
|
||||
anUnitName:='Star.Green3';
|
||||
InFilename:='';
|
||||
FoundFilename:=DirCache.FindUnitSourceInCompletePath(StarDir,anUnitName,InFilename);
|
||||
Expected:=StarDir+PathDelim+'green/Star.Green3.pas';
|
||||
AssertEquals('searching '+anUnitName,Expected,FoundFilename);
|
||||
|
||||
// searching an anycase unit
|
||||
anUnitName:='star.green3';
|
||||
InFilename:='';
|
||||
FoundFilename:=DirCache.FindUnitSourceInCompletePath(StarDir,anUnitName,InFilename,true);
|
||||
Expected:=StarDir+PathDelim+'green/Star.Green3.pas';
|
||||
AssertEquals('searching '+anUnitName,Expected,FoundFilename);
|
||||
finally
|
||||
CodeToolBoss.DefineTree.RemoveDefineTemplate(DirDef);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_LazTests;
|
||||
procedure TTestFindDeclaration.
|
||||
TestFindDeclaration_IncludeSearch_DirectiveWithPath;
|
||||
var
|
||||
aFilename: String;
|
||||
StarCode: TCodeBuffer;
|
||||
Tool: TCodeTool;
|
||||
begin
|
||||
TestFiles('laztests');
|
||||
aFilename:=ExpandFileNameUTF8(SetDirSeparators('moduletests/star/star.main.pas'));
|
||||
StarCode:=CodeToolBoss.LoadFile(aFilename,true,false);
|
||||
if not CodeToolBoss.Explore(STarCode,Tool,true) then begin
|
||||
debugln('Error: '+CodeToolBoss.ErrorDbgMsg);
|
||||
Fail('Explore failed: '+CodeToolBoss.ErrorMessage);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_LazTestsBugs;
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_IncludeSearch_StarStar;
|
||||
var
|
||||
StarDir, IncPath, Expected, IncFilename, FoundFilename: String;
|
||||
DirDef, IncPathDef: TDefineTemplate;
|
||||
DirCache: TCTDirectoryCachePool;
|
||||
begin
|
||||
TestFiles('laztests', 'b*.p*');
|
||||
StarDir:=ExpandFileNameUTF8(SetDirSeparators('moduletests/star'));
|
||||
|
||||
DirDef:=TDefineTemplate.Create('TTestFindDeclaration_IncudeSearch','','',StarDir,da_Directory);
|
||||
try
|
||||
CodeToolBoss.DefineTree.Add(DirDef);
|
||||
IncPathDef:=TDefineTemplate.Create('IncPath','',IncludePathMacroName,DefinePathMacro+PathDelim+'**',da_DefineRecurse);
|
||||
DirDef.AddChild(IncPathDef);
|
||||
CodeToolBoss.DefineTree.ClearCache;
|
||||
|
||||
// check include search path in some directories
|
||||
Expected:=StarDir+PathDelim+'**';
|
||||
|
||||
IncPath:=CodeToolBoss.GetIncludePathForDirectory(StarDir);
|
||||
AssertEquals('include path',Expected,IncPath);
|
||||
|
||||
IncPath:=CodeToolBoss.GetIncludePathForDirectory(StarDir+PathDelim+'green');
|
||||
AssertEquals('include path',Expected,IncPath);
|
||||
|
||||
DirCache:=CodeToolBoss.DirectoryCachePool;
|
||||
|
||||
// searching a lowercase include
|
||||
IncFilename:='Star.inc';
|
||||
FoundFilename:=DirCache.FindIncludeFileInCompletePath(StarDir,IncFilename);
|
||||
Expected:=StarDir+PathDelim+'star.inc';
|
||||
AssertEquals('searching '+IncFilename,Expected,FoundFilename);
|
||||
|
||||
// searching a mixedcase include
|
||||
IncFilename:='Green.inc';
|
||||
FoundFilename:=DirCache.FindIncludeFileInCompletePath(StarDir,IncFilename);
|
||||
Expected:=StarDir+PathDelim+'green/Green.inc';
|
||||
AssertEquals('searching '+IncFilename,Expected,FoundFilename);
|
||||
|
||||
// searching an include file without extension
|
||||
IncFilename:='Green';
|
||||
FoundFilename:=DirCache.FindIncludeFileInCompletePath(StarDir,IncFilename);
|
||||
Expected:=StarDir+PathDelim+'green/Green.inc';
|
||||
AssertEquals('searching '+IncFilename,Expected,FoundFilename);
|
||||
|
||||
finally
|
||||
CodeToolBoss.DefineTree.RemoveDefineTemplate(DirDef);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_DirectiveWithIn;
|
||||
@ -1300,6 +1408,21 @@ begin
|
||||
FindDeclarations(Code);
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_FPCTests;
|
||||
begin
|
||||
TestFiles('fpctests');
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_LazTests;
|
||||
begin
|
||||
TestFiles('laztests');
|
||||
end;
|
||||
|
||||
procedure TTestFindDeclaration.TestFindDeclaration_LazTestsBugs;
|
||||
begin
|
||||
TestFiles('laztests', 'b*.p*');
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterTests([TTestFindDeclaration]);
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user