Delphi Code Completion Fails - delphi

We use Embarcadero Delphi 2010 and recently a change was made to one of the units of a medium-sized project, causing code completion to stop working completely -- but only inside this project, it still works fine in other projects. Puzzled, I searched the interwebs for clues on what exactly could make this happen, but my search wasn't too successful.
From what I gathered, it looks like IDE has a few parsers/compilers that work completely separated from one another, which makes it entirely possible that the faster code-completion compiler could fail where the main compiler would not. Which is exactly what's happening to my project.
My question: Is there a way to find out WHERE exactly the Code Insight/Code Completion compiler is failing? Does the IDE keep a log of on-the-fly parsing/compilations anywhere?

Is there a way to find out WHERE exactly the Code Insight/Code Completion compiler is failing?
Not readily, not without debugging the IDE.
Does the IDE keep a log of on-the-fly parsing/compilations anywhere?
No.
I suggest that you install Andy Hausladen's IDEFixPack. If that does not help then use your revision control to isolate the code change that causes the problem. And find a different way to write that code that happens not to bork code completion. Trial and error is likely to be the most productive method here, much as I hate to say that.

I recently had the same problem using Delphi 10.2. After a lot of research I found that I had inadvertently declared a variable in a type section with an end; following on the next line. Removing the errors restored the code completion function. So I would recommend combing the interface for an error or restoring a backup from the directory history.

Related

Delphi Internal Error when compiling a DPK Project

I have a DPK project which sometimes shows errors ("out of memory") while compiling (into Delphi IDE), and sometime it compiles with success.
But, when I try compile it through the MSBUILD, it always throws this error message:
error F2084: Internal Error: AV004A784A-WFFFD3764-1
Someone have an idea to solve it?
An internal error like that is a compiler error. We cannot solve them, only the compiler developer can do so. You need to submit a bug report to Embarcadero. Given the antiquity of XE3 you are unlikely to ever receive a fix.
Modern versions of Delphi are less prone to out of memory failures so if upgrading is an option then doing so will likely side-step the problem.
If upgrading is not an option then you are probably going to have to keep muddling along and cursing every time you encounter one of these errors.
This is actual very common (at least i experienced these kind of errors very often). I did go with the approach to remove source code files step by step from the DPK until compiling works. This way you also see which file is causing these errors, then go ahead and outcomment source code parts in this file step by step until you find the offending line, then rewrite it (in what way you need to find out yourself).
As David Heffernan already said, there is no way you can really solve it, because the error is internal to the compiler or linker, and only the developers of these can remove that bug.
But often, there are some workarounds.
In my experience, such internal errors are often related to generics and anonymous methods, or to inlined code, especially if two or all of these are combined.
So find out what code change you made before the internal error occurred. If you use a versioning system, or Delphi's internal _history system, restore to a previous version until the error goes away. Then you can do a difference with your "offending" code and see which code caused the internal error.
Often, too complex expressions (especially for the types I mentioned above) cause internal errors. If that is the case, try to simplify the expressions by calculating subexpressions first. Also, instead of using ad-hoc generic declarations like
x := TList<SomeType<Integer>>.Create;
you should try to use pre-defined types:
type
SomeTypeInteger = SomeType<Integer>;
SometypeList = TList<SomeTypeInteger>;
...
x := SometypeList.Create;
In other words,
try to find the "offending" code by going back in your history until it goes away
once you have found it, try to simplify that piece of code. Disentangle expressions and predefine types
experiment with different ways to express the code until the error goes away
If you do that, you may be successful in avoiding the internal error. It has often taken me some time, but I have always found a way to achieve what I wanted. If you couldn't, ask about specific errors here (by posting the offending code, the exact error and if possible a Minimal, Complete, and Verifiable example).
Fortunately, these errors have become very rare in the newest compilers.

Why are there errors in my structure viewer pane but not when I compile?

I build my project, and there are no errors:
That's because the build succeeded without any errors:
This is a good thing. The application runs and everything!
Except there are errors
What the compiler doesn't tell me is that there are errors:
I just happened to have this file open. And i just happened to have the Structure viewer open. And i just happened to see the errors.
Is there a way for Delphi to report all error it encounters during a build?
Is optimization on?
No
It's no big deal for a simple one-form test application, with one error. But when i have 200 forms, XE6 starts to look as bad a Visual Studio 2012. I then have to be sure to manually open every code file and check if there are any errors in it.
Is there a way to get XE6 to report all errors?
#xe6usability
The compiler is correct. Your code does not contain an error. You have two functions with the same name, but declared with the overload directive.
The IDE's Code Insight, or Error Insight, or whatever the feature is called, is mis-reporting this as an error. This is an age old phenomenon. The IDE uses a different code parser from the real compiler. Indeed, if I recall correctly, it uses multiple such fake parsers. They are not as good as the real one, and not infrequently get things like this wrong. It's considered to be a minor inconvenience and that's probably reasonable. I'd much rather the real compiler got it right than the other way around.
Short answer: Turn off ErrorInsight, it doesn't work.
Click Tools, Options, Find Editor Options item in the list, expand it, find Code Insight, click it. Then unclick Error insight.

