IDE: fpc parser: find ld message file:line: msg

git-svn-id: trunk@45186 -
This commit is contained in:
mattias 2014-05-26 14:46:29 +00:00
parent 53ca8fe17d
commit 04d59be9be
3 changed files with 92 additions and 37 deletions

View File

@ -167,6 +167,8 @@ type
procedure ImproveMsgUnitNotUsed(aSynchronized: boolean; MsgLine: TMessageLine);
procedure ImproveMsgUnitNotFound(aSynchronized: boolean;
MsgLine: TMessageLine);
procedure ImproveMsgLinkerUndefinedReference(aSynchronized: boolean;
MsgLine: TMessageLine);
procedure Translate(p: PChar; MsgItem, TranslatedItem: TFPCMsgItem;
out TranslatedMsg: String; out MsgType: TMessageLineUrgency);
function LongenFilename(MsgLine: TMessageLine; aFilename: string): string; // (worker thread)
@ -1386,6 +1388,9 @@ For example:
Examples for linking errors:
linkerror.o(.text$_main+0x9):linkerror.pas: undefined reference to `NonExistingFunction'
/path/lib/x86_64-linux/blaunit.o: In function `FORMCREATE':
/path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA'
Closing script ppas.sh
Mac OS X linker example:
@ -1420,7 +1425,7 @@ begin
MsgLine:=inherited CreateMsgLine(i);
MsgLine.MsgID:=0;
MsgLine.SubTool:=SubToolFPCLinker;
MsgLine.Urgency:=mluWarning;
MsgLine.Urgency:=mluImportant;
AddMsgLine(MsgLine);
end;
end;
@ -1780,6 +1785,67 @@ begin
end;
end;
procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
aSynchronized: boolean; MsgLine: TMessageLine);
{ For example:
/path/lib/x86_64-linux/blaunit.o: In function `FORMCREATE':
/path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA'
}
function CheckForFileAndLineNumber: boolean;
var
p: PChar;
Msg: String;
aFilename: String;
LineNumber: Integer;
i: SizeInt;
begin
Result:=false;
if aSynchronized then exit;
if MsgLine.HasSourcePosition then exit;
Msg:=MsgLine.Msg;
p:=PChar(Msg);
// check for "filename:decimals: message"
// or unit1.o(.text+0x3a):unit1.pas:48: undefined reference to `DoesNotExist'
// read filename
repeat
if p^=#0 then exit;
inc(p);
until (p^=':') and (p[1] in ['0'..'9']);
aFilename:=LeftStr(Msg,p-PChar(Msg));
// check for something):filename
i:=Pos('):',aFilename);
if i>0 then
Delete(aFilename,1,i+1);
aFilename:=TrimFilename(aFilename);
// read line number
inc(p);
LineNumber:=0;
while p^ in ['0'..'9'] do begin
LineNumber:=LineNumber*10+ord(p^)-ord('0');
if LineNumber>9999999 then exit;
inc(p);
end;
if p^<>':' then exit;
inc(p);
while p^ in [' '] do inc(p);
Result:=true;
MsgLine.Msg:=copy(Msg,p-PChar(Msg)+1,length(Msg));
MsgLine.Filename:=aFilename;
MsgLine.Line:=LineNumber;
MsgLine.Column:=1;
MsgLine.Urgency:=mluError;
end;
begin
if MsgLine.SubTool<>SubToolFPCLinker then exit;
if CheckForFileAndLineNumber then exit;
end;
procedure TIDEFPCParser.Translate(p: PChar; MsgItem, TranslatedItem: TFPCMsgItem;
out TranslatedMsg: String; out MsgType: TMessageLineUrgency);
begin
@ -2168,7 +2234,7 @@ begin
then begin
// try to find for short file name the full file name
aFilename:=MsgLine.Filename;
if not FilenameIsAbsolute(aFilename) then begin
if (not FilenameIsAbsolute(aFilename)) then begin
MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory];
if fIncludePathValidForWorkerDir<>MsgWorkerDir then begin
// fetch include path
@ -2218,6 +2284,8 @@ begin
ImproveMsgUnitNotFound(aSynchronized, MsgLine);
ImproveMsgUnitNotUsed(aSynchronized, MsgLine);
ImproveMsgSenderNotUsed(aSynchronized, MsgLine);
end else if MsgLine.SubTool=SubToolFPCLinker then begin
ImproveMsgLinkerUndefinedReference(aSynchronized, MsgLine);
end;
end;
fLastWorkerImprovedMessage[aSynchronized]:=Tool.WorkerMessages.Count-1;

View File

