Just upgraded from Delphi XE to Tokyo, and was hoping for some updated IDE features.
One nice to have feature would be automatically providing options to add a unit to the uses clause. For example, if you reference something in code that isn't in a uses, it would be nice if the IDE prompted you to add the related unit(s).
For example, keeping it simple, in IntelliJ, you might declare a Button, but not yet have added the associated Library to the Import clause.
When this happens, the offending line is highlighted (just like in Delphi), but the IDE will let you add the necessary library with an Alt-Enter. If there are multiple libraries (it knows about it) it will prompt you for the one you want.
Anything like this for Delphi?
Delphi 2007 and later versions support this for most types that it knows about (in the search or library path). (It may have been available in D2005/2006; I don't have them installed anywhere now to check. I know it was not in Delphi 7.)
Put in the type, and use the Refactor menu (Refactor->Find Unit) or press Ctrl+Shift+A.
Here's an example:
It's not 100% effective, but it's a vast improvement over the old way.
(And yes, I know about TArray<string>, before someone chimes in. I just grabbed a quick type that I knew wouldn't be in the default VCL form uses clause for an example.)
Related
I tried to copy and paste a component from one data module into another in Delphi XE2. The component was a Fast Report data source link component. The data module was brand new, just created that second, in XE2.
Someone else had the same problem and reported it on quality central as 106369 and same error message leading me to this mysterious DocWiki entry.
So data modules now have a framework affinity, and a designtime-only pseudo property, which according to the docs:
"Because the ClassGroup pseudo-property is used only by the IDE and is not a compiler-generated property (hence, 'pseudo-property'), ClassGroup is not documented in the compiler-generated Libraries Reference. The page you are reading is the documentation for ClassGroup."
So, the first time I even learn this exists is when it blocks me from copy and pasting components into my data module from an existing set of designtime building blocks that I didn't wish to rebuild from scratch.
Once I change the data module affinity, I can paste stuff into data modules without it bugging me. Thank goodness for Google-that-error or I'd be stuck.
If it is intended to help us write cross platform data modules, and yet it only affects the IDE, according to the documentation, that's inconsistent with the warning that you get when you play with this at designtime, here's the error you get if you change it:
EInvalidType : The following component(s) are not available in the specified
class group. This is likely to cause compile or runtime errors.
frxDBSet.TfrxDBDataset.
What I can't see is how that error message can be correct, and the documentation can also be correct.
The warnings seem to suggest compile, link, and runtime errors if this is set incorrectly. Curious minds who want to know what's really going on, want to know: What is this thing about and why did it get added to the data modules in XE2. I anticipate other people will stumble upon this weird feature, with the feeling that they've stepped in something like dinosaur droppings, and want to know what is up with this feature.
My best answer at this point is that a data module affinity for TPersistent which means, in XE2 lingo, that this data module doesn't want non-visual controls in it, that are VCL-specific. In a future version of Delphi, perhaps a similar marker would allow us to mark forms as being "clean of dependencies on the VCL or windows" too?
Update 1: The .PAS source code of your data module stores this pseudo-property in a way that looks a bit like a compiler directive, like this:
implementation
{%CLASSGROUP 'Vcl.Controls.TControl'}
I think it is pretty obviously what its intended use is for, and the documentation you link to is pretty extensive about that purpose.
It is meant to prevent VCL-only components from being placed on a FireMonkey-accessible DataModule, and vice versa.
Since TDataModule is initially framework-neutral, only framework-neutral components can be placed on it.
So obviously, your source DataModule has a different affinity than your new DataModule, which is why copy/paste does not work until you change the affinity of the new DataModule to match the affinity of the source DataModule.
MS Visual Studio has a great feature: it automatically suggests the units to add in using clause when you typing the code with refrences to absent standard classes.
Is there any 3-rd party tool to implement similar feature for Delphi?
I'm tired to add all those SysUtils, Windows, Messages etc in each new unit.
If the unit which contains the reference is not yet in the uses list, this is how I save many manual steps:
right-click on the underlined (error-insighted) text
choose “Refactoring | Find Unit…“.
A dialog will present the available unit which contains the unknown type or symbol, and a mouse click adds the selected unit to the uses list of the current file.
CNPack Input Helper can sugest and autocomplete units (sorry for another answer, but I can't comment other).
CNPack unfortunately don't auto-add units from place of code input but you can:
Copy a word from cursor place (CNPack->Editor enchancements->Tabset/Button->Clipboard operations->Cut/copy token...).
Eventually search this word in source files (grep) to identify unit.
Use CNPack->Toggle Uses/Include Field (Ctrl+u) and start typing and use CNPack->Input Helper sugestion/autocompletion, or IDE/GExperts/CNPack use unit future
Back to place of code edition
The JCL includes the "Uses Wizard." It watches for compilation errors mentioning "Undeclared identifier," and when it sees one, it automatically adds the unit where that identifier is declared.
The package JclUsesExpert.dpk is only available for certain Delphi versions. I don't know if that's because the plug-in doesn't work in later versions, or if someone merely neglected to copy the project into later versions' folders.
This is not a tool to suggest references, it only cleans up unneeded unit clauses.
CnPack IDE Wizards is an excellent opensource plugin for Delphi.
http://www.cnpack.org/index.php?lang=en
I use its Uses cleaner feature a lot.
There is a menu item:
CnPack->Project Enhancements->Use Unit
I think this can be helpful for your needs.
Or maybe you can try this:
http://www.epocalipse.com/products.htm
Unit Expert
"A freeware Delphi add-in that allows you to quickly open units and also add them to the uses clause."
I never tried this expert but it semms promising.
The rFindUnit IDE extension is the enhanced version of built-in "Refactoring | Find Unit…" function suggested by #mjn above.
Please explain package use (in short sentences with small words (for Dummies)).
I just moved from D7 to XE2 and packages seem much more prevelant, and I seem to need to qualify a lot more things.
In D7 I would say uses windows and now I must say uses winapi.windows.
I find that when I call MessageDlg() I can't pass in mtError, I need to qualify it.
Before I go too far down the wrong road - what's the simple solution?
Can I somehow continue to use my old code with package names which I suspect are terminal (that is, for packages A.B.C I have auses C clause).
Can I add one statement somewhere to do this? Or configure the project.
Sorry to sound so dumb :-(
Package use is no different in XE2 than in earlier versions. What is different is that all of Embarcadero's unit names are now prefixed with new Unit Scope Names ("System", "Vcl", "Winapi", etc) to help designate which units belong to the RTL, the VCL, FireMonkey, specific platforms, etc.
You can update your code to fully qualify everything now, if you want to, but you do not have to. You can instead specify the particular scope names in the "Unit Scope Names" setting of the Project Options instead, then no code changes are needed (other than the usual changes when migrating from one version to another).
These are called unit scopes. Because of the new FireMonkey libraries, and the cross-platform support, it's required that you declare which unit you're referring to for types and function declarations.
You can set defaults using Project->Options->Compiler->Unit Scope Names. This is documented as well.
Remember the old class hierarchy posters that used to come w/Delphi?
I'm wanting a full class hierarchy browser for ALL my Delphi classes, including the custom ones I've built and installed on the palette, plus third-party components. Ideally easily searchable by class name (including "whole word only" searches, so partial matches don't count).
I've only seen two things that come close:
1) GExpets Class Browser - Works great, BUT doesn't automatically load ALL installed components / classes, which is what I want. You have to import all the source units manually, as far as I can tell.... which can be quite a hassle. It also doesn't allow "whole word only" searches, so sometimes searching for a class w/a common "sub name" takes forever.
2) Eagle / DevExpress CDK - It loads the full class list automatically, and seems to work brilliantly, but it's only usable in D7 and prior, and it's not really focused on being a class browser per se, so much as an "inherit from" chooser.
Is there anything out there which does this already? If not, how difficult would it be to write an app that, at bare minimum, builds a self-referencing class-name table, so I could at least throw it into a database / treeview component to easily view inheritance / ancestry, etc.?
I think ModelMaker Code Explorer has this feature, but I don't use it
ESSModel is another nice class browser tool, and it's open source. I don't know if there's any way to get it to load a list of units automatically. Not sure, but you may be able to manually import all the units you want and then save that as a base project that you start from with all your individual projects. Not sure how performance would be with that much loaded, or how easy it to view the part(s) you want.
http://essmodel.sourceforge.net/
Assuming you need a Delphi IDE Expert (you've mentioned somewhere in your post: "...installed on the palette, plus third-party components"), DelphiDiver is good for you (Source code available on the DelphiPraxis, registration needed).
Look and feel:
If you feel like delving into the IDE in order to get more indepth details, click Inspect the IDE hence the name of the Expert (DelphiDiver) ;-)
Click Inspect the Packages so as to browse any other third party component(s) or whatever package(s)/component(s) you've installed.
It makes use of the advanced RTTI and requires Delphi 2010 version onward.
I've personally installed it using Delphi XE on my box.
I hope it can serve as a base for the more focused Full VCL Class Browser you are looking for.
Following up on this question, I'm working on a large Delphi 7 codebase which was not written very nicely.
I'm looking at code like this, as a small example:
if FMode=mdCredit then begin
Panel8.Caption:='Credit';
SpeedButton3.Enabled:=false;
SpeedButton4.Enabled:=false;
SpeedButton5.Enabled:=false;
SpeedButton5.Enabled:=false;
SpeedButton6.Visible:=False;
SpeedButton10.Visible:=False;
end;
Followed by another 6 very similar blocks. The whole thing is in this style.
So I'm thinking that this would be much easier to read if the controls were named sensibly.
I could just use a global search and replace, but I'll run into problems when multiple forms use the same names, and also I'd have to be careful to change (eg) SpeedButton10 before SpeedButton1.
Is there some plugin which has the ability to perform a "smart" rename for me?
Edit:
Sorry, I should have mentioned this before: I tried both GExperts and Castalia's "Rename Component" feature, but they both seem to be intended for use when adding the component to the form initially.
They don't do a search+replace in the code, or rename existing events (SpeedButtonXClick() -> cmdCreditClick()).
Have I missed something?
Not exactly a plug-in, but you can use one of the more recent versions of Delphi and the refactoring feature in there. Maybe you could use the free Turbo Edition . . .
You might try ModelMaker for Delphi 7. It has refactoring support that might work for you.
The Rename Symbol refactoring in recent Delphi versions will work across units in a project. Since you say Delphi 7 I guess that's not going to help you, and in the past I've just used TextPad, a great editor that (like many others) will do powerful search/replace across files (with or without confirmation).
HTH
Edit: Craig's right - GExperts will do this, as will Castalia.
I think GExperts has a search and replace like this.
Don't know if it can work in your case, but you could try to load your project in a later version of Delphi that has the refactoring capability and use it to change the components names while taking care of all the dependencies. Then you just have to do a diff and see what has been changed.
Why not use Sync Edit? Its part of the IDE (at least in 2006+):
The Sync Edit feature lets you simultaneously edit indentical identifiers in selected code. For example, in a procedure that contains three occurrences of label1, you can edit just the first occurrence and all the other occurrences will change automatically.
(copied from the BDS2006 Help)
You will have to rename your components first, but it takes the pain out of most of this. I prefer the GExperts wizard of renaming components as they are added to the form, but as you pointed out, it only works when the component is added to the form, and doesn't reach into the individual usages of the components in code. The reason for the renaming of the components first is that when you select the entire block of code to do the rename, it won't make the appropriate changes in the dfm file...just your locally selected code block.
To use the feature, select your entire implementation block, then press the button in the gutter that has two pencils "linked" by a line...then press tab until you get the first one you want to edit...when you change its name, it will change globally in the rest of your source file. Press ESC when your done.