How can I load a package and keep the debugger working?

I'm using TJvPluginManager in the JVCL to create and load BPL-based plugins for my program. Problem is, one of the plugins isn't loading properly, and I can't debug it. Every time I try to trace into the loading sequence, it gets as far as the LoadLibrary API call, and then the debugger seems to forget what it's there for. It completely loses the ability to associate program code with source lines, give meaningful data in a call stack, or display local variables. It will still stop at breakpoints, but it breaks to the CPU window, with all the inline source code stripped out.
This happens on Delphi 2007 and 2009, and it's driving me nuts. Does anyone know how to load a plugin without it breaking the debugger? Does anyone even know why it's breaking it in the first place?
NOTE: I'm not looking for alternative methods of debugging. I know all about tracing and logging and all the rest. What I want is to understand what's going wrong and how to fix it. Surely I'm not the only person who's ever used TJvPluginManager?
Not quite the answer to your question: Have you tried to debug the package project, by setting the host application and putting a breakpoint into the package's startup code?
I've found Ray Kanopka's (Raize) CodeSite to be invaluable for debugging in situations where the integrated debugger is acting up. Thinking about the things I want to monitor using CodeSite actually helps me focus on what's important - it enforces good habits.
Another alternative to Codesite is Overseer which is part of the nexus project, but stands alone so does not require you to use their framework. Codesite is by far the better option, but in a pinch Overseer would work just as well.
I found that using packages for plugins can be problematic and many years ago switched to a completely COM based implementation for plugins and never had any problems. The other advantage to COM based plugins, they don't require Delphi to write, do not need to be recompiled when the main app switches to a new version of the compiler (my plugins compiled with Delphi 5 still run fine against the main application compiled in Delphi 2009!) and they are easier to write test applications to assist in debugging.
The only side effect I notice, is that shared code ends up in both executables and the plugins require registration into the registry.
Hmmmm... This is a stupid question, but I have to ask: the initialization function have the EXACT declaration syntax like the other plugins that work ?(from your question, I deducted you made some others that work)
Check your dependencies. Make sure each unit is compiled into one package only. Whenever a package needs to reference a unit from another package, use the requires clause to do so. Watch for compiler warnings about implicitly linked units.

Incorrect circular reference error

