How to reproduce this Code Completion bug? - delphi

I'm having a bug on Delphi XE2 (Update 4 Hotfix 1), which reproduces many times on the legacy project I work (it evolved from D6 to D7,D2006 and finally XE2), but I didn't know how to trigger it in a smaller project.
The latest time, it triggered on creating an event handler for a "hidden popup" on the app. When I click on the menu option to create the Click handler this happens.
pprocedure TMainForm.Blablabla1Click(Sender: TObject);
begin
end;
rocedure TMainForm.FormActivate(Sender: TObject);
You can see that the IDE inserted the new code INSIDE the declaration of the next method... But it's not all.
Almost all times, on the DPR, code gets mangled too:
AApplication.CreateForm(TDM_DataAcc, DM_DataAcc);
AApplication.CreateForm(TMainForm, MainForm);
pplication.CreateForm(Tfrm_login, frm_login);
f frm_Login.CanLogin = mrOK then Application.Run
(It's almost like that, I don't remember if the 3rd Application.CreateForm get its' 'A' clipped or not, the other I'm sure are doubled and the IF gets its' "I" clipped).
Chasing on QualityCentral doesn't help (found nothing). This also happens sometimes on Class Completion(Ctrl-SHift-C).
Someone knows what triggers that bug, so I can create an new application and send it to Embarcadero?

Behavior like that suggests that the IDE is miscounting characters in the file. There are several "file oddities" that the developers might not have anticipated and that could cause a character index to be miscalculated.
Check your file for unusual line endings. For example, a line missing a carriage return will appear correctly in the editor, but can cause incorrect line numbers elsewhere in the program.
Non-breaking spaces are another kind of character that will appear normally, and maybe even parse correctly, but occupies multiple bytes when represented in UTF-8 when the "normal" version of the character (a regular space) only takes up one. You will sometimes acquire such characters if you copy code from a Web browser.
Incorrect byte-order marks for UTF-8 or UTF-16 source files might also cause problems.
Often, opening your source file in Notepad or a hex editor will help you identify these problems.

Related

Delphi - My debugger seems to be out of sync with the source code [duplicate]

Since yesterday, all blue dots (compiled lines) in my source code are shifted with one line up.
So, the first dot starts at 'var' instead of 'begin' and the last dot is one line before the last 'end' of a function.
I deleted all files (starting with DCUs) except DPR, PAS, DFM and DPRJ and recompiled. But the dots are still shifted.
How can I fix this? It makes the step=by-step debugging almost impossible.
It could be that the file is corrupted so that you don't have proper line end combination (#13#10) on one line. Is the "one line up error" throughout the file or does it start somewhere in the middle of the unit?
Beginning with Delphi 2007 (maybe already Delphi 2005) you can check the line ends in your code by enableing checkbox Show line breaks in Tools - Options - Editor options - Source options. The line breaks look like this:
As you can see, a CR on its own is not considered a line break and messes up the synchronization of the executable line dots
Try closing Delphi then deleting all *.identcache files.
I have a batch file at the root of my Delphi projects directory that recursively deletes all identcache files.
Try This:
Open the unit in an editor with capabilities to change codification, like Notepad++.
Code/save the file as ANSI.
Open or recharge the file in the Delphi IDE.
The dots must be in the right place.

Delphi xe8 error reading textfile created from Delphi 7 version and vice versa

I try to convert a code from Delphi 7 to delphi xe8 and I cannot find a solution to the following case.
Our old application creates a txt file which first row is like that
±HEADER―ID°N1799―USER_ID°N1―PATH_NAME―R_DATABASE°TC:\DATA―R_SERVER°TTEST_SRV―R_COMPUTER°TMYPC―
Char(―) is chr(175).
We tried to read the already created file from our new application with Delphi xe8 like that:
StrData := TStringList.Create;
StrData.LoadFromFile(sFile);
StrData.Text returns the desired text but chr(175) is replaced with chr(8213).
In order to go on I did the followings:
StrData.LoadFromFile(sFile,TEncoding.ANSI);
StrData.Text := StringReplace(StrData.Text,Chr(8213),Chr(175),[rfReplaceAll]);
What I cannot solve is the opposite case.
I have to create that file from Delphi xe8 so as it would be exactly the same with the one produced from the old delphi 7 application.
At the beginning I used the same code we had:
StrData.SavetoFile(sFile); //returns text but chr(175) is replaced with (?)
Also i tried all encodings with no results.
StrData.SavetoFile(sFile,Ansi);//returns text but chr(175) is replaced with (?) etc.
The same results also when converts the code to TStreamFile or textfile.
base64 encode files
Old one - Correct one (StrData.SavetoFile(sFile)) //Delphi 7
wrFIRUFERVLigJVJRMKwTjE4NjbigJVSSUTCsE4zNjHigJVDU0lURV9JRMKwTjHigJVSU0lURV9JRMKwTjEwMeKAlVNTSVRFX0lEwrBOMeKAlVRSTl9EQVRFwrBENDIzODIuNjA2NzkzOTgxNeKAlVVTRVJfSUTCsE4x4oCVUEFUSF9OQU1FwrBUXFxkZWxwaGkyMDEycjJcQkVORUZJVF9URVNUXFBBX09GRklDRV9WU0xcVFJBTlNGRVJcRVhQT1JU4oCVRklMRV9OQU1FwrBUQU5BRDM2MU0udHh04oCVRklMRV9UWVBFwrBO4oCVUENLX1NFTkRFUsKwVEFkbWlu4oCVUENLX05PVEVTwrBU4oCVX1JWX0lEMcKwTuKAlVNWX0lEwrBO4oCVUlZfSUTCsE7igJVSREJfSUTCsE4xMeKAlVNEQl9JRMKwTjEx4oCVUENLX0NOWFTCsFQwMywxNSw3MiwwMOKAlUtFWUlEwrBUezczRDIwMDU3LTM3NTgtNDlDMi05NTlGLTA4QzYxMDY4NEZGNn3igJVGTF9UWVBFwrBOMuKAlUZMX1NUQVRVU8KwTjDigJVTVEFSVF9EVMKwRDQyMzgyLjYwNjQ5MzA1NTbigJVSX1NUQVJUX0RUwrBE4oCVUl9FTkRfRFTCsETigJVSX1VTRVLCsFTigJVSX1BBVEjCsFTigJVTSVpFX1BDS8KwTuKAlVNJWkVfREFUQcKwTuKAlVNJWkVfQVRDSMKwTuKAlVNJWkVfRE9DU8KwTuKAlURBVEVfSU7CsETigJVSX0RBVEFCQVNFwrBU4oCVUl9TRVJWRVLCsFTigJVSX0NPTVBVVEVSwrBU4oCV
StrData.SavetoFile(sFile,Tencoding.Ansi); & StrData.SavetoFile(sFile); //XE8
wrFIRUFERVI/SUTCsE4xODY3P1JJRMKwTjM2Mj9DU0lURV9JRMKwTjE/UlNJVEVfSUTCsE4xMDE/U1NJVEVfSUTCsE4xP1RSTl9EQVRFwrBENDIzODIuNzA3NzA4MzMzMz9VU0VSX0lEwrBOMT9QQVRIX05BTUXCsFRcXGRlbHBoaTIwMTJyMlxCRU5FRklUX1RFU1RcUEFfT0ZGSUNFX1ZTTFxUUkFOU0ZFUlxFWFBPUlQ/RklMRV9OQU1FwrBUQU5BRDM2Mk0udHh0P0ZJTEVfVFlQRcKwTj9QQ0tfU0VOREVSwrBUQWRtaW4/UENLX05PVEVTwrBOP19SVl9JRDHCsE4/U1ZfSUTCsE4/UlZfSUTCsE4/UkRCX0lEwrBOMTE/U0RCX0lEwrBOMTE/UENLX0NOWFTCsFQwMywxNSw3MiwwMD9LRVlJRMKwVHtGQzM1N0QyNC1EQjRBLTRBOUMtQkE3My0xQ0FBMEVFRDUzOUJ9P0ZMX1RZUEXCsE4yP0ZMX1NUQVRVU8KwTjA/U1RBUlRfRFTCsEQ0MjM4Mi43MDcyNjg1MTg1P1JfU1RBUlRfRFTCsEQ/Ul9FTkRfRFTCsEQ/Ul9VU0VSwrBUP1JfUEFUSMKwVD9TSVpFX1BDS8KwTj9TSVpFX0RBVEHCsE4/U0laRV9BVENIwrBOP1NJWkVfRE9DU8KwTj9EQVRFX0lOwrBEP1JfREFUQUJBU0XCsFQ/Ul9TRVJWRVLCsFQ/Ul9DT01QVVRFUsKwVD8=
StrData.SavetoFile(sFile,Tencoding.UTF8); //XE8
wrFIRUFERVLCr0lEwrBOMTg3MMKvUklEwrBOMzY1wq9DU0lURV9JRMKwTjHCr1JTSVRFX0lEwrBOMTAxwq9TU0lURV9JRMKwTjHCr1RSTl9EQVRFwrBENDIzODIuNzIyODEyNcKvVVNFUl9JRMKwTjHCr1BBVEhfTkFNRcKwVFxcZGVscGhpMjAxMnIyXEJFTkVGSVRfVEVTVFxQQV9PRkZJQ0VfVlNMXFRSQU5TRkVSXEVYUE9SVMKvRklMRV9OQU1FwrBUQU5BRDM2NU0udHh0wq9GSUxFX1RZUEXCsE7Cr1BDS19TRU5ERVLCsFRBZG1pbsKvUENLX05PVEVTwrBOwq9fUlZfSUQxwrBOwq9TVl9JRMKwTsKvUlZfSUTCsE7Cr1JEQl9JRMKwTjExwq9TREJfSUTCsE4xMcKvUENLX0NOWFTCsFQwMywxNSw3MiwwMMKvS0VZSUTCsFR7ODE5REQ0NDQtQzEwQi00MTY1LUFEQjAtQkI2NDAyRjA3NUI4fcKvRkxfVFlQRcKwTjLCr0ZMX1NUQVRVU8KwTjDCr1NUQVJUX0RUwrBENDIzODIuNzIyNTIzMTQ4McKvUl9TVEFSVF9EVMKwRMKvUl9FTkRfRFTCsETCr1JfVVNFUsKwVMKvUl9QQVRIwrBUwq9TSVpFX1BDS8KwTsKvU0laRV9EQVRBwrBOwq9TSVpFX0FUQ0jCsE7Cr1NJWkVfRE9DU8KwTsKvREFURV9JTsKwRMKvUl9EQVRBQkFTRcKwVMKvUl9TRVJWRVLCsFTCr1JfQ09NUFVURVLCsFTCrw==
Any ideas?
The file saved by your Delphi 7 program is UTF-8 encoded. I decoded the base64 that you supplied and look at it in a hex editor. It looks like this:
The first two bytes are C2 B1. That is the UTF-8 encoding for ±. You can check that here: https://mothereff.in/utf-8.
Use LoadFromFile(..., TEncoding.UTF8) to load the file, and SaveToFile(..., TEncoding.UTF8) to save it. That's all you need to do. Note that when you save this way then a BOM will be included in the file. If that is not desired then it possible to omit the BOM, as has been covered here before.
Do note that you must remove the call to StringReplace. That modifies the text and serves no useful purpose. You absolutely do not wish to replace U+2015 ― with U+00AF ¯.
Based on the comments to this answer it seems that you have some Delphi 7 code that produced UTF-8 encoded text which behaves incorrectly when executed by Delphi XE8. That's not surprising due to the change from ANSI to UTF-16. You will need to revisit this code and adapt it appropriately. It's impossible for us to say more given the fact the only you have this code.
It feels very much as though you are trying things almost at random and hoping for a quick fix. That is not productive. You will only make progress with a clear understanding of Unicode, and your program. You will need to step back, slow down, and fill in the gaps in your knowledge.

How do I keep Delphi from automatically expanding folded code regions?

I widely use {$Regions} in my units, but sometimes the VCL editor takes annoying decisions to automatically expand all regions. Is there any way to tell the editor not
to expand regions that are collapsed unless I explicity do this by clicking on the + button?
Update from comments:
Unfolding occurs,
with nested procs/funcs. Introducing a new nested "procedure" header. As soon as you type the 'p' character, all other nested procs/funcs are unfolded. This occurss also if, for instance, by mistake, you delete the "end" of any nested proc/func (or anything of the kind).
with regions. If you start a comment with "{", the Region immediately below is unfolded. Starting a comment with "(*" provoques all Regions below to be unfolded and same applies to all procs/funcs under those Regions.
Unfortunately this is one of the problems of Delphi whis is present athleast since Delphi XE if not even from older versions and still hasn't been fixed.
The reason why code gets automaticaly unfolded is the fact that as soon as Error Insight system detects any syntax error in your unit it treats all the code below that poiunt as non-valid and thus expans all folded code below that point.
So far the only way that I know to avoid this is to disable the Error Insight. But that means you won't be warned about any potentional syntax errors untill you try to compile your program.
But I seriously hope Embarcadero will go and fix this soon as it makeswhole code folding system to be useless unles you have Error Insight disabled as you spend more time folding the autoexpanded code again that writing any new code.
EDIT: Steps to reproduce this (one way of reproducing it)
Create new application
Create two new even handlers for OnCreate and OnClose for your form or any two other methods.
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//
end;
In case if you created even handlers make sure there is athleast some code in the lowest handler metrhod or athleast one commented line so that optimizer doesent automatically remove the "empy" event handler.
Now in top event handler write "Form." and you will se how bottom event handler will be automatically expanded.
You will see that at this point delphi desent even know when or where current method code block in which syntax error has been detected ends. And this also makes it imposible to properly detect any code blocks below that point.

Delphi error appeared suddenly on one machine: E2056 String literals may have at most 255 elements, how is it possible?

I was able to build one application up to this morning, then I don't know what happened as I try to build I have
[DCC Error] myunit.pas(1710): E2056 String literals may have at most 255 element`
Why this if this was working? (1710) was not edited in last month. I checked with a colleague project options and environement options one by one and they are the same. (the only difference is that i installed all Delphi updates, while he didn't anyway I didn't install them today).
moreover if I fix the above "erroor" by splitting the string in 2, doing something like
S := 'firstpart' + 'secondpart';
instead of
S := 'firstpartsecondpart';
// this is an example of course firstpartsecondpart
//is a string of more than 255 chars
I have another problem:
[DCC Error] myunit.pas(1797): E2283 Too many local constants. Use shorter procedures
Why this? I didn't change this procedure today. It is a long procedure indeed, but it used to compile up to this morning. I tried to split tjhe procedure in 2 and I was able to compile...
And Finally...
Breakpoints doesn't work anymore. If I try to set a breakpoint, after compiling and linking the RED cirlce of breaxpoint becomes green with an X, like when you try to debug a line of code that cannot be debugged.
I tried all, including rebooting and setting Debug Info to True in project options.
FINAL NOTE: It seems that for some reason some strange settings have been applied. I can't recall having done something strange. Recently I installed CnPack, but I could use it effectively for days. This problem started today.
Can anyone give me an hand? I am in real trouble, I lost half day and I still don't see a way out.
It seems you've changed the "Huge strings" project option. Did you add a {$H} to your code? Or did you fiddle with the project options? ("Compiler options/Huge strings" need to be checked to default to strings longer than 255 characters.)
The green breakpoint thingie means that this specific code is not compiled, thus it will not be called. Check if your code is calling this code, or perhaps it's looking at some other (pre-compiled?) unit.
My comments from below to complete the answer:If all breakpoints are green, it appears you have a problem setting the project options. If you remove the YourProject.dproj and YourProject.dproj.local files (Move somewhere else, don't delete) and then open the YourProject.dpr, your project should have the default options. Check if it works in that case. If not, move the old files back.The E2056 error is because strings inside Delphi code cannot be longer than 255 characters. Splitting it by including '+' in your string can fix this. See qc.embarcadero.com/wc/qcmain.aspx?d=71575 for why your collegue doesn't get this warning.

Delphi "EClassNotFound" errors, and corrupted DFM possibility

I am getting a cascading set of "EClassNotFound" errors in in my Delphi 2007 project. Doesn't seem to be caused by the missing Name property value as often is the case, and though adding RegisterClass(XXX) in the initialization section(s) fixes the EClassNotFound error at hand, another one follows it seemingly indefinitely.
I finally cracked open the DFM file in text editor, and it looks likely corrupted to me (lots of non-ASCII characters amidst form element names, and very "unstructured" looking when compared to what I'm used to seeing in a DFM file). (I'd post a same here but not sure that's OK, w/the non-aSCII, so will hold off).
The form loads fine, and seems to compile / syntax check OK too, but once I run it, trouble.
Going back to early versions of it in SVN, it looks like it's been in this state for some time, which makes me think that either A) the DFM file isn't my problem, or B) the Delphi form-streaming is quite fault-tolerant/robust (Bonus Question: Which is it?).
If the DFM file is the problem, and is corrupted, rolling back will have to be a roll-back WAY back, and that's gonna be expensive. Given that the IDE can still load it, is there any utility that can clean up the file?
Or, am I totally off base w/the DFM as primary suspect?
Thanks folks for the input. Forgot about the binary/text options w/DFM files, so that was helpful. It looks like the DFM itself is not corrupted.
Still having the EClassError issue though. re: It being missing property values, or referencing non-existing properties, etc., a further question: Is the class the error is given for (currently TnxSqlUpdateObject, but probably more waiting in the wings if experience thus far is consistent) usually/always the actual "culprit" class/object?
For instance, right now my main form has four references to TnxSqlUpdateObject, w/those actually dropped on the form. If I put RegisterClass(TnxSqlUpdateObject) in the initialization section, it runs fine for that EClassNotFound error but then goes on to the next one (in this case, TStringField).
I have reinstalled the NexusDB components in this case, and also built a new project using some of the components I thought might be the problem. It compiles and runs fine, UNTIL I add this other form from my real project (which, in turn, unfortunately references quite a few others).
SO, it sounds like my real issue is how to methodically diagnose and fix any and all EClassNotFound errors?
I get this error if a component is on the form, but doesn't have an entry in the form definition in the source file too. Most often when I've copied and pasted from another form. Simplest solution is to select the component, cut it, then paste it back. When you save, the component's unit will be added to the source, and when you run it again it will all be okay.
Well, a dfm file could be binary or tekst (as I'm correct from version 4.0).
You can check this by right click on the form and check the Text DFM flag.
If a dfm file is corrupt, tou can try to fix it by removing all suspicious lines.
Be sure to leave the object .. end sets intact and you probably only loose some property values.
By the way, the dfm file should look like this (to get an idea of the general structure):
object Form5: TForm5
Left = 0
DesignSize = (
426
652)
object Button1: TButton
Left = 343
end
object Memo2: TMemo
Anchors = [akLeft, akTop, akRight, akBottom]
end
end
If it does not look like that you are probably editing the binary file.
If you have a recent compiled exe that works, you can use a resource-editor, like PE Explorer, to get the dfm-definition. Then you can compare the one from the exe with the one that you now have.
I believe there is tools to convert binary dfm-files to text-files too. This will give you a better view on the file, and help you decide if it's really corrupted or not. I see Felix has something on the topic.
If the Delphi IDE shows the form ok without errors, I can't believe there is a corruption-error. Could there be a package problem? Do you use runtime-packages?
Update:
Hvae you tried Eurekalog or madExcept or something similar to get a more detailed error message with callstack and memorydumt? Maybe that will give you some clue about the problem.
But generally i think this error comes from missing runtime package, or a missing unit in the uses-clause. If you think you know witch component causes the error, search the source for the call to RegisterClass( ), and see if that unit somehow is included in the projcets uses-clause. If not, add it and try again.
If you can load the form in the Delphi IDE the DFM resource is not corrupted. Delphi uses the same code to load the DFM as the final executable will use, so I think that won't be the reason.
You can open the DFM in the Delphi IDE directly (if the corresponding pas file is not open), or you can use Alt+F12 to switch between form view and text view of the DFM. In this view the structure should be sane, with correct indentation and so on.
As Gamecat pointed out you can use the command in the form popup menu to toggle the DFM storage format. Leave it as text for Delphi 5+, it works better this way with SVN.
As for the cause of your runtime problem - I have no idea...
Edit: After your ruling out the DFM as the source of the problem I can only assume that an important unit in the uses list is missing, which can only happen if not all the components on your form have a corresponding member field. You should check that all the components referenced in the DFM are also in the form, even when you do not access them in your code. This will in turn cause Delphi to add any missing units to the uses clause when the file is saved. Manually registering components should not be necessary if the form class has references to all the components in the DFM.
For a quick check you could create a test form, drop all of the components that your "problem" form has onto it (one instance is enough), and check whether this works.
This can happen in case you have changed one of your custom components and removed a property from it. The property is stil in the DFM and Delphi tries to initialize it.
Try to remove manually parts from your DFM so you can pinpoint which component is causing the problem.
Try this:
Make backup first
Right click on form in designer; uncheck "Text DFM"
Save
Right click on form in designer; check "Text DFM"
Save

Resources