@ -3336,18 +3336,18 @@ end;
procedure TMessagesFrame.ShowIDMenuItemClick(Sender: TObject);
begin
if MsgShowIDMenuItem.Checked then
MessagesCtrl.Options:=MessagesCtrl.Options+[mcoShowMessageID]
if mcoShowMessageID in MessagesCtrl.Options then
MessagesCtrl.Options:=MessagesCtrl.Options-[mcoShowMessageID]
else
MessagesCtrl.Options:=MessagesCtrl.Options-[mcoShowMessageID];
MessagesCtrl.Options:=MessagesCtrl.Options+[mcoShowMessageID];
end;
procedure TMessagesFrame.TranslateMenuItemClick(Sender: TObject);
begin
if MsgTranslateMenuItem.Checked then
MessagesCtrl.Options:=MessagesCtrl.Options+[mcoShowTranslated]
if mcoShowTranslated in MessagesCtrl.Options then
MessagesCtrl.Options:=MessagesCtrl.Options-[mcoShowTranslated]
else
MessagesCtrl.Options:=MessagesCtrl.Options-[mcoShowTranslated];
MessagesCtrl.Options:=MessagesCtrl.Options+[mcoShowTranslated];
end;
procedure TMessagesFrame.UnhideMsgTypeClick(Sender: TObject);
@ -3428,7 +3428,7 @@ end;
procedure TMessagesFrame.HideHintsWithoutPosMenuItemClick(Sender: TObject);
begin
MessagesCtrl.ActiveFilter.HideNotesWithoutPos:=MsgHideHintsWithoutPosMenuItem.Checked;
MessagesCtrl.ActiveFilter.HideNotesWithoutPos:=not MessagesCtrl.ActiveFilter.HideNotesWithoutPos;
end;
procedure TMessagesFrame.HideMsgOfTypeMenuItemClick(Sender: TObject);

View File

@ -98,7 +98,7 @@ type
TQuickFixClassWithAbstractMethods = class(TMsgQuickFix)
public
function IsApplicable(Msg: TMessageLine): boolean;
function IsApplicable(Msg: TMessageLine; out aClassName, aMethodName: string): boolean;
procedure CreateMenuItems(Fixes: TMsgQuickFixes); override;
procedure QuickFix(Fixes: TMsgQuickFixes; Msg: TMessageLine); override;
end;
@ -182,7 +182,7 @@ begin
// Check: Local variable "$1" not used
if not TIDEFPCParser.MsgLineIsId(Msg,5025,Identifier,Dummy) then
exit;
if not IsValidIdent(Identifier) then exit;
if not Msg.HasSourcePosition or not IsValidIdent(Identifier) then exit;
// check if message position is at end of identifier
// (FPC gives position of start or end of identifier)
@ -253,21 +253,13 @@ end;
{ TQuickFixClassWithAbstractMethods }
function TQuickFixClassWithAbstractMethods.IsApplicable(Msg: TMessageLine
): boolean;
var
aClassName: string;
aMethodName: string;
function TQuickFixClassWithAbstractMethods.IsApplicable(Msg: TMessageLine; out
aClassName, aMethodName: string): boolean;
begin
Result:=false;
if (Msg.SubTool<>SubToolFPC)
or (Msg.MsgID<>4046) // Constructing a class "$1" with abstract method "$2"
or (not Msg.HasSourcePosition)
then exit;
if not IDEFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then begin
debugln(['TQuickFixClassWithAbstractMethods.IsApplicable can not extract values: ',Msg.Msg]);
exit;
end;
// Check: Constructing a class "$1" with abstract method "$2"
if not IDEFPCParser.MsgLineIsId(Msg,4046,aClassname,aMethodName) then exit;
if (not Msg.HasSourcePosition) then exit;
Result:=true;
end;
@ -280,8 +272,7 @@ var
begin
if Fixes.LineCount<>1 then exit;
Msg:=Fixes.Lines[0];
if not IsApplicable(Msg) then exit;
if not IDEFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then exit;
if not IsApplicable(Msg,aClassName,aMethodName) then exit;
Fixes.AddMenuItem(Self,Msg,'Show abstract methods of "'+aClassName+'"');
end;
@ -297,11 +288,7 @@ var
NewY: integer;
NewTopLine: integer;
begin
if not IsApplicable(Msg) then exit;
if not IDEFPCParser.GetFPCMsgValues(Msg,aClassName,aMethodName) then begin
debugln(['TQuickFixClassWithAbstractMethods.QuickFix invalid message ',Msg.Msg]);
exit;
end;
if not IsApplicable(Msg,aClassName,aMethodName) then exit;
if not LazarusIDE.BeginCodeTools then begin
DebugLn(['TQuickFixClassWithAbstractMethods failed because IDE busy']);
@ -353,6 +340,7 @@ function TQuickFixUnitNotFound_Remove.IsApplicable(Msg: TMessageLine; out
MissingUnitName, UsedByUnit: string): boolean;
begin
Result:=false;
if Msg=nil then exit;
if (Msg.SubTool<>SubToolFPC)
or (not Msg.HasSourcePosition)
or ((Msg.MsgID<>5023) // Unit "$1" not used in $2
@ -423,14 +411,13 @@ var
CleanPos: integer;
Node: TCodeTreeNode;
Identifier: String;
Dummy: string;
begin
Result:=false;
if (Msg.SubTool<>SubToolFPC)
or (Msg.MsgID<>5000) // identifier not found "$1"
or (not Msg.HasSourcePosition)
then exit;
Identifier:=IDEFPCParser.GetFPCMsgValue1(Msg);
if not IsValidIdent(Identifier) then exit;
// check: identifier not found "$1"
if not IDEFPCParser.MsgLineIsId(Msg,5000,Identifier,Dummy) then
exit;
if not Msg.HasSourcePosition or not IsValidIdent(Identifier) then exit;
// check if message position is at end of identifier
// (FPC gives position of end of identifier)