From 4665cd188941cf68e4318f2ce6c747b769fbf8bf Mon Sep 17 00:00:00 2001 From: mattias Date: Thu, 22 May 2014 13:47:53 +0000 Subject: [PATCH] IDE: fpc msg parser: search for include files git-svn-id: trunk@45150 - --- components/ideintf/ideexterntoolintf.pas | 4 + ide/etfpcmsgparser.pas | 157 +++++++++++++++-------- ide/etquickfixes.pas | 18 +-- ide/unitdependencies.pas | 2 +- 4 files changed, 120 insertions(+), 61 deletions(-) diff --git a/components/ideintf/ideexterntoolintf.pas b/components/ideintf/ideexterntoolintf.pas index c14b4c1122..d467eb326e 100644 --- a/components/ideintf/ideexterntoolintf.pas +++ b/components/ideintf/ideexterntoolintf.pas @@ -286,7 +286,11 @@ type read FHideHintsUnitNotUsedInMainSource write FHideHintsUnitNotUsedInMainSource default true; end; + TFPCParserClass = class of TFPCParser; +var + IDEFPCParser: TFPCParserClass = nil; +type { TMakeParser - standard parser for 'make' messages, implemented by IDE } TMakeParser = class(TExtToolParser) diff --git a/ide/etfpcmsgparser.pas b/ide/etfpcmsgparser.pas index d4445ee677..b0ee1ddc01 100644 --- a/ide/etfpcmsgparser.pas +++ b/ide/etfpcmsgparser.pas @@ -124,6 +124,12 @@ type fLastWorkerImprovedMessage: array[boolean] of integer; fLastSource: TCodeBuffer; fFileExists: TFilenameToPointerTree; + fIncPathValidForWorkerDir: string; + fIncPath: string; + fFPCMsgItemUnitNotUsed: TFPCMsgItem; + fFPCMsgItemCantFindUnitUsedBy: TFPCMsgItem; + fFPCMsgItemCompilationAborted: TFPCMsgItem; + fMissingFPCMsgItem: TFPCMsgItem; function FileExists(const Filename: string; aSynchronized: boolean): boolean; function CheckForMsgId(p: PChar): boolean; // (MsgId) message function CheckForFileLineColMessage(p: PChar): boolean; // the normal messages: filename(y,x): Hint: .. @@ -140,16 +146,18 @@ type function CheckForLoadFromUnit(p: PChar): Boolean; function CheckForWindresErrors(p: PChar): boolean; function CreateMsgLine: TMessageLine; - function CheckMsgID(MsgLine: TMessageLine; MsgID: integer): boolean; + function IsMsgID(MsgLine: TMessageLine; MsgID: integer; + var Item: TFPCMsgItem): boolean; procedure ImproveMsgHiddenByIDEDirective(const SourceOK: Boolean; var MsgLine: TMessageLine); - procedure ImproveMsgSenderNotUsed(MsgLine: TMessageLine); + procedure ImproveMsgSenderNotUsed(aSynchronized: boolean; MsgLine: TMessageLine); procedure ImproveMsgUnitNotUsed(aSynchronized: boolean; - const aFilename: String; var MsgLine: TMessageLine); + const aFilename: String; MsgLine: TMessageLine); procedure ImproveMsgUnitNotFound(aSynchronized: boolean; - var MsgLine: TMessageLine); + MsgLine: TMessageLine); 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) public DirectoryStack: TStrings; MsgFilename: string; // e.g. /path/to/fpcsrc/compiler/msg/errore.msg @@ -162,7 +170,6 @@ type procedure InitReading; override; // called if 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; - function LongenFilename(aFilename: string): string; procedure ImproveMessages(aSynchronized: boolean); override; function GetFPCMsgIDPattern(MsgID: integer): string; override; class function IsSubTool(const SubTool: string): boolean; override; @@ -995,6 +1002,9 @@ begin fLastWorkerImprovedMessage[false]:=-1; fLastWorkerImprovedMessage[true]:=-1; + + fIncPathValidForWorkerDir:='-'; + FreeAndNil(DirectoryStack); end; procedure TIDEFPCParser.Done; @@ -1100,9 +1110,14 @@ begin if ReadString(p,'Fatal: ') then begin MsgType:=mluFatal; // check for "Fatal: compilation aborted" - MsgItem:=MsgFile.GetMsg(MsgIDCompilationAborted); + if fFPCMsgItemCompilationAborted=nil then begin + fFPCMsgItemCompilationAborted:=MsgFile.GetMsg(MsgIDCompilationAborted); + if fFPCMsgItemCompilationAborted=nil then + fFPCMsgItemCompilationAborted:=fMissingFPCMsgItem; + end; p2:=p; - if (MsgItem<>nil) and ReadString(p2,MsgItem.Pattern) then + if (fFPCMsgItemCompilationAborted<>fMissingFPCMsgItem) + and ReadString(p2,fFPCMsgItemCompilationAborted.Pattern) then CheckFinalNote; end else if ReadString(p,'Panic') then @@ -1149,10 +1164,10 @@ begin if (fMsgID>0) then begin TranslatedItem:=nil; MsgItem:=nil; - if (TranslationFile<>nil) then - TranslatedItem:=TranslationFile.GetMsg(fMsgID); if (MsgFile<>nil) then MsgItem:=MsgFile.GetMsg(fMsgID); + if (TranslationFile<>nil) then + TranslatedItem:=TranslationFile.GetMsg(fMsgID); Translate(p,MsgItem,TranslatedItem,TranslatedMsg,MsgType); if (TranslatedItem=nil) and (MsgItem=nil) then begin if ConsoleVerbosity>=0 then @@ -1458,16 +1473,19 @@ begin Result.MsgID:=fMsgID; end; -function TIDEFPCParser.CheckMsgID(MsgLine: TMessageLine; MsgID: integer - ): boolean; -var - Item: TFPCMsgItem; +function TIDEFPCParser.IsMsgID(MsgLine: TMessageLine; MsgID: integer; + var Item: TFPCMsgItem): boolean; begin if MsgLine.MsgID=MsgID then exit(true); - if MsgLine.MsgID<>0 then exit(false); - Item:=MsgFile.GetMsg(MsgID); - if Item=nil then exit; - if Item.PatternFits(MsgLine.Msg)<0 then exit(false); + Result:=false; + if MsgLine.MsgID<>0 then exit; + if Item=nil then begin + Item:=MsgFile.GetMsg(MsgID); + if Item=nil then + Item:=fMissingFPCMsgItem; + end; + if Item=fMissingFPCMsgItem then exit; + if Item.PatternFits(MsgLine.Msg)<0 then exit; MsgLine.MsgID:=MsgID; Result:=true; end; @@ -1480,10 +1498,10 @@ var Y: Integer; begin // check for {%H-} - X:=MsgLine.Column; - Y:=MsgLine.Line; if SourceOK and (not (mlfHiddenByIDEDirectiveValid in MsgLine.Flags)) then begin + X:=MsgLine.Column; + Y:=MsgLine.Line; if (y<=fLastSource.LineCount) and (x-1<=fLastSource.GetLineLength(y-1)) then begin p:=PChar(fLastSource.Source)+fLastSource.GetLineStart(y-1)+x-2; @@ -1501,9 +1519,11 @@ begin end; end; -procedure TIDEFPCParser.ImproveMsgSenderNotUsed(MsgLine: TMessageLine); +procedure TIDEFPCParser.ImproveMsgSenderNotUsed(aSynchronized: boolean; + MsgLine: TMessageLine); // FPCMsgIDParameterNotUsed = 5024; Parameter "$1" not used begin + if aSynchronized then exit; if (MsgLine.Urgency<=mluVerbose) then exit; // check for Sender not used if HideHintsSenderNotUsed @@ -1513,7 +1533,7 @@ begin end; procedure TIDEFPCParser.ImproveMsgUnitNotUsed(aSynchronized: boolean; - const aFilename: String; var MsgLine: TMessageLine); + const aFilename: String; MsgLine: TMessageLine); // check for Unit not used message in main sources // and change urgency to merely 'verbose' const @@ -1521,7 +1541,7 @@ const begin if aSynchronized then exit; if (MsgLine.Urgency<=mluVerbose) then exit; - if not CheckMsgID(MsgLine,FPCMsgIDUnitNotUsed) then exit; + if not IsMsgID(MsgLine,FPCMsgIDUnitNotUsed,fFPCMsgItemUnitNotUsed) then exit; //debugln(['TIDEFPCParser.ImproveMsgUnitNotUsed ',aSynchronized,' ',MsgLine.Msg]); // unit not used @@ -1539,7 +1559,7 @@ begin end; procedure TIDEFPCParser.ImproveMsgUnitNotFound(aSynchronized: boolean; - var MsgLine: TMessageLine); + MsgLine: TMessageLine); procedure FixSourcePos(CodeBuf: TCodeBuffer; MissingUnitname: string); var @@ -1637,11 +1657,15 @@ var OnlyInstalled: Boolean; s: String; begin - if (not aSynchronized) then exit; - if not CheckMsgID(MsgLine,10022) then // Can't find unit $1 used by $2 + if MsgLine.Urgencynil) - and (CompareFilenames(aFilename,fLastSource.Filename)=0) then begin - SourceOK:=true; - end else begin - if aSynchronized then begin - // load source file - //debugln(['TFPCParser.ImproveMessages loading ',aFilename]); - Code:=CodeToolBoss.LoadFile(aFilename,true,false); - if Code<>nil then begin - if fLastSource=nil then - fLastSource:=TCodeBuffer.Create; - fLastSource.Filename:=aFilename; - fLastSource.Source:=Code.Source; - SourceOK:=true; + if not FilenameIsAbsolute(aFilename) then begin + MsgWorkerDir:=MsgLine.Attribute['WD']; + if fIncPathValidForWorkerDir<>MsgWorkerDir then begin + // fetch include path + if aSynchronized then begin + fIncPathValidForWorkerDir:=MsgWorkerDir; + fIncPath:=CodeToolBoss.GetIncludePathForDirectory( + ChompPathDelim(MsgWorkerDir)); + end else begin + NeedSynchronize:=true; end; - end else begin - NeedSynchronize:=true; + end; + if fIncPathValidForWorkerDir=MsgWorkerDir then begin + aFilename:=SearchFileInPath(aFilename,MsgWorkerDir,fIncPath,';', + [sffSearchLoUpCase]); + if aFilename<>'' then + MsgLine.Filename:=aFilename; end; end; - ImproveMsgHiddenByIDEDirective(SourceOK, MsgLine); + // get source + SourceOK:=false; + aFilename:=MsgLine.GetFullFilename; + if FilenameIsAbsolute(aFilename) then begin + if (fLastSource<>nil) + and (CompareFilenames(aFilename,fLastSource.Filename)=0) then begin + SourceOK:=true; + end else begin + if aSynchronized then begin + // load source file + //debugln(['TFPCParser.ImproveMessages loading ',aFilename]); + Code:=CodeToolBoss.LoadFile(aFilename,true,false); + if Code<>nil then begin + if fLastSource=nil then + fLastSource:=TCodeBuffer.Create; + fLastSource.Filename:=aFilename; + fLastSource.Source:=Code.Source; + SourceOK:=true; + end; + end else begin + NeedSynchronize:=true; + end; + end; + end; + + if MsgLine.Urgency4046) // Constructing a class "$1" with abstract method "$2" or (not Msg.HasSourcePosition) then exit; - if not TFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then begin + if not IDEFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then begin debugln(['TQuickFixClassWithAbstractMethods.IsApplicable can not extract values: ',Msg.Msg]); exit; end; @@ -283,7 +283,7 @@ begin if Fixes.LineCount<>1 then exit; Msg:=Fixes.Lines[0]; if not IsApplicable(Msg) then exit; - if not TFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then exit; + if not IDEFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then exit; Fixes.AddMenuItem(Self,Msg,'Show abstract methods of "'+aClassName+'"'); end; @@ -300,7 +300,7 @@ var NewTopLine: integer; begin if not IsApplicable(Msg) then exit; - if not TFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then begin + if not IDEFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then begin debugln(['TQuickFixClassWithAbstractMethods.QuickFix invalid message ',Msg.Msg]); exit; end; @@ -363,7 +363,7 @@ begin and (Msg.MsgID<>10022) // Can't find unit $1 used by $2 and (Msg.MsgID<>10023)) // Unit $1 was not found but $2 exists then exit; - if not TFPCParser.GetFPCMsgValues(Msg,Unit1,Unit2) then begin + if not IDEFPCParser.GetFPCMsgValues(Msg,Unit1,Unit2) then begin debugln(['TQuickFixUnitNotFound_Remove.IsApplicable failed to extract unit names: ',Msg.Msg]); exit; end; @@ -379,7 +379,7 @@ begin if Fixes.LineCount<>1 then exit; Msg:=Fixes.Lines[0]; if not IsApplicable(Msg) then exit; - if not TFPCParser.GetFPCMsgValues(Msg,Unit1,Unit2) then exit; + if not IDEFPCParser.GetFPCMsgValues(Msg,Unit1,Unit2) then exit; Fixes.AddMenuItem(Self,Msg,'Remove uses "'+Unit1+'"'); end; @@ -391,7 +391,7 @@ var Code: TCodeBuffer; begin if not IsApplicable(Msg) then exit; - if not TFPCParser.GetFPCMsgValues(Msg,MissingUnitName,SrcUnitName) then begin + if not IDEFPCParser.GetFPCMsgValues(Msg,MissingUnitName,SrcUnitName) then begin debugln(['TQuickFixUnitNotFound_Remove.QuickFix invalid message ',Msg.Msg]); exit; end; @@ -431,7 +431,7 @@ begin or (Msg.MsgID<>5000) // identifier not found "$1" or (not Msg.HasSourcePosition) then exit; - Identifier:=TFPCParser.GetFPCMsgValue1(Msg); + Identifier:=IDEFPCParser.GetFPCMsgValue1(Msg); if not IsValidIdent(Identifier) then exit; // check if message position is at end of identifier @@ -462,7 +462,7 @@ begin if Fixes.LineCount<>1 then exit; Msg:=Fixes.Lines[0]; if not IsApplicable(Msg) then exit; - Identifier:=TFPCParser.GetFPCMsgValue1(Msg); + Identifier:=IDEFPCParser.GetFPCMsgValue1(Msg); if Identifier='' then exit; Fixes.AddMenuItem(Self,Msg,'Create local variable "'+Identifier+'"'); // ToDo: add private/public variable @@ -479,7 +479,7 @@ var NewTopLine: integer; begin if Msg=nil then exit; - Identifier:=TFPCParser.GetFPCMsgValue1(Msg); + Identifier:=IDEFPCParser.GetFPCMsgValue1(Msg); if Identifier='' then exit; if not LazarusIDE.BeginCodeTools then begin diff --git a/ide/unitdependencies.pas b/ide/unitdependencies.pas index 473d4298f6..f9c1904275 100644 --- a/ide/unitdependencies.pas +++ b/ide/unitdependencies.pas @@ -450,7 +450,7 @@ var UnitName2: String; Path: TStringList; begin - if not TFPCParser.GetFPCMsgValues(Msg,UnitName1,UnitName2) then begin + if not IDEFPCParser.GetFPCMsgValues(Msg,UnitName1,UnitName2) then begin debugln(['TQuickFixCircularUnitReference.QuickFix invalid message ',Msg.Msg]); exit; end;