Our team had been using Delphi 6 for many years, then switched to Delphi 2006 years ago. With both versions we have the following problem: frequently the compiler complains about a unit which is supposedly used recursively. This unit is a 40k LOC unit which is at the core of a project with almost 1 million LOC (third party included).
The error message is incorrect: a full build on the project always works. Unfortunately, the error message does not tell us where the supposed circular reference is, just the name of that unit. Sometimes it even happens that valid error messages are listed 2-4 times until that circular reference problem is "found". Clearly the compiler is running in a circle here. Because of the size of that project it is hard to find the problem manually. Therefore I made a tool which proves that there really is no circular reference (the tool creates a directed dependency graph of the units and determines the coherence components in that graph - there are none except if I deliberately put some in).
This is not only affecting F9 compilation but also code completion / insight which is not working most of the time. Sometimes it works when I press ctrl-space a second time...
Any ideas how we can isolate or even fix the problem? Note that it will be very hard to split the 40k LOC unit into smaller ones because it contains about 15 large classes which depend on each other in the interface section (I know it's bad but should work anyway).
Update
We are constantly refactoring but this is one tough unit to refactor because everything depends on everything, almost. Have been trying to get around it via interfaces but we are talking about some classes with 100s of methods and properties. And it would be slower.
Upgrading to D2009 may be an option down the road but right now we're stuck with D2006 (the unicode stuff and the price tag are two of the stoppers here). Question is anyway if it would help since the problem is in there since D6 at least.
About trimming the uses clauses, we have been doing this frequently with Icarus. But that did not help so far. We are down to 90 custom units in the interface section now. However, with a true circular reference the problem could be in any unit. Also tried to add all units to the dpr.
The project shares a lot of code with other projects, and there are some IFDEFs. However, the defines are not set up in project options but via a common include file. Therefore all modules should see the same defines. Also, the problem reoccurs shortly after a full rebuild without switching to another project.
I will probably be downvoted for this. In D2005 I had a 10k loc unit (datamodule) that flat out stopped compiling. Had to separate out some datasets/code to another datamodule. That 10k unit was and is a mess. You really should consider refactoring out some code to other units. My module has since D2005 / separation grown even worse, but it still compiles in D2007. So my answer is a) refactor and b) upgrade to D2009.
It seems clear that this is due to a slight difference between the background compiler and the real thing. You could look around (QualityCentral) what's known on that topic.
Also, since you didn't explicitly state this, you should remove unnecessary units and move uses statements down to implementation if possible. Maybe your tool could help with this.
And just to be sure you should check the unit aliases and Path settings.
You write that a full build does always succeed, but shortly after the incremental build fails with this error. Assuming that you experience this in the IDE, have you tried to use the command line compiler dcc32 to do incremental builds?
If you don't feed it the "-Q" switch (which probably most Makefiles or scripts for command line builds do) it will output a lot of information what files it compiles in what order. You could either try to do an incremental build after the error appeared in the IDE, or you could keep a command line open next to the IDE and Alt+Tab to it for compilation, skipping compilation in the IDE completely.
I simply assume you have a way to build using dcc32, one way or another - with the size of your project I can't imagine otherwise.
We regularly fall in similar problems, and we never managed (or bothered long enough) to find the precise cause. There seems to be a problem in the order which Delphi chooses to compile the units when hitting Ctrl-F9, which is incompatible with the actual dependency order of the units.
Have you tried deleting "MyBigFatUnit.dcu" before hitting Ctrl-F9?
Have you tried to re-order the declaration of your units in your dpr/dpk files, so that units appear in a correct compilation order? (i.e.: if unit B depends on unit A, unit A should appear first in the dpr/dpk)
Do you have any other projects that use part of the same codebase? If you compile one of them under different compiler settings or IFDEFs, it might change certain things in some of the DCUs which would lead to a circular dependency. A full build rebuilds all DCUs and then the problem goes away.
Try Icarus (free) from Peganza. If that does not tell you what the problem is, try their Pascal Analyzer.
We have this problem as well, also with a fairly large codebase.
We are currently using D2009, but have had this problem with all previous versions of Delphi.
It most frequently happens immediately after doing an update from source control, so I suspect there is some timestamp issue within the Delphi build process.
In our case, if Ctrl-F9 fails and reports the circular reference, a second Ctrl-F9 will generally work
A way I have been told to deal with this is to open another arbitrary file in the project, change that file, save it, and then try running the incremental compile again. Surprisingly enough, this usually works.
We have a 4 MLOC project where this comes up from time to time and this "solution" works for me.
I've fought this before, in my experience the error is quasi-legitimate. It's been a quite a while (the error has nothing to do with the version) but my memory of the situation is that it involves a loop in which part of the loop is in the implementation.
Unit A uses B in the implementation. Unit B uses A in the interface. If you compile B first it calls for A but since the call for B is in the implementation it succeeds. If you compile A first it calls for B, B turns around and calls for A in the interface, boom. Such loops are only safe if both cross references are in the implementation.
The solution is to design things so there is a minimum of stuff used in the interface and to make certain there's nothing resembling a loop in those units. So long as you keep your type definitions separate from units with code this is pretty easy to do.
The error coming and going depending on what you are doing is a hallmark of this issue as it comes down to how you enter the loop. When you do a full build the order is consistent and you either get it 100% or 0%, it's not random.

Delphi debugger?

I'm finishing an internship at a company and have just been thrown onto this project for the last month where the program is built upon an engine that they "failed" to buy the source code for. Now I've been given the task of finding out why it is failing, on only certain conditions and customer feedback hasn't been great. The main developer for the project is also out on leave for several months.
I have the engine install and know the language it was written in (delphi6?).
note which I have never had to use
I have our products msi.
I'm expected to go through the regular app and pinpoint the problem. I suspect it is something to do with fields not being re-initialized properly.
Is there a way to attach a debugger to the exe to see callstacks and all that hotness?
Any help that would avoid countless use cases would be received gratefully.
You can attach the Delphi debugger to any running process (like all other win32 debuggers out there) but I don't think the experience will be near what you expect. Delphi produces really tight executables which means the info for building human readable callstacks or any kind of "hotness" are simply not there.
Your only chance is in that if your application is a Debug release. In that case, Delphi debugger should help more than a generic debugger.
You might also want to have a look at this thread - Is there a program to decompile Delphi?
In Delphi 2006 (not sure about 6) you can attach the debugger to a running process.
You only get assembler instructions, registers, flags, memory dump and stack (hex). Hope that is enough.
Nice, I tried to attach to the ide/debugger and they disallowed that ;-).

Resources