IDE: fpc msg parser: fixed crash if unit not found, pass -vbq when building IDE

git-svn-id: trunk@45502 -
This commit is contained in:
mattias 2014-06-13 21:06:24 +00:00
parent 69873d9763
commit 935eeca8e9
4 changed files with 79 additions and 26 deletions

View File

@ -199,6 +199,7 @@ function ReadNextFPCParameter(const CmdLine: string; var Position: integer;
function ExtractFPCParameter(const CmdLine: string; StartPos: integer): string;
function FindNextFPCParameter(const CmdLine, BeginsWith: string; var Position: integer): integer;
function GetLastFPCParameter(const CmdLine, BeginsWith: string; CutBegins: boolean = true): string;
function GetFPCParameterSrcFile(const CmdLine: string): string;
type
TCTPascalExtType = (petNone, petPAS, petPP, petP);
@ -1326,6 +1327,22 @@ begin
end;
end;
function GetFPCParameterSrcFile(const CmdLine: string): string;
// the source file is the last parameter not starting with minus
var
p: Integer;
StartPos: integer;
begin
p:=1;
while ReadNextFPCParameter(CmdLine,p,StartPos) do begin
if (CmdLine[StartPos]='-') then continue;
Result:=ExtractFPCParameter(CmdLine,StartPos);
if (Result='') or (Result[1]='-') then continue;
exit;
end;
Result:='';
end;
function SearchFileInDir(const Filename, BaseDirectory: string;
SearchCase: TCTSearchFileCase): string;

View File

@ -799,6 +799,9 @@ begin
if not (Result in [mrOk,mrIgnore]) then Exit;
end;
// write full file names and message ids
AppendExtraOption('-vbq');
if fUnitOutDir<>'' then
// FPC interpretes '\ ' as an escape for a space in a path on Windows,
// so make sure the directory doesn't end with the path delimiter.

View File

@ -29,7 +29,7 @@ unit etFPCMsgParser;
{$mode objfpc}{$H+}
{off $DEFINE VerboseQuickFixUnitNotFoundPosition}
{off $DEFINE VerboseFPCMsgUnitNotFound}
interface
@ -38,8 +38,9 @@ uses
IDEExternToolIntf, PackageIntf, LazIDEIntf, ProjectIntf, IDEUtils,
CompOptsIntf, CodeToolsFPCMsgs, CodeToolsStructs, CodeCache, CodeToolManager,
DirectoryCacher, BasicCodeTools, DefineTemplates, SourceLog, LazUTF8,
FileUtil, LConvEncoding, TransferMacros, etMakeMsgParser, EnvironmentOpts,
LCLProc, LazarusIDEStrConsts;
FileUtil, LConvEncoding, LazFileUtils,
LazConf, TransferMacros, etMakeMsgParser,
EnvironmentOpts, LCLProc, LazarusIDEStrConsts;
const
FPCMsgIDLogo = 11023;
@ -1631,13 +1632,13 @@ procedure TIDEFPCParser.ImproveMsgUnitNotFound(aPhase: TExtToolParserSyncPhase;
Caret: TCodeXYPosition;
NewFilename: String;
begin
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound File=',CodeBuf.Filename]);
{$ENDIF}
LazarusIDE.SaveSourceEditorChangesToCodeCache(nil);
if not CodeToolBoss.FindUnitInAllUsesSections(CodeBuf,MissingUnitname,NamePos,InPos)
then begin
DebugLn('TIDEFPCParser.ImproveMsgUnitNotFound failed due to syntax errors or '+MissingUnitname+' is not used in '+CodeBuf.Filename);
DebugLn('TIDEFPCParser.ImproveMsgUnitNotFound FindUnitInAllUsesSections failed due to syntax errors or '+MissingUnitname+' is not used in '+CodeBuf.Filename);
exit;
end;
Tool:=CodeToolBoss.CurCodeTool;
@ -1782,14 +1783,16 @@ begin
MsgLine.Attribute[FPCMsgAttrMissingUnit]:=MissingUnitName;
MsgLine.Attribute[FPCMsgAttrUsedByUnit]:=UsedByUnit;
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound Missing="',MissingUnitname,'" used by "',UsedByUnit,'"']);
{$ENDIF}
CodeBuf:=nil;
Filename:=MsgLine.GetFullFilename;
if (CompareFilenames(ExtractFileName(Filename),'staticpackages.inc')=0)
and IsFileInIDESrcDir(Filename) then begin
and ((ExtractFilePath(Filename)='')
or (CompareFilenames(ExtractFilePath(Filename),AppendPathDelim(GetPrimaryConfigPath))=0))
then begin
// common case: when building the IDE a package unit is missing
// staticpackages.inc(1,1) Fatal: Can't find unit sqldblaz used by Lazarus
// change to lazarus.pp(1,1)
@ -1810,7 +1813,7 @@ begin
if NewFilename='' then begin
NewFilename:=LazarusIDE.FindUnitFile(UsedByUnit);
if NewFilename='' then begin
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound unit not found: ',UsedByUnit]);
{$ENDIF}
end;
@ -1819,24 +1822,24 @@ begin
Filename:=NewFilename;
end;
if Filename<>'' then begin
if FilenameIsAbsolute(Filename) then begin
CodeBuf:=CodeToolBoss.LoadFile(Filename,false,false);
if CodeBuf=nil then begin
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound unable to load unit: ',Filename]);
{$ENDIF}
end;
end else begin
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound unable to locate UsedByUnit: ',UsedByUnit]);
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound unable to locate UsedByUnit: ',UsedByUnit,' Filename="',MsgLine.Filename,'" Attr[',FPCMsgAttrWorkerDirectory,']=',MsgLine.Attribute[FPCMsgAttrWorkerDirectory],' Tool.WorkerDirectory=',Tool.WorkerDirectory]);
{$ENDIF}
end;
// fix line and column
Owners:=nil;
UsedByOwner:=nil;
PPUFiles:=TStringList.Create;
try
UsedByOwner:=nil;
if CodeBuf<>nil then begin
FixSourcePos(CodeBuf,MissingUnitname);
Owners:=PackageEditingInterface.GetOwnersOfUnit(CodeBuf.Filename);
@ -1845,13 +1848,13 @@ begin
end;
// if the ppu exists then improve the message
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound Filename=',CodeBuf.Filename]);
{$ENDIF}
if FilenameIsAbsolute(CodeBuf.Filename) then begin
if (CodeBuf<>nil) and FilenameIsAbsolute(CodeBuf.Filename) then begin
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound Filename=',CodeBuf.Filename]);
{$ENDIF}
PPUFilename:=CodeToolBoss.DirectoryCachePool.FindCompiledUnitInCompletePath(
ExtractFilePath(CodeBuf.Filename),MissingUnitname);
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TQuickFixUnitNotFoundPosition.Execute PPUFilename=',PPUFilename,' IsFileInIDESrcDir=',IsFileInIDESrcDir(CodeBuf.Filename)]);
{$ENDIF}
PkgName:='';
@ -1889,8 +1892,10 @@ begin
// two units of a package cannot find each other
s+=Format(lisCheckSearchPathPackageTryACleanRebuildCheckImpleme, [
TIDEPackage(UsedByOwner).Name]);
end else if (UsedByOwner<>nil) and (PkgName<>'')
and PackageEditingInterface.IsOwnerDependingOnPkg(UsedByOwner,PkgName,DepOwner)
end else if (PkgName<>'')
and (OnlyInstalled
or ((UsedByOwner<>nil)
and PackageEditingInterface.IsOwnerDependingOnPkg(UsedByOwner,PkgName,DepOwner)))
then begin
// ppu file of an used package is missing
s+=Format(lisCheckIfPackageCreatesPpuCheckNothingDeletesThisFil, [
@ -1906,7 +1911,7 @@ begin
s+='.';
end;
MsgLine.Msg:=s;
{$IFDEF VerboseQuickFixUnitNotFoundPosition}
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.ImproveMsgUnitNotFound Msg.Msg="',MsgLine.Msg,'"']);
{$ENDIF}
end;
@ -2206,6 +2211,9 @@ begin
fIncludePathValidForWorkerDir:=MsgWorkerDir;
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
ChompPathDelim(MsgWorkerDir));
{$IFDEF VerboseFPCMsgUnitNotFound}
debugln(['TIDEFPCParser.FetchIncludePath ',fIncludePath]);
{$ENDIF}
NeedAfterSync:=true;
end;
end;
@ -2554,6 +2562,8 @@ var
SourceOK: Boolean;
MsgWorkerDir: String;
PrevMsgLine: TMessageLine;
CmdLineParams: String;
SrcFilename: String;
begin
//debugln(['TIDEFPCParser.ImproveMessages START ',aSynchronized,' Last=',fLastWorkerImprovedMessage[aSynchronized],' Now=',Tool.WorkerMessages.Count]);
for i:=fLastWorkerImprovedMessage[aPhase]+1 to Tool.WorkerMessages.Count-1 do
@ -2566,7 +2576,7 @@ begin
then begin
aFilename:=MsgLine.Filename;
if (not FilenameIsAbsolute(aFilename)) then begin
// short file name => 1. try to find the full file name
// short file name => 1. search the full file name in previous message
if i>0 then begin
PrevMsgLine:=Tool.WorkerMessages[i-1];
if (PrevMsgLine.SubTool=SubToolFPC)
@ -2580,9 +2590,13 @@ begin
end;
end;
if (not FilenameIsAbsolute(aFilename)) then begin
// short file name => 2. try include path
// short file name => 2. search in include path
MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory];
FetchIncludePath(aPhase,MsgWorkerDir);
FetchIncludePath(aPhase,MsgWorkerDir); // needs Phase etpspAfterReadLine+etpspSynchronized
{$IFDEF VerboseFPCMsgUnitNotFound}
if aPhase=etpspSynchronized then
debugln(['TIDEFPCParser.ImproveMessages IncPath="',fIncludePath,'" aFilename="',aFilename,'" MsgWorkerDir="',MsgWorkerDir,'"']);
{$ENDIF}
if (aPhase in [etpspAfterReadLine,etpspAfterSync])
and (fIncludePathValidForWorkerDir=MsgWorkerDir) then begin
// include path is valid and in worker thread
@ -2593,6 +2607,25 @@ begin
MsgLine.Filename:=aFilename;
end;
end;
if (not FilenameIsAbsolute(aFilename)) and (aPhase=etpspAfterReadLine)
then begin
CmdLineParams:=Tool.CmdLineParams;
if Pos(CmdLineParams,PathDelim+'fpc'+ExeExt+' ')>0 then begin
// short file name => 3. check the cmd line param source file
SrcFilename:=GetFPCParameterSrcFile(Tool.CmdLineParams);
if (SrcFilename<>'')
and ((CompareFilenames(ExtractFilename(SrcFilename),aFilename)=0)
or (CompareFilenames(ExtractFileNameOnly(SrcFilename),aFilename)=0))
then begin
if not FilenameIsAbsolute(SrcFilename) then begin
MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory];
SrcFilename:=ResolveDots(AppendPathDelim(MsgWorkerDir)+SrcFilename);
end;
if FilenameIsAbsolute(SrcFilename) then
MsgLine.Filename:=SrcFilename;
end;
end;
end;
// get source
SourceOK:=false;

View File

@ -1602,8 +1602,8 @@ begin
StdErrLine:='';
LastUpdate:=GetTickCount64;
while (Tool<>nil) and (Tool.Stage=etsRunning) do begin
HasOutput:=ReadInputPipe(Tool.Process.Stderr,StdErrLine)
or ReadInputPipe(Tool.Process.Output,OutputLine);
HasOutput:=ReadInputPipe(Tool.Process.Output,OutputLine)
or ReadInputPipe(Tool.Process.Stderr,StdErrLine);
if (not HasOutput) then begin
// no more pending output
if not Tool.Process.Running then break;