Still need to research this: [WayBack] I search for way to automatically generate class body from interface definition… – Jacek Laskowski – Google+
–jeroen
Posted by jpluimers on 2019/01/23
Still need to research this: [WayBack] I search for way to automatically generate class body from interface definition… – Jacek Laskowski – Google+
–jeroen
Posted in Conference Topics, Conferences, Delphi, Development, Event, ModelMaker Code Explorer, Software Development | 2 Comments »
Posted by jpluimers on 2019/01/21
Historically, [WayBack] W1036: Variable '%s' might not have been initialized (Delphi) has had a lot of gotchas.
The most important still is that it never show for managed types (strings, interfaces, etc).
Usually W1036 shows for non-managed types, but Dan Hacker has found a new case where it does not in [WayBack] Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been initialized’ if the StringsToDo parameter in DoSomething is defined as a var… – Dan Hacker – Google+
He noticed it in Delphi XE and 10.2 Tokyo.
I tested it with the Win32 compiler in XE8.
This warns:
program W1036;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes;
procedure DoSomething(var StringsToDo: TStringList); // <-------- this line makes the difference
begin
//do nothing
end;
procedure Test;
var
MyStrings : TStringList;
begin
MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
DoSomething(MyStrings);
end;
begin
end.
This does not warn:
program W1036;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.Classes;
procedure DoSomething(StringsToDo: TStringList); // <-------- this line makes the difference
begin
//do nothing
end;
procedure Test;
var
MyStrings : TStringList;
begin
MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
DoSomething(MyStrings);
end;
begin
end.
initially, I misread his report and reacted wrongly on the cause (but rightly on the suggested use case of var and of TStringList):
Because a var parameter means that the caller should pass in an initialised parameter. Otherwise it should be an
outparameter, not avarparameter.
varparameter for reference types likeTStrings(only pass asTStringListif it deliberately is not compatible withTStrings) is a risky thing anyway, because the called method can overwrite it and then the caller has to notice the change, then decide what to do with the previous value (likely free it).
I later correct myself:
Looking better, I think it is a compiler issue.
The only difference between nothing and var is the loading of the parameter as a pointer:
with
var//W1036.dpr.16: MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
//004CD924 8B45FC mov eax,[ebp-$04]
//004CD927 E8B8A6F3FF call TObject.Free
//Project1.dpr.17: DoSomething(MyStrings);
//004CD92C 8D45FC lea eax,[ebp-$04]
//004CD92F E8E0FFFFFF call DoSomethingwithout
var//W1036.dpr.16: MyStrings.Free; {W1036 warning if StringsToDo param is NOT var}
//004CD924 8B45FC mov eax,[ebp-$04]
//004CD927 E8B8A6F3FF call TObject.Free
//Project1.dpr.17: DoSomething(MyStrings);
//004CD92C 8B45FC mov eax,[ebp-$04]
//004CD92F E8E0FFFFFF call DoSomething
So:
var, a pointer to the instance of MyStrings (obtained by a lea instruction) gets pushed on the stackvar, the instance of MyStrings (obtained by a mov instruction) gets pushed on the stack.For the difference metween mov and lea, and the use of [] brackets, see:
Given the following
code:L1 db "word", 0
mov al, [L1]
mov eax, L1What do the brackets ([L1]) represent?
–jeroen
Source: Why don’t I get the warning W1036 Variable “‘MyStrings’ might not have been i…
Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 3 Comments »
Posted by jpluimers on 2019/01/01
The biggest lie I tell myself is “I don’t need to write that down, I’ll remember it”
It’s likely older, but the oldest reference I could find was 2012 [WayBack].
So before I forget:
Happy New Year everyone!
With the above quote, it is no coincidence I started my blog even earlier (in 2009): it’s my off-line memory, way better readable than my hand-writing and indexed by various search engines.
Posted in About, Conference Topics, Conferences, Event, LifeHacker, Personal, Power User | Leave a Comment »
Posted by jpluimers on 2018/12/20
The Delphi IDE manages the .dpr and .dproj files for, trying to keep them in sync.
Some information is duplicated between the two, especially files referenced by relative paths: those files are contained in your project.
This means you cannot do something like this in your .dpr file:
{$IFDEF DEBUG}
Debug in '..\..\..\..\Shared\Debug.pas';
{$ELSE}
Debug in '..\Debug.pas'
{$ENDIF}
There is no equivalent for this in the .dproj and it will confuse the IDE which file now actually is or is not inside your project.
Better to leave the file outside of your project, then modify the RELEASE/DEBUG search paths to have the correct one.
Even better is to have just one Debug.pas file containing the changes.
–jeroen
Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »
Posted by jpluimers on 2018/12/18
I just saw this code in the Delphi RTL enabled for RELEASE builds of the procedure TThreadPool.TQueueWorkerThread.Execute; code:
{$IFDEF MSWINDOWS} OutputDebugString(PChar(Format('Thread Exiting: %d', [ThreadId]))); {$ENDIF}
Never, ever do this.
If you code review code that contains it: ensure it has some kind of compile time DEBUG conditional around it.
–jeroen
Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 12 Comments »
Posted by jpluimers on 2018/11/22
The first messages on G+ saw about Delphi 10.3 Rio are these:

“I would have preferred to have the plugins ready at the same time Rio shipped, but shipping Rio itself took precedence.” – if you would have done that you would have seen for yourself where it still has some glitches and what is problematic for third party plugin developers before the release, but hey…
[WayBack] Are these menus removed in 10.3 Rio? “The context menus for the code editor tabs and files in the Project Manager now have a “Show In Explorer” menu it… – Zhan Wang – Google+
+Ralf Stocker On the contrary. Inline variables reduce scope, make code more readable and remove a whole range of potential bugs.
You can make fine mess out of your code with or without inline variables. And if you do it will not be their fault but yours.
+Darian Miller So we should never get any new features because existing tutorials will be broken and we will have to learn something new?
If you are confused by reading code with inline variables more than five minutes after you have learned about existence of that feature, maybe you are in the wrong profession.
And no, reducing scope is not code smell. You cannot always refactor into another method. Small methods are good, but they must have some logical organization.
Too much granulation can be equally bad as too less granulation.
+Darian Miller First of all, you don’t have to use inline variables if you don’t like them. Cost of readability, departure from historical context/documentation, lack of backward compatibility will equal to zero. Even the tooling will not be broken if you don’t use it (unless, of course you don’t write tools)
Some benefits, there are too many to write them all:
You cannot forget to initialize variable before use
procedure Test1;
begin
var sl := TStringList.Create;
try
finally
sl.Free;
end;
end;
You cannot use variable that belongs to wrong scope and might be uninitialized – this code will not compile
procedure Test2;
begin
try
var sl := TStringList.Create;
finally
sl.Free;
end;
end;
5. Type inference – repeating type two times, especially with generics makes code harder to read because while you are skipping reading redundant information, you may skip important one.
This is just the tip of the iceberg. Inline variables are without a doubt extremely valuable feature.
Coding will be a lot simpler as Dalija explained. Here an example using generics:
TYourType = TDictionary<String, Cardinal>;
TYourClass = class
fSomeDic : TYourType
public
procedure DoSomething;
end;
implementation
procedure TYourClass.DoSomething;
begin
for var lItem in fSomeDic do
litem.Value := 10;
end;
As you see this is very easy to read. And litem belongs to the for loop. It doesn’t exists outside. Any reference to it will raise an error.
If you need to change your base type to
TYoutype = TDictionary<string, uint64>;
There’s nothing else to change. No need to hunt every tpair<K,V> declaration.
You have the tools, use it at you see fit!
program Test_C2527;
{$APPTYPE CONSOLE}
uses
Generics.Collections;
type
TData = record
Z: Integer;
end;
var
Q: TThreadedQueue;
begin
end.
program Project3;
{$APPTYPE CONSOLE}
uses
Generics.Collections,
Types;
type
TDateAndRawData = record
Values : PDouble; // pointer to the data 'array'
end;
TDataQueue = TThreadedQueue<TDateAndRawData>;
begin
end.
So lets take a look at which suggestions made the cut for 10.3 – referencing my original post.
Feature Implemented Comments … No Type Inference Yes! For inline variables only, Confuses code insight! Inline variable declaration, with type inference and block scope Yes, Yes and Yes! Confuses code insight! Loop variable inline declaration Yes! Confuses code insight! … No
Related:
I think I will wait a while before installing until more positive messages are being published.
If you do want to try, the hashes of delphicbuilder10_3_0_94364.iso are these:
crc32 157b6e36 md5 0882d58cb53a7d0a828cc45d06c6ecd0 sha1 21579b530f781895885923809d9e670b439ebf9d sha256 9213de93c2abdd6a2ee23aa84fc7e63a87d62d0344f0d0f0ee162d0e7dce7c7d
and for the radstudio10_3_0_esd_94364.exe they are:
crc32 033aeb53 md5 b25fab9d5f0724fb1d59ea77deff6702 sha1 289bbf33c90ae43b151af116e1e7c7a5348591e6 sha256 fb9a825ddaf235441ff72c10fbb03d2cf94adb3f037508e69f0978a37dc95773
Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »
Posted by jpluimers on 2018/11/15
My solution in [WayBack] delphi – post-build event with multiple if/copy combinations only execute if first file does not exist – Stack Overflow is an addendum to my 2014 post Delphi prebuild/prelink/postbuild events.
Here we go:
Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development, The Old New Thing, Windows Development | Leave a Comment »
Posted by jpluimers on 2018/11/07
Below are a few interesting things from this thread [WayBack] Any idea why Delphi (At least since Seattle) does this to Dproj filesand… – Tommi Prami – Google+.
It’s likely that the WordPress system deleted parts between angle brackets because it thinks it’s invalid HTML and WordPress is PHP.
Anyhow: maybe by now I’ve found time for creating an XSD for .dproj files in addition to the one I mentioned yesterday for the .groupproj files: Validating a nested XML element with an empty namespace using XSD – Stack Overflow.
Oh and in the mean time for various Delphi versions, there is a (binary, because it uses some commercially licensed parts) [WayBack] Dproj changed or not changed? Normalize it! | The Art of Delphi Programming.
Files and directories I need to research:
In the mean time, QualityPortal indicates that:
Achim Kalwa:
That is a long living bug: https://quality.embarcadero.com/browse/RSP-11308
Still exists in Berlin Update 2.Jeroen Wiert Pluimers
For more than a decade, the IDE rewriting dproj files in different order/indentation/spacing, properties appearing/disappearing in DFM files and writing DFM files despite no changes have driven me even more nuts than I was.Walter Prins
+Jeroen Wiert Pluimers Yes. Given that .dproj is XML I’ve been almost annoyed enough to look at making some kind of pre-checkin script to force sort things to try and avoid the issue. Almost… Edit: Ah, just checked that RSP, which references this: https://github.com/joshkel/RadCli Seems someone has already done it.Lübbe Onken
Did you try tidy_proj +Walter Prins? For me it fails with a “Unicode Encode Error” when I try to write an output file. In my case this is caused by German umlauts in the excluded bpl section descriptions. Changing the umlauts to something low-ascii allows tidy_proj to finish.Walter Prins
+Lübbe Onken No, but I have just done so. Unicode bites again. To fix that error, change line 125 from:print(proj.toxml())
to:
print(proj.toxml().encode(‘utf-8’))
Note: This will likely not display correctly if you allow the output to go to the console but will ensure it is correct if redirected back to file.
Edit: Ha, I was about to go report this issue ad suggest this fix, but I see you’ve already suggested essentially the same fix. ;)
Jeroen Wiert Pluimers’s profile photo
Jeroen Wiert Pluimers
+Walter Prins interesting tool! Do you know of a tool that can downgrade .dproj files so you can use them with older Delphi versions? (the opposite of what the IDE does)?Or someone that has written more than my XSD on .dproj files? My one is so small that’s hardly a real attempt. https://wiert.me/2013/08/31/delphi-first-try-on-an-xsd-for-groupproj-files/
Walter Prins
+Jeroen Wiert Pluimers No, but interesting idea. I suppose you’re probably aware that the JEDI JCL/JVCL takes a somewhat similar (ish) related approach, in that it generates project and package files that are compatible with every desired version of Delphi from minimalist (XML) template files. Every so often I think it might be worth looking whether one can re-use the code from there easily but haven’t gotten around to it. Always something else to do first. :/Jeroen Wiert Pluimers
+Walter Prins no I didn’t. Where should I start reading on that minimalist template approach?Walter Prins
+Jeroen Wiert Pluimers Sorry I see I missed out the word installer in my comment: It’s the Jedi JCL/JVCL installers that uses xml templates etc.But the point stands: I guess it should be (perhaps) possible to reuse its infrastructure for ones own projects, though as I say I keep meaning to look into this but haven’t really done so.
(BTW I’m assuming you are familiar with the JCL/JVCL and in in particular their installers that bootstrap from source code? If not then perhaps my comments may not be that useful?)
Anyway, not sure if or where there’s particular documentation about this (kind of doubt it), but if you have the JCL/JVCL installed somewhere, then first of all have a look at the “xml” folders e.g. “<jclroot>\jcl\packages\xmls” and “<jvclroot>\jvcl\packages\xml”.
These files appear to define projects and packages in a seemingly abstract/somewhat minimal way using XML. This seemingly is then used to automatically produce .dproj and .dpk files which are placed in e.g. “<jclroot>\jcl\packages\dXX” and “<jvclroot>\jvcl\packages\dXX” where dXX corresponds to a folder for each of the supported Delphi versions and compiled/used during installation.
Having just looked into this briefly a bit further as a result of this conversation: Key units here (in the case of JVCL) seems to be “<jvclroot>\devtools\PackagesGenerator\PackageGenerator.pas”, “<jvclroot>\install\JVCLInstall\PackageUtils.pas” and “<jvclroot>\devtools\common\PackageInformation.pas” (used predictably by <jvclroot>\JVCLInstall.dproj)
(Additionally, having looked at this a bit more closely, it also appears that the JCL does not actually replace all or even most of its .dproj and .dpk files after all, but ships version specific .dproj and .dpk files in most cases, though the JVCL does appear to mostly do so. )
Edit: The JCL also has this interesting sounding unit “jclroot>\source\windows\JclMsBuild.pas” which appears to be an MSBuild project file parser…
–jeroen
Posted in Conference Topics, Conferences, Continuous Integration, Delphi, Development, Event, msbuild, Software Development, XML, XML/XSD, XSD | Leave a Comment »
Posted by jpluimers on 2018/10/31
Answering [WayBack] delphi – post-build event with multiple if/copy combinations only execute if first file does not exist – Stack Overflow made me do a quick search for parentheses handling in batch files. TL;DR: it is a mess.
But it reveals some interesting links:
–jeroen
Posted in Batch-Files, Conference Topics, Conferences, Development, Event, Scripting, Software Development, Windows Development | Leave a Comment »
Posted by jpluimers on 2018/10/09
Blast from the past, but still relevant, this article by Peter Below:
This article follows the path of a keystroke message through the VCL. You will learn how the key processing is implemented, how the OnKey events work and what intervention points for the programmer can be found in the whole process. In addition, things like message processing are explained, and you will learn how to trace messages in the debugger from the message loop to their eventual destination.
Source: [WayBack] A Key’s Odyssey
Via: [WayBack] Vcl.Controls.pasprocedure TWinControl.CNKeyDown(var Message: TWMKeyDown);..if IsMenuKey(Message) then Exit; … – Attila Kovacs – Google+
-jeroen
Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »