mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-14 06:59:14 +02:00
IDE: help for fpc messages: using codetools parser
git-svn-id: trunk@35149 -
This commit is contained in:
parent
0055462762
commit
f247b41ce8
@ -71,6 +71,7 @@ type
|
|||||||
Index: integer; // index in list
|
Index: integer; // index in list
|
||||||
function GetName(WithID: boolean = true): string;
|
function GetName(WithID: boolean = true): string;
|
||||||
function PatternFits(aMsg: string): integer; // >=0 fits
|
function PatternFits(aMsg: string): integer; // >=0 fits
|
||||||
|
function GetTrimmedComment(NoLineBreaks, NoLatex: boolean): string;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TFPCMsgFile }
|
{ TFPCMsgFile }
|
||||||
@ -346,6 +347,47 @@ begin
|
|||||||
until false;
|
until false;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TFPCMsgItem.GetTrimmedComment(NoLineBreaks, NoLatex: boolean): string;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
StartPos: Integer;
|
||||||
|
begin
|
||||||
|
Result:=Comment;
|
||||||
|
for i:=length(Result) downto 1 do begin
|
||||||
|
if NoLineBreaks and (Result[i] in [#10,#13]) then
|
||||||
|
Result[i]:=' '
|
||||||
|
else if Result[i]=#9 then
|
||||||
|
Result[i]:=' '
|
||||||
|
else if NoLatex and (Result[i] in ['{','}']) then
|
||||||
|
Result[i]:=' ';
|
||||||
|
if Result[i]=' ' then begin
|
||||||
|
if (i=1) or (i=length(Result)) or (Result[i+1] in [' ',#10,#13]) then
|
||||||
|
system.Delete(Result,i,1);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if NoLatex then begin
|
||||||
|
// remove tags
|
||||||
|
i:=1;
|
||||||
|
while i<length(Result) do begin
|
||||||
|
if Result[i]='/' then begin
|
||||||
|
StartPos:=i;
|
||||||
|
inc(i);
|
||||||
|
if Result[i]='/' then begin
|
||||||
|
// double slash
|
||||||
|
inc(i);
|
||||||
|
end else if Result[i] in ['a'..'z','A'..'Z'] then begin
|
||||||
|
while (i<=length(Result))
|
||||||
|
and (Result[i] in ['a'..'z','A'..'Z','0'..'9','_']) do
|
||||||
|
inc(i);
|
||||||
|
System.Delete(Result,StartPos,i-StartPos);
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TFPCMsgFile }
|
{ TFPCMsgFile }
|
||||||
|
|
||||||
function TFPCMsgFile.GetItems(Index: integer): TFPCMsgItem;
|
function TFPCMsgFile.GetItems(Index: integer): TFPCMsgItem;
|
||||||
|
@ -39,7 +39,7 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, LCLProc, Dialogs, FileUtil, TextTools, MacroIntf,
|
Classes, SysUtils, LCLProc, Dialogs, FileUtil, TextTools, MacroIntf,
|
||||||
LazarusIDEStrConsts, LazConfigStorage, HelpIntfs, IDEHelpIntf, LazHelpIntf,
|
LazarusIDEStrConsts, LazConfigStorage, HelpIntfs, IDEHelpIntf, LazHelpIntf,
|
||||||
LazHelpHTML, CodeToolsFPCMsgs, FileProcs;
|
LazHelpHTML, CodeToolsFPCMsgs, FileProcs, CodeToolManager, CodeCache;
|
||||||
|
|
||||||
const
|
const
|
||||||
lihcFPCMessages = 'FreePascal Compiler messages';
|
lihcFPCMessages = 'FreePascal Compiler messages';
|
||||||
@ -56,7 +56,7 @@ type
|
|||||||
FFoundComment: string;
|
FFoundComment: string;
|
||||||
FLastMessage: string;
|
FLastMessage: string;
|
||||||
FMsgFile: TFPCMsgFile;
|
FMsgFile: TFPCMsgFile;
|
||||||
FMsgFileAge: TCTFileAgeTime;
|
FMsgFileChangeStep: integer;
|
||||||
FMsgFilename: string;
|
FMsgFilename: string;
|
||||||
procedure SetFPCTranslationFile(const AValue: string);
|
procedure SetFPCTranslationFile(const AValue: string);
|
||||||
procedure SetFoundComment(const AValue: string);
|
procedure SetFoundComment(const AValue: string);
|
||||||
@ -78,7 +78,7 @@ type
|
|||||||
property FoundComment: string read FFoundComment write SetFoundComment;
|
property FoundComment: string read FFoundComment write SetFoundComment;
|
||||||
property MsgFile: TFPCMsgFile read FMsgFile;
|
property MsgFile: TFPCMsgFile read FMsgFile;
|
||||||
property MsgFilename: string read FMsgFilename write SetMsgFilename;
|
property MsgFilename: string read FMsgFilename write SetMsgFilename;
|
||||||
property MsgFileAge: TCTFileAgeTime read FMsgFileAge;
|
property MsgFileChangeStep: integer read FMsgFileChangeStep;
|
||||||
published
|
published
|
||||||
property FPCTranslationFile: string read FFPCTranslationFile
|
property FPCTranslationFile: string read FFPCTranslationFile
|
||||||
write SetFPCTranslationFile;
|
write SetFPCTranslationFile;
|
||||||
@ -88,11 +88,6 @@ procedure CreateFPCMessagesHelpDB;
|
|||||||
function AddFPCMessageHelpItem(const Title, URL, RegularExpression: string
|
function AddFPCMessageHelpItem(const Title, URL, RegularExpression: string
|
||||||
): THelpDBIRegExprMessage;
|
): THelpDBIRegExprMessage;
|
||||||
|
|
||||||
function FindFPCMessageComment(const CommentFile, Msg: string;
|
|
||||||
ExtractText: boolean): string;
|
|
||||||
procedure ParseFPCMessagesFile(Lines: TStrings;
|
|
||||||
const SearchMessage: string; var FoundComment: string);
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
procedure CreateFPCMessagesHelpDB;
|
procedure CreateFPCMessagesHelpDB;
|
||||||
@ -130,199 +125,6 @@ begin
|
|||||||
FPCMessagesHelpDB.RegisterItem(Result);
|
FPCMessagesHelpDB.RegisterItem(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function FindFPCMessageComment(const CommentFile, Msg: string;
|
|
||||||
ExtractText: boolean): string;
|
|
||||||
var
|
|
||||||
sl: TStringList;
|
|
||||||
p: Integer;
|
|
||||||
TagStart: LongInt;
|
|
||||||
begin
|
|
||||||
Result:='';
|
|
||||||
sl:=TStringList.Create;
|
|
||||||
try
|
|
||||||
sl.LoadFromFile(UTF8ToSys(CommentFile));
|
|
||||||
ParseFPCMessagesFile(sl,Msg,Result);
|
|
||||||
if ExtractText and (Result<>'') then begin
|
|
||||||
p:=1;
|
|
||||||
while (p<length(Result)) do begin
|
|
||||||
case Result[p] of
|
|
||||||
'\':
|
|
||||||
begin
|
|
||||||
TagStart:=p;
|
|
||||||
inc(p);
|
|
||||||
if (p<=length(Result)) and (Result[p]='\') then begin
|
|
||||||
inc(p);
|
|
||||||
end else begin
|
|
||||||
// remove tag
|
|
||||||
while (p<=length(Result)) and (Result[p] in ['a'..'z','A'..'Z'])
|
|
||||||
do
|
|
||||||
inc(p);
|
|
||||||
Result:=copy(Result,1,TagStart-1)+copy(Result,p,length(Result));
|
|
||||||
p:=TagStart;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
'{','}':
|
|
||||||
begin
|
|
||||||
// remove brackets
|
|
||||||
Result:=copy(Result,1,p-1)+copy(Result,p+1,length(Result));
|
|
||||||
end;
|
|
||||||
else
|
|
||||||
inc(p);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
sl.Free;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ParseFPCMessagesFile(Lines: TStrings;
|
|
||||||
const SearchMessage: string; var FoundComment: string);
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
Line: string;
|
|
||||||
|
|
||||||
procedure Error(const ErrMsg: string);
|
|
||||||
begin
|
|
||||||
raise Exception.Create('Line='+IntToStr(i+1)+': '+ErrMsg+' in "'+Line+'"');
|
|
||||||
end;
|
|
||||||
|
|
||||||
function CompareTextWithSearchMessage(const Command: string;
|
|
||||||
TypeStart, TxtStart: integer): boolean;
|
|
||||||
var
|
|
||||||
RegularExpression: String;
|
|
||||||
p: Integer;
|
|
||||||
begin
|
|
||||||
Result:=false;
|
|
||||||
if TxtStart>length(Command) then exit;
|
|
||||||
if TypeStart>length(Command) then exit;
|
|
||||||
|
|
||||||
RegularExpression:=copy(Command,TxtStart,length(Command));
|
|
||||||
// replace all $d variables with (.*)
|
|
||||||
p:=length(RegularExpression);
|
|
||||||
while (p>0) do begin
|
|
||||||
if (RegularExpression[p]='$') then begin
|
|
||||||
if (p<length(RegularExpression))
|
|
||||||
and (RegularExpression[p+1] in ['1'..'9']) then begin
|
|
||||||
RegularExpression:=copy(RegularExpression,1,p-1)+'(.*)'
|
|
||||||
+copy(RegularExpression,p+2,length(RegularExpression));
|
|
||||||
end else begin
|
|
||||||
RegularExpression:=copy(RegularExpression,1,p-1)+'\'
|
|
||||||
+copy(RegularExpression,p,length(RegularExpression));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
dec(p);
|
|
||||||
end;
|
|
||||||
case Command[TypeStart] of
|
|
||||||
'F': RegularExpression:='Fatal: '+RegularExpression;
|
|
||||||
'E': RegularExpression:='Error: '+RegularExpression;
|
|
||||||
'N': RegularExpression:='Note: '+RegularExpression;
|
|
||||||
'I': RegularExpression:='Info: '+RegularExpression;
|
|
||||||
'H': RegularExpression:='Hint: '+RegularExpression;
|
|
||||||
end;
|
|
||||||
|
|
||||||
try
|
|
||||||
Result:=REMatches(SearchMessage,RegularExpression);
|
|
||||||
except
|
|
||||||
on E: Exception do begin
|
|
||||||
WriteLn('CompareTextWithSearchMessage RegExpr Error ',E.Message,' RegularExpression="'+RegularExpression+'"');
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
// debugging:
|
|
||||||
//if System.Pos('is assigned but never used',Command)>0 then WriteLn('CompareTextWithSearchMessage "',RegularExpression,'" Result=',Result);
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
Command: String;
|
|
||||||
CommandLine: Integer;
|
|
||||||
|
|
||||||
procedure ErrorInCommand(const ErrMsg: string);
|
|
||||||
begin
|
|
||||||
raise Exception.Create('Line='+IntToStr(CommandLine+1)+': '+ErrMsg+' in "'+Command+'"');
|
|
||||||
end;
|
|
||||||
|
|
||||||
var
|
|
||||||
EqualPos: LongInt;
|
|
||||||
Comment: String;
|
|
||||||
BracketLevel: Integer;
|
|
||||||
x: Integer;
|
|
||||||
PartStart: Integer;
|
|
||||||
TypeStart: LongInt;
|
|
||||||
TxtStart: LongInt;
|
|
||||||
begin
|
|
||||||
FoundComment:='';
|
|
||||||
Comment:='';
|
|
||||||
Command:='';
|
|
||||||
CommandLine:=0;
|
|
||||||
BracketLevel:=0;
|
|
||||||
for i:=0 to Lines.Count-1 do begin
|
|
||||||
Line:=Lines[i];
|
|
||||||
if (Trim(Line)='') or (Line[1]='#') then continue;
|
|
||||||
|
|
||||||
// example:
|
|
||||||
// general_t_compilername=01000_T_Compiler: $1
|
|
||||||
// % When the \var{-vt} switch is used, this line tells you what compiler
|
|
||||||
// % is used.
|
|
||||||
if Line[1]='%' then begin
|
|
||||||
if BracketLevel>0 then
|
|
||||||
Error('unclosed bracket in lines before');
|
|
||||||
Comment:=Comment+copy(Line,2,length(Line));
|
|
||||||
end else begin
|
|
||||||
if BracketLevel=0 then begin
|
|
||||||
// end old message
|
|
||||||
if Command<>'' then begin
|
|
||||||
if CompareByte(Command[1],'option_',7)=0 then begin
|
|
||||||
// option
|
|
||||||
end else begin
|
|
||||||
// read '='
|
|
||||||
EqualPos:=System.Pos('=',Command);
|
|
||||||
if EqualPos<1 then ErrorInCommand('missing =');
|
|
||||||
// read number
|
|
||||||
PartStart:=EqualPos+1;
|
|
||||||
TypeStart:=PartStart;
|
|
||||||
while (TypeStart<=length(Command)) and (Command[TypeStart]<>'_') do
|
|
||||||
inc(TypeStart);
|
|
||||||
// read type
|
|
||||||
inc(TypeStart);
|
|
||||||
TxtStart:=TypeStart;
|
|
||||||
while (TxtStart<=length(Command)) and (Command[TxtStart]<>'_') do
|
|
||||||
inc(TxtStart);
|
|
||||||
// read text
|
|
||||||
inc(TxtStart);
|
|
||||||
if SearchMessage<>'' then begin
|
|
||||||
if CompareTextWithSearchMessage(Command,TypeStart,TxtStart) then
|
|
||||||
begin
|
|
||||||
FoundComment:=Trim(Comment);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// start a new message
|
|
||||||
Comment:='';
|
|
||||||
Command:=Line;
|
|
||||||
CommandLine:=i;
|
|
||||||
end else begin
|
|
||||||
// continue command
|
|
||||||
Command:=Command+Line;
|
|
||||||
end;
|
|
||||||
// update BracketLevel
|
|
||||||
for x:=1 to length(Line) do begin
|
|
||||||
case Line[x] of
|
|
||||||
'[': inc(BracketLevel);
|
|
||||||
']':
|
|
||||||
if BracketLevel>0 then
|
|
||||||
dec(BracketLevel)
|
|
||||||
else
|
|
||||||
Error('closing a bracket, which was not opened.');
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TFPCMessagesHelpDatabase }
|
{ TFPCMessagesHelpDatabase }
|
||||||
|
|
||||||
procedure TFPCMessagesHelpDatabase.SetFoundComment(const AValue: string);
|
procedure TFPCMessagesHelpDatabase.SetFoundComment(const AValue: string);
|
||||||
@ -347,7 +149,7 @@ procedure TFPCMessagesHelpDatabase.SetMsgFilename(AValue: string);
|
|||||||
begin
|
begin
|
||||||
if FMsgFilename=AValue then Exit;
|
if FMsgFilename=AValue then Exit;
|
||||||
FMsgFilename:=AValue;
|
FMsgFilename:=AValue;
|
||||||
FMsgFileAge:=-1;
|
FMsgFileChangeStep:=-1;
|
||||||
FreeAndNil(FMsgFile);
|
FreeAndNil(FMsgFile);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -370,6 +172,8 @@ function TFPCMessagesHelpDatabase.GetNodesForMessage(const AMessage: string;
|
|||||||
var ErrMsg: string): TShowHelpResult;
|
var ErrMsg: string): TShowHelpResult;
|
||||||
var
|
var
|
||||||
Filename: String;
|
Filename: String;
|
||||||
|
Code: TCodeBuffer;
|
||||||
|
MsgItem: TFPCMsgItem;
|
||||||
begin
|
begin
|
||||||
Result:=inherited GetNodesForMessage(AMessage, MessageParts, ListOfNodes,
|
Result:=inherited GetNodesForMessage(AMessage, MessageParts, ListOfNodes,
|
||||||
ErrMsg);
|
ErrMsg);
|
||||||
@ -388,26 +192,29 @@ begin
|
|||||||
Filename:=Filename+FPCTranslationFile
|
Filename:=Filename+FPCTranslationFile
|
||||||
else
|
else
|
||||||
Filename:=Filename+'errore.msg';
|
Filename:=Filename+'errore.msg';
|
||||||
if not FileExistsUTF8(Filename) then exit;
|
Code:=CodeToolBoss.LoadFile(Filename,true,false);
|
||||||
|
if Code=nil then exit;
|
||||||
|
|
||||||
// load MsgFile
|
// load MsgFile
|
||||||
if (Filename<>MsgFilename) or (FileAgeCached(Filename)<>MsgFileAge) then begin
|
if (Filename<>MsgFilename) or (Code.ChangeStep<>MsgFileChangeStep) then begin
|
||||||
MsgFilename:=Filename;
|
MsgFilename:=Filename;
|
||||||
if FMsgFile=nil then
|
if FMsgFile=nil then
|
||||||
FMsgFile:=TFPCMsgFile.Create;
|
FMsgFile:=TFPCMsgFile.Create;
|
||||||
FMsgFileAge:=FileAgeCached(MsgFilename);
|
FMsgFileChangeStep:=Code.ChangeStep;
|
||||||
try
|
try
|
||||||
MsgFile.LoadFromFile(MsgFilename);
|
MsgFile.LoadFromText(Code.Source);
|
||||||
except
|
except
|
||||||
on E: Exception do begin
|
on E: Exception do begin
|
||||||
debugln(['TFPCMessagesHelpDatabase failed to load "'+MsgFilename+'": '+E.Message]);
|
debugln(['TFPCMessagesHelpDatabase failed to parse "'+MsgFilename+'": '+E.Message]);
|
||||||
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
if MsgFile=nil then exit;
|
||||||
|
|
||||||
|
MsgItem:=MsgFile.FindWithMessage(AMessage);
|
||||||
|
if MsgItem=nil then exit;
|
||||||
FoundComment:=FindFPCMessageComment(Filename,AMessage,true);
|
FoundComment:=MsgItem.GetTrimmedComment(true,true);
|
||||||
if FoundComment<>'' then begin
|
if FoundComment<>'' then begin
|
||||||
Result:=shrSuccess;
|
Result:=shrSuccess;
|
||||||
CreateNodeQueryListAndAdd(DefaultNode,nil,ListOfNodes,true);
|
CreateNodeQueryListAndAdd(DefaultNode,nil,ListOfNodes,true);
|
||||||
|
Loading…
Reference in New Issue
Block a user