CoMPi74 3 Posted June 25, 2021 Hi there, I am looking for some kind of plugin which allows to catch and filter out build / output messages for selected group of files (let say, I have a project with hundreds of units but I just want to see messages for a few units I am assigned to). Is there such a tool? Or any suggestion how to develop such a tool? Thanks in advance Piotr Share this post Link to post
Lars Fosdal 1792 Posted June 25, 2021 When you say messages - do you mean hints and warnings? (IMO, Hints and warnings are bugs waiting to happen and needs to be fixed on sight) 2 Share this post Link to post
CoMPi74 3 Posted June 25, 2021 9 minutes ago, Lars Fosdal said: When you say messages - do you mean hints and warnings? (IMO, Hints and warnings are bugs waiting to happen and needs to be fixed on sight) Yes, exactly. And I have to say, I fully agree with above claim :) That is my main reason I am looking for such a tool. Any suggestions? Share this post Link to post
Lars Fosdal 1792 Posted June 25, 2021 Not that I know of. I am on my team like a hawk to have them clean up code that generates hints and warnings before they commit, so usually what I see is mine. But - it could be useful. Perhaps @dummzeuch has something up his sleeve? Share this post Link to post
Guest Posted June 25, 2021 I would suggest to try the following https://www.davidghoyle.co.uk/WordPress/?page_id=1449 Also read the companion blogposts about the above https://www.davidghoyle.co.uk/WordPress/?s=Notify+Me+of+Everything I didn't try it but if that is not catching your needed messages, then you need to install hooks in the IDE, but this is different story, try the above first. Share this post Link to post
CoMPi74 3 Posted June 25, 2021 @Kas Ob. I did not realize there is such a great web page :) I will definitely read it. Thank you. Share this post Link to post
CoMPi74 3 Posted June 25, 2021 @Lars Fosdal Such a skill is both a gift and a curse 😉 I know something about it 😉 Coming back to the matter, as you mentioned, I also hope that @dummzeuch will be able to help. Or @Uwe Raabe or @David Millington? Share this post Link to post
dummzeuch 1505 Posted June 25, 2021 37 minutes ago, Lars Fosdal said: Perhaps @dummzeuch has something up his sleeve? I've got something called msbuildfilter as part of my buildtools, But It solves a different problem even though it does parse the msbuild output. It's not open source and I can't easily make it. So it's not possible to simply adapt it to this purpose So, no, nothing readily available up my sleeve. 😉 Share this post Link to post
Lars Fosdal 1792 Posted June 25, 2021 Just jotting down what my brain generates - what if... - Each hint warning could display the last git username that touched the file - If the file is changed but not committed, it would be your name - A filter could be added to highlight messages for specific username(s) and/or unit names - or hide messages not matching the filter Share this post Link to post
Uwe Raabe 2057 Posted June 25, 2021 AFAIK, there is currently no mechanism to intercept the message display via OTAPI. Share this post Link to post
CoMPi74 3 Posted June 25, 2021 It's all a song of the future :) I was thinking about a much simpler tool. Because I know best what files interest me, at least initially, I assume that the filtering will be based on a selected list of files (e.g. read from a text file). Share this post Link to post
CoMPi74 3 Posted June 25, 2021 (edited) @Uwe Raabe That's not very good news 😕 Edited June 25, 2021 by CoMPi74 Share this post Link to post
Guest Posted June 25, 2021 Years ago I wrote the "JEDI Uses Wizard" which scanned compiler messages to "catch" unresolved symbol errors and offer adding appropriate units to the uses clause. With no official OpenTools API available, it had to use a hack to retrieve the compiler output from the message window's treeview. The code is very old and perhaps a bit dangerous (although back then it seemed stable) and I have no idea if it still works today (the IDE internals might have changed). See if it helps you: https://github.com/project-jedi/jcl/blob/master/jcl/experts/useswizard/JCLUsesWizard.pas Share this post Link to post
Guest Posted June 25, 2021 30 minutes ago, CoMPi74 said: That's not very good news 😕 Uwe is right there is no direct way to receive these messages. But if you up to do it yourself and learn huge deal of valuable experience, then there is a way, to do that you need to hook one these if not all IOTAMessageServices70.AddCompilerMessage IOTAMessageServices80.AddCompilerMessage and its overloaded version In theory one of these should be your target if not then you want to go after the custom messages, but begin with the AddCompilerMessage, and use https://github.com/MahdiSafsafi/DDetours Share this post Link to post
CoMPi74 3 Posted June 25, 2021 @Ondrej Kelle, @Kas Ob. I'll look at it this weekend. Thanks :) Share this post Link to post
Guest Posted June 25, 2021 @CoMPi74 Sorry, but i think DDetours will not help you there ! So before wasting your time, you should know that i don't think you will get the result, the problem is more complicated and direct hook will not be possible here, still though knowing how to use hooking and reading Dave blog are very valuable knowledge. Share this post Link to post
Der schöne Günther 316 Posted June 25, 2021 I had the same use case a few months ago, and I was glad to find out that you can at least easily select, copy & paste the compiler output as text lines. Writing yourself a tool that filters the output (for example, by unit or severity) should be trivial. The extra step to select, copy & paste might be annoying, but better than nothing. Share this post Link to post
dummzeuch 1505 Posted June 25, 2021 8 hours ago, Ondrej Kelle said: Years ago I wrote the "JEDI Uses Wizard" which scanned compiler messages to "catch" unresolved symbol errors and offer adding appropriate units to the uses clause. With no official OpenTools API available, it had to use a hack to retrieve the compiler output from the message window's treeview. Which Delphi version was that for? My guess would be Delphi 7 or earlier, because later versions use a VirtualTreeview and I found no way to get at its contents. Share this post Link to post
Guest Posted June 25, 2021 I believe that there is few points to attack here, for now i found one (ugly one) that exists on compiler message chain. Will try to hook it after checking it existence in multiple IDE's, but can't go further than Seattle, will try this evening, hoping to not lose the interest due to boredom. Share this post Link to post
Guest Posted June 25, 2021 Here working code, at least for few IDE's i tested with. unit CaptureCompilerOutput; interface uses SysUtils, Windows, ToolsAPI, DDetours, VCL.Dialogs; implementation const {$IFDEF VER210} // Delphi 2010 CoreIDEPackage = 'CoreIde140.bpl'; HProcName = '@Msglines@TCompilerMsgLine@$bctr$qqr17Compintf@TMsgKindix20System@UnicodeStringiit3t3ox54System@%DelphiInterface$t26Msglinesintf@IMessageGroup%'; {$ENDIF} {$IFDEF VER260} // Delphi XE5 CoreIDEPackage = 'CoreIde190.bpl'; HProcName = '@Msglines@TCompilerMsgLine@$bctr$qqr17Compintf@TMsgKindix20System@UnicodeStringiit3t3ox54System@%DelphiInterface$t26Msglinesintf@IMessageGroup%'; {$ENDIF} {$IFDEF VER290} // Delphi XE8 CoreIDEPackage = 'CoreIde220.bpl'; HProcName = '@Msglines@TCompilerMsgLine@$bctr$qqr17Compintf@TMsgKindix20System@UnicodeStringiit3t3ox53System@%DelphiInterface$26Msglinesintf@IMessageGroup%'; {$ENDIF} {$IFDEF VER300} // Delphi 10 (Seattle) CoreIDEPackage = 'CoreIde230.bpl'; HProcName = '@Msglines@TCompilerMsgLine@$bctr$qqr17Compintf@TMsgKindix20System@UnicodeStringiit3t3ox53System@%DelphiInterface$26Msglinesintf@IMessageGroup%'; {$ENDIF} type THookedCM = function(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11: Pointer): Pointer; TCompilerMsgType = (cmkHint, cmkWarn, cmkError, cmkFatal, cmkInfo); var HandleCoreIDEBpl: THandle; FCompilerMsgLineProc: Pointer; TrampolineProc: THookedCM; procedure CompilerMessage(const Source, Msg, FileName: string; MsgKind: TCompilerMsgType); begin // put your code here if MsgKind <> cmkInfo then begin ShowMessage('1 -> ' + Source + #13#10 + '2 -> ' + Msg + #13#10 + '3 -> ' + FileName + #13#10 + '4 -> ' + IntToStr(Ord(MsgKind))); end; end; function HookedProc(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11: Pointer): Pointer; begin CompilerMessage(PChar(P9), PChar(P8), PChar(P5), TCompilerMsgType(P3)); Result := TrampolineProc(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11); end; procedure HookCompilerMessages; begin HandleCoreIDEBpl := GetModuleHandle(CoreIDEPackage); FCompilerMsgLineProc := GetProcAddress(HandleCoreIDEBpl, HProcName); if FCompilerMsgLineProc = nil then ShowMessage('The function address couldn''t be found, Check package and function name.') else TrampolineProc := InterceptCreate(FCompilerMsgLineProc, @HookedProc); end; procedure UnHookCompilerMessages; begin InterceptRemove(@TrampolineProc); end; initialization HookCompilerMessages; finalization UnHookCompilerMessages; end. The two consts belongs to the running IDE, Delphi 2010 and XE5 did has different declaration for that function, XE8 and 10 did has the same export name for that function, so there is a chance later versions did not change it, As how to obtain it? It is declared in the CoreIdeXX.bpl as export, so easy to find and add. Also the TCompilerMsgType is same as TOTAMessageKind in ToolsAPI.pas, but i can be 100% sure so i declared it, for me it looks accurate. The three text strings from the compiler will be isolated along with the kind in CompilerMessage. Share this post Link to post
Guest Posted June 26, 2021 17 hours ago, dummzeuch said: Which Delphi version was that for? My guess would be Delphi 7 or earlier, because later versions use a VirtualTreeview and I found no way to get at its contents. From the comment about TLine from coreide60.bpl, it might have been Delphi 6. Sorry if it's no longer applicable. Share this post Link to post
Guest Posted June 26, 2021 Refined version with source line number. unit CaptureCompilerOutput; interface uses SysUtils, Windows, ToolsAPI, DDetours{, VCL.Dialogs}; implementation const HPROC_NAME_OLD = '@Msglines@TCompilerMsgLine@$bctr$qqr17Compintf@TMsgKindix20System@UnicodeStringiit3t3ox54System@%DelphiInterface$t26Msglinesintf@IMessageGroup%'; HPROC_NAME_NEWER = '@Msglines@TCompilerMsgLine@$bctr$qqr17Compintf@TMsgKindix20System@UnicodeStringiit3t3ox53System@%DelphiInterface$26Msglinesintf@IMessageGroup%'; {$IFDEF VER200} // Delphi 2009 COREIDEPACKAGE = 'CoreIde120.bpl'; HPROCNAME = HPROC_NAME_OLD; {$ENDIF} {$IFDEF VER210} // Delphi 2010 COREIDEPACKAGE = 'CoreIde140.bpl'; HPROCNAME = HPROC_NAME_OLD; {$ENDIF} {$IFDEF VER260} // Delphi Xe5 COREIDEPACKAGE = 'CoreIde190.bpl'; HPROCNAME = HPROC_NAME_OLD; {$ENDIF} {$IFDEF VER290} // Delphi Xe8 COREIDEPACKAGE = 'CoreIde220.bpl'; HPROCNAME = HPROC_NAME_NEWER; {$ENDIF} {$IFDEF VER300} // Delphi 10 (Seattle) COREIDEPACKAGE = 'CoreIde230.bpl'; HPROCNAME = HPROC_NAME_NEWER; {$ENDIF} type THookedCM = function(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11: Pointer): Pointer; TCompilerMsgType = (cmkHint, cmkWarn, cmkError, cmkFatal, cmkInfo); var HandleCoreIDEBpl: THandle; FCompilerMsgLineProc: Pointer; TrampolineProc: THookedCM; function CompilerMTypeToStr(Cmt: TCompilerMsgType): string; begin case Cmt of cmkHint: Result := 'Hint'; cmkWarn: Result := 'Warning'; cmkError: Result := 'Error'; cmkFatal: Result := 'Fatal'; cmkInfo: Result := 'Info'; else Result := 'Uknown'; end; end; // Returning false will prevent this message form being added to IDE's Message Window function CompilerMessage(const From, Msg, SourceFile: string; SourceLine: Integer; MsgKind: TCompilerMsgType): Boolean; begin {if MsgKind <> cmkInfo then begin ShowMessage('From -> ' + From + #13#10 + 'Message -> ' + Msg + #13#10 + 'SourceFile -> ' + SourceFile + #13#10 + 'SourceLine -> ' + IntToStr(SourceLine) + #13#10 + 'MessageKind -> ' + CompilerMTypeToStr(MsgKind)); end; } // Returning false will prevent this message form being added to IDE's Message Window Result := True; end; function HookedProc(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11: Pointer): Pointer; begin if CompilerMessage(PChar(P9), PChar(P8), PChar(P5), integer(P6), TCompilerMsgType(P3)) then Result := TrampolineProc(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11) else Result := nil; end; procedure HookCompilerMessages; begin HandleCoreIDEBpl := GetModuleHandle(COREIDEPACKAGE); if HandleCoreIDEBpl = 0 then raise Exception.Create('CompilerMessagesHook : Package ' + COREIDEPACKAGE + ' not found.'); FCompilerMsgLineProc := GetProcAddress(HandleCoreIDEBpl, HPROCNAME); if FCompilerMsgLineProc = nil then raise Exception.Create('CompilerMessagesHook : The following function can''t be located in ' + COREIDEPACKAGE + #13#10 + HPROCNAME); TrampolineProc := InterceptCreate(FCompilerMsgLineProc, @HookedProc); end; procedure UnHookCompilerMessages; begin InterceptRemove(@TrampolineProc); end; initialization HookCompilerMessages; finalization UnHookCompilerMessages; end. Share this post Link to post
CoMPi74 3 Posted July 3, 2021 On 6/25/2021 at 5:05 PM, Der schöne Günther said: I had the same use case a few months ago, and I was glad to find out that you can at least easily select, copy & paste the compiler output as text lines. Writing yourself a tool that filters the output (for example, by unit or severity) should be trivial. The extra step to select, copy & paste might be annoying, but better than nothing. This is the way I am doing it right now. Though, I do not use a "special" tool ;) Instead I use Notepad++. It is enough for small projects but I am going to cleanup a significantly larger project and I need a better tool. Share this post Link to post
Blavatsky 0 Posted March 13, 2022 (edited) On 6/25/2021 at 6:43 PM, Ondrej Kelle said: Years ago I wrote the "JEDI Uses Wizard" which scanned compiler messages to "catch" unresolved symbol errors and offer adding appropriate units to the uses clause. With no official OpenTools API available, it had to use a hack to retrieve the compiler output from the message window's treeview. The code is very old and perhaps a bit dangerous (although back then it seemed stable) and I have no idea if it still works today (the IDE internals might have changed). See if it helps you: https://github.com/project-jedi/jcl/blob/master/jcl/experts/useswizard/JCLUsesWizard.pas Hello Ondrej, Has there been any new work on Jedi Uses WIZARD ? How do you use it exactly ? I tried compiling it (D11 JEDI 2.8 and 3.5) but it mentioned something about first getting a DOC-O-MATIC filename.... What does that entail ? Edited March 13, 2022 by Blavatsky Share this post Link to post
Guest Posted March 13, 2022 8 hours ago, Blavatsky said: Hello Ondrej, Has there been any new work on Jedi Uses WIZARD ? How do you use it exactly ? I tried compiling it (D11 JEDI 2.8 and 3.5) but it mentioned something about first getting a DOC-O-MATIC filename.... What does that entail ? Hi. Sorry, I haven't used it for years now and I have no idea. Share this post Link to post