IDE: message parser: split synchronized phase to move more processing from main to sub thread

git-svn-id: trunk@45375 -
This commit is contained in:
mattias 2014-06-06 09:41:27 +00:00
parent a7d3ed095d
commit 566f80a37a
3 changed files with 182 additions and 101 deletions

View File

@ -255,6 +255,24 @@ type
procedure ConsistencyCheck; procedure ConsistencyCheck;
end; end;
{ The output is parsed in chunks (multiple lines) at a time.
First every output line is passed to each parser via ReadLine.
After the whole chunk was processed via ReadLine, each parser is called
with ImproveMessages up to three times. During ImproveMessages the Tool
is locked via its critical section.
After ImproveMessages the chunk is passed to the Views.
}
TExtToolParserSyncPhase = (
etpspAfterReadLine, { (worker thread) after lines were created by parsers
via ReadLine and added to Tool.WorkerMessages. In this phase parsers can
look what other parsers have created and/or to decide if they need some
data from the IDE (NeedSynchronize:=true) }
etpspSynchronized, { (main thread) parsers can collect data from the IDE.
If the data need processing set NeedAfterSync:=true }
etpspAfterSync { (worker thread) use the collected IDE data }
);
TExtToolParserSyncPhases = set of TExtToolParserSyncPhase;
{ TExtToolParser { TExtToolParser
Read the output of a tool, for example the output of the Free Pascal compiler. Read the output of a tool, for example the output of the Free Pascal compiler.
It does not filter. Some parsers can work together, for example make and fpc. It does not filter. Some parsers can work together, for example make and fpc.
@ -262,6 +280,7 @@ type
} }
TExtToolParser = class(TComponent) TExtToolParser = class(TComponent)
private private
FNeedAfterSync: boolean;
FNeedSynchronize: boolean; FNeedSynchronize: boolean;
FTool: TAbstractExternalTool; FTool: TAbstractExternalTool;
public public
@ -273,8 +292,9 @@ type
function CreateMsgLine(OutputIndex: integer): TMessageLine; // (worker thread) function CreateMsgLine(OutputIndex: integer): TMessageLine; // (worker thread)
procedure AddMsgLine(MsgLine: TMessageLine); virtual; // (worker thread) procedure AddMsgLine(MsgLine: TMessageLine); virtual; // (worker thread)
property Tool: TAbstractExternalTool read FTool;// set when added to a tool property Tool: TAbstractExternalTool read FTool;// set when added to a tool
property NeedSynchronize: boolean read FNeedSynchronize write FNeedSynchronize; property NeedSynchronize: boolean read FNeedSynchronize write FNeedSynchronize; // set this in ImproveMessages phase etpspAfterReadLine
procedure ImproveMessages({%H-}aSynchronized: boolean); virtual; // (Synchronized=true->main, else worker thread) called after parsers added lines to Tool.WorkerMessages, Tool is in Critical section property NeedAfterSync: boolean read FNeedAfterSync write FNeedAfterSync; // set this in ImproveMessages phase etpspSynchronized
procedure ImproveMessages({%H-}aPhase: TExtToolParserSyncPhase); virtual; // Tool.WorkerMessages, Tool is in Critical section
procedure ConsistencyCheck; virtual; procedure ConsistencyCheck; virtual;
class function IsSubTool(const SubTool: string): boolean; virtual; class function IsSubTool(const SubTool: string): boolean; virtual;
class function GetMsgPattern({%H-}SubTool: string; {%H-}MsgID: integer; class function GetMsgPattern({%H-}SubTool: string; {%H-}MsgID: integer;
@ -1392,7 +1412,7 @@ begin
Tool.WorkerMessages.Add(MsgLine); Tool.WorkerMessages.Add(MsgLine);
end; end;
procedure TExtToolParser.ImproveMessages(aSynchronized: boolean); procedure TExtToolParser.ImproveMessages(aPhase: TExtToolParserSyncPhase);
begin begin
end; end;

View File

@ -147,7 +147,7 @@ type
fFileExists: TFilenameToPointerTree; fFileExists: TFilenameToPointerTree;
fIncludePath: string; // only valid if fIncludePathValidForWorkerDir=Tool.WorkerDirectory fIncludePath: string; // only valid if fIncludePathValidForWorkerDir=Tool.WorkerDirectory
fIncludePathValidForWorkerDir: string; fIncludePathValidForWorkerDir: string;
fLastWorkerImprovedMessage: array[boolean] of integer; fLastWorkerImprovedMessage: array[TExtToolParserSyncPhase] of integer;
fLineToMsgID: TPatternToMsgIDs; fLineToMsgID: TPatternToMsgIDs;
fMissingFPCMsgItem: TFPCMsgItem; fMissingFPCMsgItem: TFPCMsgItem;
fMsgID: Integer; // current message id given by ReadLine (-vq) fMsgID: Integer; // current message id given by ReadLine (-vq)
@ -176,16 +176,17 @@ type
function CreateMsgLine: TMessageLine; function CreateMsgLine: TMessageLine;
procedure AddLinkingMessages; procedure AddLinkingMessages;
procedure AddResourceMessages; procedure AddResourceMessages;
procedure ImproveMsgHiddenByIDEDirective(const SourceOK: Boolean; function NeedSource(aPhase: TExtToolParserSyncPhase; SourceOk: boolean): boolean;
var MsgLine: TMessageLine); procedure ImproveMsgHiddenByIDEDirective(aPhase: TExtToolParserSyncPhase;
procedure ImproveMsgSenderNotUsed(aSynchronized: boolean; MsgLine: TMessageLine); MsgLine: TMessageLine; SourceOK: Boolean);
procedure ImproveMsgUnitNotUsed(aSynchronized: boolean; MsgLine: TMessageLine); procedure ImproveMsgSenderNotUsed(aPhase: TExtToolParserSyncPhase; MsgLine: TMessageLine);
procedure ImproveMsgUnitNotFound(aSynchronized: boolean; procedure ImproveMsgUnitNotUsed(aPhase: TExtToolParserSyncPhase; MsgLine: TMessageLine);
procedure ImproveMsgUnitNotFound(aPhase: TExtToolParserSyncPhase;
MsgLine: TMessageLine); MsgLine: TMessageLine);
procedure ImproveMsgLinkerUndefinedReference(aSynchronized: boolean; procedure ImproveMsgLinkerUndefinedReference(aPhase: TExtToolParserSyncPhase;
MsgLine: TMessageLine);
procedure ImproveMsgIdentifierPosition(SourceOK: boolean; aSynchronized: boolean;
MsgLine: TMessageLine); MsgLine: TMessageLine);
procedure ImproveMsgIdentifierPosition(aPhase: TExtToolParserSyncPhase;
MsgLine: TMessageLine; SourceOK: boolean);
procedure Translate(p: PChar; MsgItem, TranslatedItem: TFPCMsgItem; procedure Translate(p: PChar; MsgItem, TranslatedItem: TFPCMsgItem;
out TranslatedMsg: String; out MsgType: TMessageLineUrgency); out TranslatedMsg: String; out MsgType: TMessageLineUrgency);
function LongenFilename(MsgLine: TMessageLine; aFilename: string): string; // (worker thread) function LongenFilename(MsgLine: TMessageLine; aFilename: string): string; // (worker thread)
@ -202,7 +203,7 @@ type
procedure Done; override; // called after process stopped (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; var Handled: boolean); override;
procedure AddMsgLine(MsgLine: TMessageLine); override; procedure AddMsgLine(MsgLine: TMessageLine); override;
procedure ImproveMessages(aSynchronized: boolean); override; procedure ImproveMessages(aPhase: TExtToolParserSyncPhase); override;
function GetFPCMsgIDPattern(MsgID: integer): string; override; function GetFPCMsgIDPattern(MsgID: integer): string; override;
function IsMsgID(MsgLine: TMessageLine; MsgID: integer; function IsMsgID(MsgLine: TMessageLine; MsgID: integer;
var Item: TFPCMsgItem): boolean; var Item: TFPCMsgItem): boolean;
@ -1095,6 +1096,8 @@ procedure TIDEFPCParser.InitReading;
fLineToMsgID.AddLines(Item.Pattern,Item.ID); fLineToMsgID.AddLines(Item.Pattern,Item.ID);
end; end;
var
p: TExtToolParserSyncPhase;
begin begin
inherited InitReading; inherited InitReading;
@ -1104,8 +1107,8 @@ begin
AddPatternItem(FPCMsgIDCallingResourceCompiler); AddPatternItem(FPCMsgIDCallingResourceCompiler);
//fLineToMsgID.WriteDebugReport; //fLineToMsgID.WriteDebugReport;
fLastWorkerImprovedMessage[false]:=-1; for p:=low(fLastWorkerImprovedMessage) to high(fLastWorkerImprovedMessage) do
fLastWorkerImprovedMessage[true]:=-1; fLastWorkerImprovedMessage[p]:=-1;
FreeAndNil(DirectoryStack); FreeAndNil(DirectoryStack);
end; end;
@ -1529,6 +1532,17 @@ begin
end; end;
end; end;
function TIDEFPCParser.NeedSource(aPhase: TExtToolParserSyncPhase;
SourceOk: boolean): boolean;
begin
if SourceOk then exit(false);
case aPhase of
etpspAfterReadLine: NeedSynchronize:=true;
etpspSynchronized: NeedAfterSync:=true;
end;
Result:=true;
end;
function TIDEFPCParser.IsMsgID(MsgLine: TMessageLine; MsgID: integer; function TIDEFPCParser.IsMsgID(MsgLine: TMessageLine; MsgID: integer;
var Item: TFPCMsgItem): boolean; var Item: TFPCMsgItem): boolean;
begin begin
@ -1547,40 +1561,42 @@ begin
Result:=true; Result:=true;
end; end;
procedure TIDEFPCParser.ImproveMsgHiddenByIDEDirective(const SourceOK: Boolean; procedure TIDEFPCParser.ImproveMsgHiddenByIDEDirective(
var MsgLine: TMessageLine); aPhase: TExtToolParserSyncPhase; MsgLine: TMessageLine; SourceOK: Boolean);
// check for {%H-}
var var
p: PChar; p: PChar;
X: Integer; X: Integer;
Y: Integer; Y: Integer;
begin begin
// check for {%H-} if MsgLine.Urgency>=mluError then exit;
if SourceOK and (not (mlfHiddenByIDEDirectiveValid in MsgLine.Flags)) then if mlfHiddenByIDEDirectiveValid in MsgLine.Flags then exit;
begin if NeedSource(aPhase,SourceOK) then
X:=MsgLine.Column; exit;
Y:=MsgLine.Line;
if (y<=fCurSource.LineCount) and (x-1<=fCurSource.GetLineLength(y-1)) X:=MsgLine.Column;
Y:=MsgLine.Line;
if (y<=fCurSource.LineCount) and (x-1<=fCurSource.GetLineLength(y-1))
then begin
p:=PChar(fCurSource.Source)+fCurSource.GetLineStart(y-1)+x-2;
//debugln(['TFPCParser.ImproveMsgHiddenByIDEDirective ',aFilename,' ',Y,',',X,' ',copy(fCurSource.GetLine(y-1),1,x-1),'|',copy(fCurSource.GetLine(y-1),x,100),' p=',p[0],p[1],p[2]]);
if ((p^='{') and (p[1]='%') and (p[2]='H') and (p[3]='-'))
or ((x>5) and (p[-5]='{') and (p[-4]='%') and (p[-3]='H') and (p[-2]='-')
and (p[-1]='}'))
then begin then begin
p:=PChar(fCurSource.Source)+fCurSource.GetLineStart(y-1)+x-2; //debugln(['TFPCParser.ImproveMsgHiddenByIDEDirective HIDDEN ',aFilename,' ',Y,',',X,' ',MsgLine.Msg]);
//debugln(['TFPCParser.ImproveMessages ',aFilename,' ',Y,',',X,' ',copy(fCurSource.GetLine(y-1),1,x-1),'|',copy(fCurSource.GetLine(y-1),x,100),' p=',p[0],p[1],p[2]]); MsgLine.Flags:=MsgLine.Flags+[mlfHiddenByIDEDirective,
if ((p^='{') and (p[1]='%') and (p[2]='H') and (p[3]='-')) mlfHiddenByIDEDirectiveValid];
or ((x>5) and (p[-5]='{') and (p[-4]='%') and (p[-3]='H') and (p[-2]='-')
and (p[-1]='}'))
then begin
//debugln(['TFPCParser.ImproveMessages HIDDEN ',aFilename,' ',Y,',',X,' ',MsgLine.Msg]);
MsgLine.Flags:=MsgLine.Flags+[mlfHiddenByIDEDirective,
mlfHiddenByIDEDirectiveValid];
end;
end; end;
MsgLine.Flags:=MsgLine.Flags+[mlfHiddenByIDEDirectiveValid];
end; end;
MsgLine.Flags:=MsgLine.Flags+[mlfHiddenByIDEDirectiveValid];
end; end;
procedure TIDEFPCParser.ImproveMsgSenderNotUsed(aSynchronized: boolean; procedure TIDEFPCParser.ImproveMsgSenderNotUsed(
MsgLine: TMessageLine); aPhase: TExtToolParserSyncPhase; MsgLine: TMessageLine);
// FPCMsgIDParameterNotUsed = 5024; Parameter "$1" not used // FPCMsgIDParameterNotUsed = 5024; Parameter "$1" not used
begin begin
if aSynchronized then exit; if aPhase<>etpspAfterReadLine then exit;
if (MsgLine.Urgency<=mluVerbose) then exit; if (MsgLine.Urgency<=mluVerbose) then exit;
// check for Sender not used // check for Sender not used
if HideHintsSenderNotUsed if HideHintsSenderNotUsed
@ -1589,18 +1605,18 @@ begin
end; end;
end; end;
procedure TIDEFPCParser.ImproveMsgUnitNotUsed(aSynchronized: boolean; procedure TIDEFPCParser.ImproveMsgUnitNotUsed(aPhase: TExtToolParserSyncPhase;
MsgLine: TMessageLine); MsgLine: TMessageLine);
// check for Unit not used message in main sources // check for Unit not used message in main sources
// and change urgency to merely 'verbose' // and change urgency to merely 'verbose'
const const
FPCMsgIDUnitNotUsed = 5023; // Unit "$1" not used in $2 FPCMsgIDUnitNotUsed = 5023; // Unit "$1" not used in $2
begin begin
if aSynchronized then exit; if aPhase<>etpspAfterReadLine then exit;
if (MsgLine.Urgency<=mluVerbose) then exit; if (MsgLine.Urgency<=mluVerbose) then exit;
if not IsMsgID(MsgLine,FPCMsgIDUnitNotUsed,fMsgItemUnitNotUsed) then exit; if not IsMsgID(MsgLine,FPCMsgIDUnitNotUsed,fMsgItemUnitNotUsed) then exit;
//debugln(['TIDEFPCParser.ImproveMsgUnitNotUsed ',aSynchronized,' ',MsgLine.Msg]); //debugln(['TIDEFPCParser.ImproveMsgUnitNotUsed ',aPhase=etpspSynchronized,' ',MsgLine.Msg]);
// unit not used // unit not used
if IndexInStringList(FilesToIgnoreUnitNotUsed,cstFilename,MsgLine.Filename)>=0 then if IndexInStringList(FilesToIgnoreUnitNotUsed,cstFilename,MsgLine.Filename)>=0 then
begin begin
@ -1608,14 +1624,14 @@ begin
end else if HideHintsUnitNotUsedInMainSource end else if HideHintsUnitNotUsedInMainSource
and FilenameIsAbsolute(MsgLine.Filename) and FilenameIsAbsolute(MsgLine.Filename)
and ((CompareFileExt(MsgLine.Filename, 'lpr', false)=0) and ((CompareFileExt(MsgLine.Filename, 'lpr', false)=0)
or FileExists(ChangeFileExt(MsgLine.Filename, '.lpk'), aSynchronized)) or FileExists(ChangeFileExt(MsgLine.Filename, '.lpk'), aPhase=etpspSynchronized))
then begin then begin
// a lpk/lpr does not use a unit => almost always not important // a lpk/lpr does not use a unit => almost always not important
MsgLine.Urgency:=mluVerbose; MsgLine.Urgency:=mluVerbose;
end; end;
end; end;
procedure TIDEFPCParser.ImproveMsgUnitNotFound(aSynchronized: boolean; procedure TIDEFPCParser.ImproveMsgUnitNotFound(aPhase: TExtToolParserSyncPhase;
MsgLine: TMessageLine); MsgLine: TMessageLine);
procedure FixSourcePos(CodeBuf: TCodeBuffer; MissingUnitname: string); procedure FixSourcePos(CodeBuf: TCodeBuffer; MissingUnitname: string);
@ -1718,9 +1734,14 @@ begin
if not IsMsgID(MsgLine,FPCMsgIDCantFindUnitUsedBy,fMsgItemCantFindUnitUsedBy) if not IsMsgID(MsgLine,FPCMsgIDCantFindUnitUsedBy,fMsgItemCantFindUnitUsedBy)
then // Can't find unit $1 used by $2 then // Can't find unit $1 used by $2
exit; exit;
if (not aSynchronized) then begin case aPhase of
NeedSynchronize:=true; etpspAfterReadLine:
exit; begin
NeedSynchronize:=true;
exit;
end;
etpspSynchronized: ;
etpspAfterSync: exit;
end; end;
if not GetFPCMsgValues(MsgLine,MissingUnitName,UsedByUnit) then if not GetFPCMsgValues(MsgLine,MissingUnitName,UsedByUnit) then
@ -1856,13 +1877,13 @@ begin
end; end;
procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference( procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
aSynchronized: boolean; MsgLine: TMessageLine); aPhase: TExtToolParserSyncPhase; MsgLine: TMessageLine);
{ For example: { For example:
/path/lib/x86_64-linux/blaunit.o: In function `FORMCREATE': /path/lib/x86_64-linux/blaunit.o: In function `FORMCREATE':
/path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA' /path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA'
} }
function CheckForFileAndLineNumber: boolean; function CheckForLDFileAndLineNumber: boolean;
var var
p: PChar; p: PChar;
Msg: String; Msg: String;
@ -1871,7 +1892,7 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
i: SizeInt; i: SizeInt;
begin begin
Result:=false; Result:=false;
if aSynchronized then exit; if aPhase<>etpspAfterReadLine then exit;
if MsgLine.HasSourcePosition then exit; if MsgLine.HasSourcePosition then exit;
Msg:=MsgLine.Msg; Msg:=MsgLine.Msg;
p:=PChar(Msg); p:=PChar(Msg);
@ -1913,11 +1934,11 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
begin begin
if MsgLine.SubTool<>SubToolFPCLinker then exit; if MsgLine.SubTool<>SubToolFPCLinker then exit;
if CheckForFileAndLineNumber then exit; if CheckForLDFileAndLineNumber then exit;
end; end;
procedure TIDEFPCParser.ImproveMsgIdentifierPosition(SourceOK: boolean; procedure TIDEFPCParser.ImproveMsgIdentifierPosition(
aSynchronized: boolean; MsgLine: TMessageLine); aPhase: TExtToolParserSyncPhase; MsgLine: TMessageLine; SourceOK: boolean);
{ FPC report the token after the identifier { FPC report the token after the identifier
=> fix the position => fix the position
Examples: Examples:
@ -1927,6 +1948,8 @@ procedure TIDEFPCParser.ImproveMsgIdentifierPosition(SourceOK: boolean;
"procedure TMyClass.DoIt ;" "procedure TMyClass.DoIt ;"
test.pas(7,26) Error: (3047) method identifier expected test.pas(7,26) Error: (3047) method identifier expected
} }
const
AttrPosChecked = 'PosChecked';
var var
LineRange: TLineRange; LineRange: TLineRange;
Line, Col: Integer; Line, Col: Integer;
@ -1943,11 +1966,11 @@ begin
and (not IsMsgID(MsgLine,FPCMsgIDMethodIdentifierExpected,fMsgItemMethodIdentifierExpected)) and (not IsMsgID(MsgLine,FPCMsgIDMethodIdentifierExpected,fMsgItemMethodIdentifierExpected))
then then
exit; exit;
if (not SourceOK) then begin if MsgLine.Attribute[AttrPosChecked]<>'' then exit;
if (not aSynchronized) then if NeedSource(aPhase,SourceOK) then
NeedSynchronize:=true;
exit; exit;
end; MsgLine.Attribute[AttrPosChecked]:=ClassName;
//DebuglnThreadLog(['Old Line=',Line,' ',MsgLine.Column]); //DebuglnThreadLog(['Old Line=',Line,' ',MsgLine.Column]);
if Line>=fCurSource.LineCount then exit; if Line>=fCurSource.LineCount then exit;
if MsgLine.MsgID=FPCMsgIDIdentifierNotFound then begin if MsgLine.MsgID=FPCMsgIDIdentifierNotFound then begin
@ -2364,7 +2387,7 @@ begin
MsgLine.Attribute[FPCMsgAttrWorkerDirectory]:=Tool.WorkerDirectory; MsgLine.Attribute[FPCMsgAttrWorkerDirectory]:=Tool.WorkerDirectory;
end; end;
procedure TIDEFPCParser.ImproveMessages(aSynchronized: boolean); procedure TIDEFPCParser.ImproveMessages(aPhase: TExtToolParserSyncPhase);
var var
i: Integer; i: Integer;
MsgLine: TMessageLine; MsgLine: TMessageLine;
@ -2377,7 +2400,7 @@ var
PrevMsgLine: TMessageLine; PrevMsgLine: TMessageLine;
begin begin
//debugln(['TIDEFPCParser.ImproveMessages START ',aSynchronized,' Last=',fLastWorkerImprovedMessage[aSynchronized],' Now=',Tool.WorkerMessages.Count]); //debugln(['TIDEFPCParser.ImproveMessages START ',aSynchronized,' Last=',fLastWorkerImprovedMessage[aSynchronized],' Now=',Tool.WorkerMessages.Count]);
for i:=fLastWorkerImprovedMessage[aSynchronized]+1 to Tool.WorkerMessages.Count-1 do for i:=fLastWorkerImprovedMessage[aPhase]+1 to Tool.WorkerMessages.Count-1 do
begin begin
MsgLine:=Tool.WorkerMessages[i]; MsgLine:=Tool.WorkerMessages[i];
Y:=MsgLine.Line; Y:=MsgLine.Line;
@ -2385,33 +2408,43 @@ begin
if (Y>0) and (X>0) if (Y>0) and (X>0)
and (MsgLine.SubTool=SubToolFPC) and (MsgLine.Filename<>'') and (MsgLine.SubTool=SubToolFPC) and (MsgLine.Filename<>'')
then begin then begin
// try to find for short file name the full file name
aFilename:=MsgLine.Filename; aFilename:=MsgLine.Filename;
if (not FilenameIsAbsolute(aFilename)) then begin if (not FilenameIsAbsolute(aFilename)) then begin
MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory]; // short file name => 1. try to find the full file name
if fIncludePathValidForWorkerDir<>MsgWorkerDir then begin if i>0 then begin
// fetch include path PrevMsgLine:=Tool.WorkerMessages[i-1];
if aSynchronized then begin if (PrevMsgLine.SubTool=SubToolFPC)
fIncludePathValidForWorkerDir:=MsgWorkerDir; and FilenameIsAbsolute(PrevMsgLine.Filename)
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory( and (CompareFilenames(ExtractFilename(PrevMsgLine.Filename),ExtractFilename(aFilename))=0)
ChompPathDelim(MsgWorkerDir)); then begin
end else begin // same file as previous message => use it
NeedSynchronize:=true; aFilename:=PrevMsgLine.Filename;
MsgLine.Filename:=aFilename;
end; end;
end; end;
if fIncludePathValidForWorkerDir=MsgWorkerDir then begin end;
if i>0 then begin if (not FilenameIsAbsolute(aFilename)) then begin
PrevMsgLine:=Tool.WorkerMessages[i-1]; // short file name => 2. try include path
if (PrevMsgLine.SubTool=SubToolFPC) MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory];
and FilenameIsAbsolute(PrevMsgLine.Filename) if fIncludePathValidForWorkerDir<>MsgWorkerDir then begin
and (CompareFilenames(ExtractFilename(PrevMsgLine.Filename),ExtractFilename(aFilename))=0) // fetch include path from IDE
then begin case aPhase of
// same file as previous message => use it etpspAfterReadLine:
aFilename:=PrevMsgLine.Filename; NeedSynchronize:=true;
etpspSynchronized:
begin
fIncludePathValidForWorkerDir:=MsgWorkerDir;
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
ChompPathDelim(MsgWorkerDir));
NeedAfterSync:=true;
end; end;
end; end;
if not FilenameIsAbsolute(aFilename) then end;
aFilename:=SearchFileInPath(aFilename,MsgWorkerDir,fIncludePath,';', if (aPhase in [etpspAfterReadLine,etpspAfterSync])
and (fIncludePathValidForWorkerDir=MsgWorkerDir) then begin
// include path is valid and in worker thread
// -> search file
aFilename:=SearchFileInPath(aFilename,MsgWorkerDir,fIncludePath,';',
[sffSearchLoUpCase]); [sffSearchLoUpCase]);
if aFilename<>'' then if aFilename<>'' then
MsgLine.Filename:=aFilename; MsgLine.Filename:=aFilename;
@ -2426,34 +2459,46 @@ begin
and (CompareFilenames(aFilename,fCurSource.Filename)=0) then begin and (CompareFilenames(aFilename,fCurSource.Filename)=0) then begin
SourceOK:=true; SourceOK:=true;
end else begin end else begin
if aSynchronized then begin // need source
// load source file case aPhase of
//debugln(['TFPCParser.ImproveMessages loading ',aFilename]); etpspAfterReadLine:
Code:=CodeToolBoss.LoadFile(aFilename,true,false);
if Code<>nil then begin
if fCurSource=nil then
fCurSource:=TCodeBuffer.Create;
fCurSource.Filename:=aFilename;
fCurSource.Source:=Code.Source;
SourceOK:=true;
end;
end else begin
NeedSynchronize:=true; NeedSynchronize:=true;
etpspSynchronized:
begin
// load source file
//debugln(['TFPCParser.ImproveMessages loading ',aFilename]);
Code:=CodeToolBoss.LoadFile(aFilename,true,false);
if Code<>nil then begin
if fCurSource=nil then
fCurSource:=TCodeBuffer.Create;
fCurSource.Filename:=aFilename;
if Code.FileOnDiskNeedsUpdate then begin
// IDE buffer contains changes that are not yet saved to disk
// The compiler messages are about the disk file
// => load the file
fCurSource.LoadFromFile(aFilename);
end else begin
// IDE buffer valid => just copy
fCurSource.Source:=Code.Source;
end;
SourceOK:=true;
NeedAfterSync:=true;
end;
end;
end; end;
end; end;
end; end;
if MsgLine.Urgency<mluError then ImproveMsgHiddenByIDEDirective(aPhase, MsgLine, SourceOK);
ImproveMsgHiddenByIDEDirective(SourceOK, MsgLine); ImproveMsgUnitNotFound(aPhase, MsgLine);
ImproveMsgUnitNotFound(aSynchronized, MsgLine); ImproveMsgUnitNotUsed(aPhase, MsgLine);
ImproveMsgUnitNotUsed(aSynchronized, MsgLine); ImproveMsgSenderNotUsed(aPhase, MsgLine);
ImproveMsgSenderNotUsed(aSynchronized, MsgLine); ImproveMsgIdentifierPosition(aPhase, MsgLine, SourceOK);
ImproveMsgIdentifierPosition(SourceOK, aSynchronized, MsgLine);
end else if MsgLine.SubTool=SubToolFPCLinker then begin end else if MsgLine.SubTool=SubToolFPCLinker then begin
ImproveMsgLinkerUndefinedReference(aSynchronized, MsgLine); ImproveMsgLinkerUndefinedReference(aPhase, MsgLine);
end; end;
end; end;
fLastWorkerImprovedMessage[aSynchronized]:=Tool.WorkerMessages.Count-1; fLastWorkerImprovedMessage[aPhase]:=Tool.WorkerMessages.Count-1;
end; end;
class function TIDEFPCParser.IsSubTool(const SubTool: string): boolean; class function TIDEFPCParser.IsSubTool(const SubTool: string): boolean;

