diff --git a/components/ideintf/ideexterntoolintf.pas b/components/ideintf/ideexterntoolintf.pas index 4654265cbc..6f75497ec2 100644 --- a/components/ideintf/ideexterntoolintf.pas +++ b/components/ideintf/ideexterntoolintf.pas @@ -103,6 +103,7 @@ type TAbstractExternalTool = class; TMessageLineFlag = ( + mlfStdErr, mlfLeftToken, // position is about left token, otherwise right token mlfFixed, // reason for the messages was resolved, e.g. quick fixed mlfHiddenByIDEDirective, @@ -297,7 +298,7 @@ type procedure Init; virtual; // called after macros resolved, before starting thread (main thread) procedure InitReading; virtual; // called if process started, before first line (worker thread) procedure Done; virtual; // called after process stopped (worker thread) - procedure ReadLine(Line: string; OutputIndex: integer; var Handled: boolean); virtual; abstract; // (worker thread) + procedure ReadLine(Line: string; OutputIndex: integer; IsStdErr: boolean; var Handled: boolean); virtual; abstract; // (worker thread) function CreateMsgLine(OutputIndex: integer): TMessageLine; // (worker thread) procedure AddMsgLine(MsgLine: TMessageLine); virtual; // (worker thread) property Tool: TAbstractExternalTool read FTool;// set when added to a tool @@ -360,8 +361,8 @@ type TDefaultParser = class(TExtToolParser) public - procedure ReadLine(Line: string; OutputIndex: integer; var Handled: boolean - ); override; + procedure ReadLine(Line: string; OutputIndex: integer; IsStdErr: boolean; + var Handled: boolean); override; class function DefaultSubTool: string; override; class function GetLocalizedParserName: string; override; class function Priority: integer; override; @@ -997,7 +998,7 @@ end; { TDefaultParser } procedure TDefaultParser.ReadLine(Line: string; OutputIndex: integer; - var Handled: boolean); + IsStdErr: boolean; var Handled: boolean); var MsgLine: TMessageLine; begin @@ -1006,6 +1007,8 @@ begin MsgLine:=CreateMsgLine(OutputIndex); MsgLine.Msg:=Line; MsgLine.Urgency:=mluImportant; + if IsStdErr then + MsgLine.Flags:=MsgLine.Flags+[mlfStdErr]; AddMsgLine(MsgLine); end; diff --git a/ide/etfpcmsgparser.pas b/ide/etfpcmsgparser.pas index 297d26a635..c64c797c6d 100644 --- a/ide/etfpcmsgparser.pas +++ b/ide/etfpcmsgparser.pas @@ -166,6 +166,7 @@ type fLineToMsgID: TPatternToMsgIDs; fMissingFPCMsgItem: TFPCMsgItem; fMsgID: Integer; // current message id given by ReadLine (-vq) + fMsgIsStdErr: boolean; fMsgItemCantFindUnitUsedBy: TFPCMsgItem; fMsgItemCompilationAborted: TFPCMsgItem; fMsgItemErrorWhileCompilingResources: TFPCMsgItem; @@ -193,6 +194,7 @@ type function CheckForWindresErrors(p: PChar): boolean; function CheckForLinkerErrors(p: PChar): boolean; function CheckForAssemblerErrors(p: PChar): boolean; + function CheckForUnspecificStdErr(p: PChar): boolean; function CreateMsgLine: TMessageLine; procedure AddLinkingMessages; procedure AddResourceMessages; @@ -232,7 +234,8 @@ type procedure Init; override; // called after macros resolved, before starting thread (main thread) procedure InitReading; override; // called when process started, before first line (worker thread) procedure Done; override; // called after process stopped (worker thread) - procedure ReadLine(Line: string; OutputIndex: integer; var Handled: boolean); override; + procedure ReadLine(Line: string; OutputIndex: integer; IsStdErr: boolean; + var Handled: boolean); override; procedure AddMsgLine(MsgLine: TMessageLine); override; procedure ImproveMessages(aPhase: TExtToolParserSyncPhase); override; function GetFPCMsgIDPattern(MsgID: integer): string; override; @@ -1549,6 +1552,19 @@ begin AddMsgLine(MsgLine); end; +function TIDEFPCParser.CheckForUnspecificStdErr(p: PChar): boolean; +var + MsgLine: TMessageLine; +begin + if not fMsgIsStdErr then exit(false); + Result:=true; + MsgLine:=CreateMsgLine; + MsgLine.SubTool:=SubToolFPC; + MsgLine.Urgency:=mluError; + MsgLine.Msg:=p; + AddMsgLine(MsgLine); +end; + function TIDEFPCParser.CheckForInfos(p: PChar): boolean; function ReadFPCLogo(PatternItem: PPatternToMsgID; @@ -1625,6 +1641,8 @@ function TIDEFPCParser.CreateMsgLine: TMessageLine; begin Result:=inherited CreateMsgLine(fOutputIndex); Result.MsgID:=fMsgID; + if fMsgIsStdErr then + Result.Flags:=Result.Flags+[mlfStdErr]; end; procedure TIDEFPCParser.AddLinkingMessages; @@ -2905,7 +2923,7 @@ begin end; procedure TIDEFPCParser.ReadLine(Line: string; OutputIndex: integer; - var Handled: boolean); + IsStdErr: boolean; var Handled: boolean); { returns true, if it is a compiler message Examples for freepascal compiler messages: Compiling @@ -2927,6 +2945,7 @@ begin p:=PChar(Line); fOutputIndex:=OutputIndex; fMsgID:=0; + fMsgIsStdErr:=IsStdErr; // skip time [0.000] if (p^='[') and (p[1] in ['0'..'9']) then begin @@ -2984,6 +3003,9 @@ begin // check for assembler errors if CheckForAssemblerErrors(p) then exit; + // last: check for unknown std error + if CheckForUnspecificStdErr(p) then exit; + {$IFDEF VerboseFPCParser} debugln('TFPCParser.ReadLine UNKNOWN: ',Line); {$ENDIF} diff --git a/ide/etmakemsgparser.pas b/ide/etmakemsgparser.pas index bb496a6800..ea261cf2a1 100644 --- a/ide/etmakemsgparser.pas +++ b/ide/etmakemsgparser.pas @@ -58,7 +58,8 @@ type constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure InitReading; override; - procedure ReadLine(Line: string; OutputIndex: integer; var Handled: boolean); override; + procedure ReadLine(Line: string; OutputIndex: integer; IsStdErr: boolean; + var Handled: boolean); override; class function DefaultSubTool: string; override; class function Priority: integer; override; end; @@ -245,7 +246,7 @@ begin end; procedure TIDEMakeParser.ReadLine(Line: string; OutputIndex: integer; - var Handled: boolean); + IsStdErr: boolean; var Handled: boolean); { returns true, if it is a make/gmake message Examples for make messages: make[1]: Entering directory `' @@ -283,7 +284,13 @@ begin MsgLine:=CreateMsgLine(OutputIndex); MsgLine.SubTool:=SubToolMake; - MsgLine.Urgency:=mluVerbose; + if IsStdErr then + begin + MsgLine.Urgency:=mluImportant; + MsgLine.Flags:=MsgLine.Flags+[mlfStdErr]; + end else begin + MsgLine.Urgency:=mluVerbose; + end; MsgLine.Msg:=Line; if p^='[' then @@ -324,7 +331,12 @@ begin MsgLine:=CreateMsgLine(OutputIndex); MsgLine.SubTool:=SubToolMake; - MsgLine.Urgency:=mluVerbose; + if IsStdErr then begin + MsgLine.Urgency:=mluImportant; + MsgLine.Flags:=MsgLine.Flags+[mlfStdErr]; + end else begin + MsgLine.Urgency:=mluVerbose; + end; MsgLine.Msg:=Line; AddMsgLine(MsgLine); exit; @@ -345,7 +357,12 @@ begin Handled:=true; MsgLine:=CreateMsgLine(OutputIndex); MsgLine.SubTool:=SubToolMake; - MsgLine.Urgency:=mluVerbose; + if IsStdErr then begin + MsgLine.Urgency:=mluImportant; + MsgLine.Flags:=MsgLine.Flags+[mlfStdErr]; + end else begin + MsgLine.Urgency:=mluVerbose; + end; MsgLine.Msg:=Line; AddMsgLine(MsgLine); end; diff --git a/ide/exttools.pas b/ide/exttools.pas index 0fdfd05f2c..64434bc464 100644 --- a/ide/exttools.pas +++ b/ide/exttools.pas @@ -306,7 +306,7 @@ var OldOutputCount: LongInt; OldMsgCount: LongInt; Parser: TExtToolParser; - NeedSynchronize: Boolean; + NeedSynchronize, IsStdErr: Boolean; MsgLine: TMessageLine; LineStr: String; begin @@ -327,17 +327,20 @@ begin for Line:=OldOutputCount to WorkerOutput.Count-1 do begin Handled:=false; LineStr:=WorkerOutput[Line]; + IsStdErr:=WorkerOutput.Objects[Line]<>nil; for i:=0 to ParserCount-1 do begin {$IFDEF VerboseExtToolAddOutputLines} DebuglnThreadLog(['TExternalTool.AddOutputLines ',DbgSName(Parsers[i]),' Line="',WorkerOutput[Line],'" READLINE ...']); {$ENDIF} - Parsers[i].ReadLine(LineStr,Line,Handled); + Parsers[i].ReadLine(LineStr,Line,IsStdErr,Handled); if Handled then break; end; if (not Handled) then begin MsgLine:=WorkerMessages.CreateLine(Line); MsgLine.Msg:=LineStr; // use raw output as default msg MsgLine.Urgency:=mluDebug; + if IsStdErr then + MsgLine.Flags:=MsgLine.Flags+[mlfStdErr]; WorkerMessages.Add(MsgLine); end; end; @@ -1420,7 +1423,8 @@ var var Buf: string; - function ReadInputPipe(aStream: TInputPipeStream; var LineBuf: string): boolean; + function ReadInputPipe(aStream: TInputPipeStream; var LineBuf: string; + IsStdErr: boolean): boolean; // true if some bytes have been read var Count: DWord; @@ -1439,7 +1443,10 @@ var while i<=Count do begin if Buf[i] in [#10,#13] then begin LineBuf:=LineBuf+copy(Buf,StartPos,i-StartPos); - fLines.Add(LineBuf); + if IsStdErr then + fLines.AddObject(LineBuf,fLines) + else + fLines.Add(LineBuf); LineBuf:=''; if (iBuf[i+1]) then @@ -1544,11 +1551,11 @@ begin LastUpdate:=GetTickCount64; while (Tool<>nil) and (Tool.Stage=etsRunning) do begin if Tool.ReadStdOutBeforeErr then begin - HasOutput:=ReadInputPipe(Tool.Process.Output,OutputLine) - or ReadInputPipe(Tool.Process.Stderr,StdErrLine); + HasOutput:=ReadInputPipe(Tool.Process.Output,OutputLine,false) + or ReadInputPipe(Tool.Process.Stderr,StdErrLine,true); end else begin - HasOutput:=ReadInputPipe(Tool.Process.Stderr,StdErrLine) - or ReadInputPipe(Tool.Process.Output,OutputLine); + HasOutput:=ReadInputPipe(Tool.Process.Stderr,StdErrLine,true) + or ReadInputPipe(Tool.Process.Output,OutputLine,false); end; if (not HasOutput) then begin // no more pending output