mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-07 02:58:05 +02:00
IDE: fpc msg parser: darwin linker reference error
git-svn-id: trunk@45383 -
This commit is contained in:
parent
3fb55d6ed6
commit
b0b5163778
@ -68,7 +68,7 @@ type
|
||||
TOnFindDefineProperty = procedure(Sender: TObject;
|
||||
const PersistentClassName, AncestorClassName, Identifier: string;
|
||||
var IsDefined: boolean) of object;
|
||||
TOnFindGDBSource = procedure(Sender: TObject; SrcType: TCodeTreeNodeDesc;
|
||||
TOnFindFPCMangledSource = procedure(Sender: TObject; SrcType: TCodeTreeNodeDesc;
|
||||
const SrcName: string; out SrcFilename: string) of object;
|
||||
|
||||
ECodeToolManagerError = class(Exception);
|
||||
@ -109,6 +109,7 @@ type
|
||||
FOnAfterApplyChanges: TOnAfterApplyCTChanges;
|
||||
FOnBeforeApplyChanges: TOnBeforeApplyCTChanges;
|
||||
FOnCheckAbort: TOnCodeToolCheckAbort;
|
||||
FOnFindFPCMangledSource: TOnFindFPCMangledSource;
|
||||
FOnGatherExternalChanges: TOnGatherExternalChanges;
|
||||
FOnFindDefinePropertyForContext: TOnFindDefinePropertyForContext;
|
||||
FOnFindDefineProperty: TOnFindDefineProperty;
|
||||
@ -832,10 +833,12 @@ type
|
||||
out NewX, NewY, NewTopLine: integer): boolean;
|
||||
|
||||
// gdb stacktraces
|
||||
function FindGBDIdentifier(GDBIdentifier: string; out aComplete: boolean;
|
||||
out aMessage: string; const OnFindSource: TOnFindGDBSource;
|
||||
function FindFPCMangledIdentifier(GDBIdentifier: string; out aComplete: boolean;
|
||||
out aMessage: string; const OnFindSource: TOnFindFPCMangledSource;
|
||||
out NewCode: TCodeBuffer;
|
||||
out NewX, NewY, NewTopLine: integer): boolean;
|
||||
property OnFindFPCMangledSource: TOnFindFPCMangledSource
|
||||
read FOnFindFPCMangledSource write FOnFindFPCMangledSource;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
@ -3830,9 +3833,9 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCodeToolManager.FindGBDIdentifier(GDBIdentifier: string; out
|
||||
function TCodeToolManager.FindFPCMangledIdentifier(GDBIdentifier: string; out
|
||||
aComplete: boolean; out aMessage: string;
|
||||
const OnFindSource: TOnFindGDBSource; out NewCode: TCodeBuffer; out NewX,
|
||||
const OnFindSource: TOnFindFPCMangledSource; out NewCode: TCodeBuffer; out NewX,
|
||||
NewY, NewTopLine: integer): boolean;
|
||||
{ Examples:
|
||||
compiler built-in
|
||||
@ -3904,6 +3907,9 @@ var
|
||||
if Assigned(OnFindSource) then begin
|
||||
OnFindSource(Self,ctnUnit,TheUnitName,aFilename);
|
||||
Result:=aFilename<>'';
|
||||
end else if Assigned(OnFindFPCMangledSource) then begin
|
||||
OnFindFPCMangledSource(Self,ctnUnit,TheUnitName,aFilename);
|
||||
Result:=aFilename<>'';
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -4066,12 +4072,13 @@ begin
|
||||
end;
|
||||
// unknown operator => use only SrcFilename
|
||||
//debugln(['TCodeToolManager.FindGBDIdentifier operator not yet supported: ',dbgstr(p^)]);
|
||||
aMessage:='operator not supported: '+dbgstr(p^);
|
||||
exit;
|
||||
end else begin
|
||||
// example: ??
|
||||
end;
|
||||
|
||||
aMessage:='unkown identifier "'+GDBIdentifier+'"';
|
||||
aMessage:='unknown identifier "'+GDBIdentifier+'"';
|
||||
end;
|
||||
|
||||
function TCodeToolManager.CompleteCode(Code: TCodeBuffer; X,Y,TopLine: integer;
|
||||
|
@ -112,8 +112,6 @@ type
|
||||
function TrcNumberAfter(var Num: Int64; const AfterSub: string): Boolean;
|
||||
function TrcNumberAfter(var Num: Integer; const AfterSub: string): Boolean;
|
||||
function TrcNumFirstAndAfter(var FirstNum, AfterNum: Int64; const AfterSub: string): Boolean;
|
||||
procedure OnFindCTSource(Sender: TObject; SrcType: TCodeTreeNodeDesc;
|
||||
const SrcName: string; out SrcFilename: string);
|
||||
|
||||
procedure ParseTraceLine(s: string; var line: TStackLine);
|
||||
procedure ParseStackTrace(trace: TStackTrace);
|
||||
@ -268,57 +266,6 @@ end;
|
||||
|
||||
{ THeapTrcInfo }
|
||||
|
||||
procedure THeapTrcInfo.OnFindCTSource(Sender: TObject;
|
||||
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
|
||||
var
|
||||
aProject: TLazProject;
|
||||
i: Integer;
|
||||
SrcEdit: TSourceEditorInterface;
|
||||
Code: TCodeBuffer;
|
||||
Tool: TCodeTool;
|
||||
begin
|
||||
case SrcType of
|
||||
ctnProgram:
|
||||
begin
|
||||
// check active project
|
||||
aProject:=LazarusIDE.ActiveProject;
|
||||
if (aProject<>nil) and (aProject.MainFile<>nil) then begin
|
||||
SrcFilename:=aProject.MainFile.Filename;
|
||||
if FilenameIsAbsolute(SrcFilename)
|
||||
and ((SrcName='')
|
||||
or (SysUtils.CompareText(ExtractFileNameOnly(SrcFilename),SrcName)=0))
|
||||
then
|
||||
exit; // found
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// search in source editor
|
||||
for i:=0 to SourceEditorManagerIntf.SourceEditorCount-1 do begin
|
||||
SrcEdit:=SourceEditorManagerIntf.SourceEditors[i];
|
||||
SrcFilename:=SrcEdit.FileName;
|
||||
if CompareText(ExtractFileNameOnly(SrcFileName),SrcName)<>0 then
|
||||
continue;
|
||||
case SrcType of
|
||||
ctnUnit:
|
||||
if not FilenameIsPascalUnit(SrcFileName) then
|
||||
continue;
|
||||
else
|
||||
// a pascal program can have any file name
|
||||
// but we don't want to open program.res or program.txt
|
||||
// => check if source is Pascal
|
||||
// => load source and check if codetools can parse at least one node
|
||||
Code:=CodeToolBoss.LoadFile(SrcFilename,true,false);
|
||||
if Code=nil then continue;
|
||||
CodeToolBoss.Explore(Code,Tool,false,true);
|
||||
if (Tool=nil) or (Tool.Tree.Root=nil) then
|
||||
continue;
|
||||
end;
|
||||
exit; // found
|
||||
end;
|
||||
// not found
|
||||
SrcFilename:='';
|
||||
end;
|
||||
|
||||
function THeapTrcInfo.PosInTrc(const SubStr: string; CaseSensetive: Boolean): Boolean;
|
||||
begin
|
||||
Result := TrcIndex<Trc.Count;
|
||||
@ -549,7 +496,7 @@ procedure THeapTrcInfo.ParseTraceLine(s: string; var line: TStackLine);
|
||||
while (i<=length(s)) and (s[i] in ['a'..'z','A'..'Z','0'..'9','_','$','?']) do
|
||||
inc(i);
|
||||
GDBIdentifier:=copy(s,1,i-1);
|
||||
CodeToolBoss.FindGBDIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource,
|
||||
CodeToolBoss.FindFPCMangledIdentifier(GDBIdentifier,Complete,TheErrorMsg,nil,
|
||||
SrcCode,SrcX,SrcY,SrcTopLine);
|
||||
if SrcCode<>nil then begin
|
||||
line.FileName:=SrcCode.Filename;
|
||||
@ -635,7 +582,7 @@ begin
|
||||
while (i<=length(s)) and (s[i] in ['a'..'z','A'..'Z','0'..'9','_','$','?']) do
|
||||
inc(i);
|
||||
GDBIdentifier:=copy(s,1,i-1);
|
||||
CodeToolBoss.FindGBDIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource,
|
||||
CodeToolBoss.FindFPCMangledIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource,
|
||||
SrcCode,SrcX,SrcY,SrcTopLine);
|
||||
if SrcCode<>nil then begin
|
||||
line.FileName:=SrcCode.Filename;
|
||||
|
@ -147,6 +147,8 @@ type
|
||||
fFileExists: TFilenameToPointerTree;
|
||||
fIncludePath: string; // only valid if fIncludePathValidForWorkerDir=Tool.WorkerDirectory
|
||||
fIncludePathValidForWorkerDir: string;
|
||||
fUnitPath: string; // only valid if fUnitPathValidForWorkerDir=Tool.WorkerDirectory
|
||||
fUnitPathValidForWorkerDir: string;
|
||||
fLastWorkerImprovedMessage: array[TExtToolParserSyncPhase] of integer;
|
||||
fLineToMsgID: TPatternToMsgIDs;
|
||||
fMissingFPCMsgItem: TFPCMsgItem;
|
||||
@ -160,6 +162,8 @@ type
|
||||
fMsgItemThereWereErrorsCompiling: TFPCMsgItem;
|
||||
fMsgItemUnitNotUsed: TFPCMsgItem;
|
||||
fOutputIndex: integer; // current OutputIndex given by ReadLine
|
||||
procedure FetchIncludePath(aPhase: TExtToolParserSyncPhase; MsgWorkerDir: String);
|
||||
procedure FetchUnitPath(aPhase: TExtToolParserSyncPhase; MsgWorkerDir: String);
|
||||
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: ..
|
||||
@ -465,15 +469,21 @@ function GetFPCMsgValue1(const Src, Pattern: string; out Value1: string
|
||||
}
|
||||
var
|
||||
p: SizeInt;
|
||||
l: SizeInt;
|
||||
begin
|
||||
Value1:='';
|
||||
Result:=false;
|
||||
if length(Src)<length(Pattern)-2 then exit;
|
||||
p:=Pos('$1',Pattern);
|
||||
if p<1 then begin
|
||||
Result:=false;
|
||||
Value1:='';
|
||||
end else begin
|
||||
Value1:=copy(Src,p,length(Src)-length(Pattern)+2);
|
||||
Result:=true;
|
||||
end;
|
||||
if p<1 then exit;
|
||||
// check start pattern
|
||||
if (p>1) and (not CompareMem(Pointer(Src),Pointer(Pattern),p-1)) then exit;
|
||||
// check end pattern
|
||||
l:=length(Pattern)-p-2;
|
||||
if (l>0)
|
||||
and (not CompareMem(Pointer(Src)+length(Src)-l,Pointer(Pattern)+p+2,l)) then exit;
|
||||
Value1:=copy(Src,p,length(Src)-length(Pattern)+2);
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function GetFPCMsgValues(Src, Pattern: string; out Value1, Value2: string
|
||||
@ -1083,6 +1093,10 @@ begin
|
||||
fIncludePathValidForWorkerDir:=Tool.WorkerDirectory;
|
||||
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
|
||||
ChompPathDelim(fIncludePathValidForWorkerDir));
|
||||
// get include search path
|
||||
fUnitPathValidForWorkerDir:=Tool.WorkerDirectory;
|
||||
fUnitPath:=CodeToolBoss.GetUnitPathForDirectory(
|
||||
ChompPathDelim(fUnitPathValidForWorkerDir));
|
||||
end;
|
||||
|
||||
procedure TIDEFPCParser.InitReading;
|
||||
@ -1883,7 +1897,7 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
|
||||
/path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA'
|
||||
}
|
||||
|
||||
function CheckForLDFileAndLineNumber: boolean;
|
||||
function CheckForLinuxLDFileAndLineNumber: boolean;
|
||||
var
|
||||
p: PChar;
|
||||
Msg: String;
|
||||
@ -1925,16 +1939,52 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
|
||||
|
||||
Result:=true;
|
||||
MsgLine.Msg:=copy(Msg,p-PChar(Msg)+1,length(Msg));
|
||||
MsgLine.Filename:=aFilename;
|
||||
MsgLine.Line:=LineNumber;
|
||||
MsgLine.Column:=1;
|
||||
MsgLine.SetSourcePosition(aFilename,LineNumber,1);
|
||||
MsgLine.Urgency:=mluError;
|
||||
end;
|
||||
|
||||
function CheckForDarwinLDReferencedFrom: boolean;
|
||||
{ For example:
|
||||
"_UNIT1_GIBTESNICHT", referenced from:
|
||||
}
|
||||
var
|
||||
MangledName: string;
|
||||
aComplete: boolean;
|
||||
aErrorMsg: string;
|
||||
NewCode: TCodeBuffer;
|
||||
NewX: integer;
|
||||
NewY: integer;
|
||||
NewTopLine: integer;
|
||||
begin
|
||||
Result:=false;
|
||||
if MsgLine.HasSourcePosition then exit;
|
||||
// check for ' "_FPC-Mangled-Identifier", referenced from:
|
||||
if not etFPCMsgParser.GetFPCMsgValue1(MsgLine.Msg,' "_$1", referenced from:',
|
||||
MangledName)
|
||||
then exit;
|
||||
Result:=true;
|
||||
case aPhase of
|
||||
etpspAfterReadLine:
|
||||
begin
|
||||
NeedSynchronize:=true;
|
||||
exit;
|
||||
end;
|
||||
etpspAfterSync: exit;
|
||||
end;
|
||||
// in main threads
|
||||
CodeToolBoss.FindFPCMangledIdentifier(MangledName,aComplete,aErrorMsg,
|
||||
nil,NewCode,NewX,NewY,NewTopLine);
|
||||
if NewCode=nil then exit;
|
||||
Result:=true;
|
||||
MsgLine.SetSourcePosition(NewCode.Filename,NewY,NewX);
|
||||
MsgLine.Urgency:=mluError;
|
||||
end;
|
||||
|
||||
begin
|
||||
if MsgLine.SubTool<>SubToolFPCLinker then exit;
|
||||
|
||||
if CheckForLDFileAndLineNumber then exit;
|
||||
if CheckForLinuxLDFileAndLineNumber then exit;
|
||||
if CheckForDarwinLDReferencedFrom then exit;
|
||||
end;
|
||||
|
||||
procedure TIDEFPCParser.ImproveMsgIdentifierPosition(
|
||||
@ -2077,6 +2127,48 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TIDEFPCParser.FetchIncludePath(aPhase: TExtToolParserSyncPhase;
|
||||
MsgWorkerDir: String);
|
||||
begin
|
||||
if MsgWorkerDir='' then
|
||||
MsgWorkerDir:=Tool.WorkerDirectory;
|
||||
if fIncludePathValidForWorkerDir<>MsgWorkerDir then begin
|
||||
// fetch include path from IDE
|
||||
case aPhase of
|
||||
etpspAfterReadLine:
|
||||
NeedSynchronize:=true;
|
||||
etpspSynchronized:
|
||||
begin
|
||||
fIncludePathValidForWorkerDir:=MsgWorkerDir;
|
||||
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
|
||||
ChompPathDelim(MsgWorkerDir));
|
||||
NeedAfterSync:=true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TIDEFPCParser.FetchUnitPath(aPhase: TExtToolParserSyncPhase;
|
||||
MsgWorkerDir: String);
|
||||
begin
|
||||
if MsgWorkerDir='' then
|
||||
MsgWorkerDir:=Tool.WorkerDirectory;
|
||||
if fUnitPathValidForWorkerDir<>MsgWorkerDir then begin
|
||||
// fetch unit path from IDE
|
||||
case aPhase of
|
||||
etpspAfterReadLine:
|
||||
NeedSynchronize:=true;
|
||||
etpspSynchronized:
|
||||
begin
|
||||
fUnitPathValidForWorkerDir:=MsgWorkerDir;
|
||||
fUnitPath:=CodeToolBoss.GetUnitPathForDirectory(
|
||||
ChompPathDelim(MsgWorkerDir));
|
||||
NeedAfterSync:=true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TIDEFPCParser.CheckForMsgId(p: PChar): boolean;
|
||||
var
|
||||
MsgItem: TFPCMsgItem;
|
||||
@ -2426,20 +2518,7 @@ begin
|
||||
if (not FilenameIsAbsolute(aFilename)) then begin
|
||||
// short file name => 2. try include path
|
||||
MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory];
|
||||
if fIncludePathValidForWorkerDir<>MsgWorkerDir then begin
|
||||
// fetch include path from IDE
|
||||
case aPhase of
|
||||
etpspAfterReadLine:
|
||||
NeedSynchronize:=true;
|
||||
etpspSynchronized:
|
||||
begin
|
||||
fIncludePathValidForWorkerDir:=MsgWorkerDir;
|
||||
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
|
||||
ChompPathDelim(MsgWorkerDir));
|
||||
NeedAfterSync:=true;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
FetchIncludePath(aPhase,MsgWorkerDir);
|
||||
if (aPhase in [etpspAfterReadLine,etpspAfterSync])
|
||||
and (fIncludePathValidForWorkerDir=MsgWorkerDir) then begin
|
||||
// include path is valid and in worker thread
|
||||
|
57
ide/main.pp
57
ide/main.pp
@ -71,8 +71,8 @@ uses
|
||||
HelpIntfs, Graphics, ExtCtrls, Dialogs, InterfaceBase, UTF8Process, LazLogger,
|
||||
lazutf8classes, LazFileCache,
|
||||
// codetools
|
||||
FileProcs, FindDeclarationTool, LinkScanner, BasicCodeTools,
|
||||
CodeToolsStructs, CodeToolManager, CodeCache, DefineTemplates, KeywordFuncLists,
|
||||
FileProcs, FindDeclarationTool, LinkScanner, BasicCodeTools, CodeToolsStructs,
|
||||
CodeToolManager, CodeCache, DefineTemplates, KeywordFuncLists, CodeTree,
|
||||
// synedit
|
||||
AllSynEdit, SynEditKeyCmds, SynBeautifier, SynEditMarks,
|
||||
// IDE interface
|
||||
@ -621,6 +621,9 @@ type
|
||||
var CodeBuffers: TFPList; // stopping when CodeBuffers=nil
|
||||
var ExpandedFilenames: TStrings
|
||||
);
|
||||
procedure CodeToolBossFindFPCMangledSource(Sender: TObject;
|
||||
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
|
||||
|
||||
function CTMacroFunctionProject(Data: Pointer): boolean;
|
||||
procedure OnCompilerParseStampIncreased;
|
||||
procedure CodeToolBossScannerInit(Self: TCodeToolManager;
|
||||
@ -1991,6 +1994,55 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainIDE.CodeToolBossFindFPCMangledSource(Sender: TObject;
|
||||
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
|
||||
var
|
||||
i: Integer;
|
||||
SrcEdit: TSourceEditorInterface;
|
||||
Code: TCodeBuffer;
|
||||
Tool: TCodeTool;
|
||||
begin
|
||||
case SrcType of
|
||||
ctnProgram:
|
||||
begin
|
||||
// check active project
|
||||
if (Project1<>nil) and (Project1.MainFile<>nil) then begin
|
||||
SrcFilename:=Project1.MainFile.Filename;
|
||||
if FilenameIsAbsolute(SrcFilename)
|
||||
and ((SrcName='')
|
||||
or (SysUtils.CompareText(ExtractFileNameOnly(SrcFilename),SrcName)=0))
|
||||
then
|
||||
exit; // found
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// search in source editor
|
||||
for i:=0 to SourceEditorManagerIntf.SourceEditorCount-1 do begin
|
||||
SrcEdit:=SourceEditorManagerIntf.SourceEditors[i];
|
||||
SrcFilename:=SrcEdit.FileName;
|
||||
if CompareText(ExtractFileNameOnly(SrcFileName),SrcName)<>0 then
|
||||
continue;
|
||||
case SrcType of
|
||||
ctnUnit:
|
||||
if not FilenameIsPascalUnit(SrcFileName) then
|
||||
continue;
|
||||
else
|
||||
// a pascal program can have any file name
|
||||
// but we don't want to open program.res or program.txt
|
||||
// => check if source is Pascal
|
||||
// => load source and check if codetools can parse at least one node
|
||||
Code:=CodeToolBoss.LoadFile(SrcFilename,true,false);
|
||||
if Code=nil then continue;
|
||||
CodeToolBoss.Explore(Code,Tool,false,true);
|
||||
if (Tool=nil) or (Tool.Tree.Root=nil) then
|
||||
continue;
|
||||
end;
|
||||
exit; // found
|
||||
end;
|
||||
// not found
|
||||
SrcFilename:='';
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
procedure TMainIDE.MainIDEFormClose(Sender: TObject;
|
||||
var CloseAction: TCloseAction);
|
||||
@ -9310,6 +9362,7 @@ begin
|
||||
OnGetMethodName:=@OnCodeToolBossGetMethodName;
|
||||
OnGetIndenterExamples:=@OnCodeToolBossGetIndenterExamples;
|
||||
OnScannerInit:=@CodeToolBossScannerInit;
|
||||
OnFindFPCMangledSource:=@CodeToolBossFindFPCMangledSource;
|
||||
end;
|
||||
|
||||
CodeToolsOpts.AssignGlobalDefineTemplatesToTree(CodeToolBoss.DefineTree);
|
||||
|
Loading…
Reference in New Issue
Block a user