View File

@ -124,6 +124,7 @@ type
FThread: TExternalToolThread; FThread: TExternalToolThread;
fExecuteAfter: TFPList; // list of TExternalTool fExecuteAfter: TFPList; // list of TExternalTool
fExecuteBefore: TFPList; // list of TExternalTool fExecuteBefore: TFPList; // list of TExternalTool
fNeedAfterSync: boolean;
fOutputCountNotified: integer; fOutputCountNotified: integer;
procedure ProcessRunning; // (worker thread) after Process.Execute procedure ProcessRunning; // (worker thread) after Process.Execute
procedure ProcessStopped; // (worker thread) when process stopped procedure ProcessStopped; // (worker thread) when process stopped
@ -428,10 +429,11 @@ begin
for i:=0 to ParserCount-1 do begin for i:=0 to ParserCount-1 do begin
Parser:=Parsers[i]; Parser:=Parsers[i];
Parser.NeedSynchronize:=false; Parser.NeedSynchronize:=false;
Parser.NeedAfterSync:=false;
{$IFDEF VerboseExtToolAddOutputLines} {$IFDEF VerboseExtToolAddOutputLines}
DebuglnThreadLog(['TExternalTool.AddOutputLines ',DbgSName(Parser),' IMPROVE threaded ...']); DebuglnThreadLog(['TExternalTool.AddOutputLines ',DbgSName(Parser),' IMPROVE after ReadLine ...']);
{$ENDIF} {$ENDIF}
Parser.ImproveMessages(false); Parser.ImproveMessages(etpspAfterReadLine);
if Parser.NeedSynchronize then if Parser.NeedSynchronize then
NeedSynchronize:=true; NeedSynchronize:=true;
end; end;
@ -450,6 +452,17 @@ begin
EnterCriticalSection; EnterCriticalSection;
try try
if fNeedAfterSync then begin
for i:=0 to ParserCount-1 do begin
Parser:=Parsers[i];
if not Parser.NeedAfterSync then continue;
{$IFDEF VerboseExtToolAddOutputLines}
DebuglnThreadLog(['TExternalTool.AddOutputLines ',DbgSName(Parser),' IMPROVE after sync ...']);
{$ENDIF}
Parser.ImproveMessages(etpspAfterSync);
end;
end;
// feed new messages into all viewers // feed new messages into all viewers
if OldMsgCount<WorkerMessages.Count then begin if OldMsgCount<WorkerMessages.Count then begin
for i:=0 to ViewCount-1 do begin for i:=0 to ViewCount-1 do begin
@ -548,14 +561,17 @@ var
begin begin
EnterCriticalSection; EnterCriticalSection;
try try
fNeedAfterSync:=false;
for i:=0 to ParserCount-1 do begin for i:=0 to ParserCount-1 do begin
Parser:=Parsers[i]; Parser:=Parsers[i];
if not Parser.NeedSynchronize then continue; if not Parser.NeedSynchronize then continue;
{$IFDEF VerboseExtToolAddOutputLines} {$IFDEF VerboseExtToolAddOutputLines}
//debugln(['TExternalTool.SynchronizedImproveMessages ',DbgSName(Parser),' ...']); //debugln(['TExternalTool.SynchronizedImproveMessages ',DbgSName(Parser),' ...']);
{$ENDIF} {$ENDIF}
Parser.ImproveMessages(true); Parser.ImproveMessages(etpspSynchronized);
Parser.NeedSynchronize:=false; Parser.NeedSynchronize:=false;
if Parser.NeedAfterSync then
fNeedAfterSync:=true;
end; end;
finally finally
LeaveCriticalSection; LeaveCriticalSection;