If I make major changes to a unit I like to change its name to make it clear this is a different version and avoid confusion with other archived versions for example:
CSVUtils.PAS becomes CsvUtilsNew.PAS
But all references to it from other units have to be changed manually, eg:
Unit ManiForm
Uses
CSVUtils
becomes
Unit ManiForm
Uses
CsvUtilsNew
This gets very laborious in complex projects.
Icarus is very good at finding all the references, but I cant find any tool that would automatically update all the other units.
Does anyone know of any tools which automatically update unit references?
Many thanks
I would use GExperts Grep Search and Replace.
I would use Notepad++ or UltraEdit to Search&Replace in all files (*.pas, *.dpr, *.dproj) the old unit name with the new unit name. Unless you have variables or functions that have the same name as the unit, this works very well, is fast and does not require any specialized parser.
You could also define a unit alias in your project options.
E.g. CSVUtils=CsvUtilsNew
Related
We're in the process of moving out Delphi XE2 apps over to Delphi XE5 (We have a window :) )
I'm wondering whether, as part of the move, I should be thinkning of adding my own Unit Scope to our internal applications. This question suggests that it's just of case of renaming units as Company.Unit.
Is it as simple as using Rename in the Project Manager?
Am I missing anything?
It's nearly that simple. You can use the Rename action in the project manager and that will rename the file, give the unit a new name, and change references in the .dpr and .dproj file. But that will not rename any references in code.
So, if you list the unit in uses clauses (seems likely that you will), or use the unit name to resolve ambiguous scope, then you will need to change the names there too.
If you don't have too many units it won't be very difficult to make the change in the project manager, and then fix all the errors that the compiler throws at you. If you have a larger project then you may be better scripting the change. I expect that you could go 99% of the way there with a simple regex based script that did the following:
Update references in the .dpr and .dproj files.
Change the file names and the unit names.
Find the uses clauses (interface and implementation sections) and update references there.
This would leave you to deal with the uses that perform scope resolution and my guess is that there would be few enough of these to let the compiler find them all.
I use a great Tool from http://www.easy-ip.net (DELPHI UNIT DEPENDENCY SCANNER) for that task.
You can change the Name of the unit and the DUPS change all your uses clause's.
I need (to make some quick and dirty tests) to modify the code of Variants and SysUtils.
What I need to do to "compile" the changes?
I can of course open those units in the IDE, but if I change them and I buoild a project again I don't see those units recompiled.
What is needed to be done?
The problem is you would need to compile ALL of the RTL/VCL against the 'new' units.
Instead modify a copy of the units in question and add them to your project when you want to use them. Delphi should use these over those in the RTL/VCL.
Unless you do not change the interface part of the unit (that is, you only modify the implementation side), you can make your own version of the RTL units (only exception is System.pas and SysInit.pas, but this is not in your scope - see our blog site for some enhancements of those units).
What you need is to put your own version of Variants.pas and SysUtils.pas in the search path of your project. They will be taken in account instead of the default RTL.
But be aware that you may easily break anything.
For testing purpose, this is OK, but if you want to use those modifications, you shall better use some automated regression tests, and know explicitly what you are doing.
Please note that you can use the "debug" version of the RTL units (from the project options), then step with the debugger within the official source code. It may help finding issues without touching the source.
If you change the interface part of the unit, you'll have to recompile all units which call the modified unit - for SysUtils and Variants, this is almost all RTL.
Delphi runtime DCUs are precompiled. It would be a waste of time to compile them at every build.
If the code you are trying to modify is a method of a built-in class, then a class helper may help:
http://docwiki.embarcadero.com/RADStudio/en/Class_and_Record_Helpers
So the question is which part of code do you want to modify in the runtime?
If you really wish to recompile the RTL you can do so (Make a backup first!). Versions of Delphi prior to Delphi 2010 had a makefile in the source folder that could be run from the command line to rebuild the rtl/vcl. I don't know for sure (I'm still using D2009) but from what I've heard this file is no longer present in newer versions. Hopefully there is an alternative. Otherwise you would wind up wasting a lot of time trying to guess that the compiler settings for each unit.
If you wish to "patch" a bug in the rtl for your project only you can copy the unit you want to modify into your project's folder and make your change. If the unit your modifying is used throughout the RTL/VCL you may find yourself copying quite a few dependent units into your project folder in order for it to compile.
If this significantly slows down the compile time for your project you can always do your initial compile then remove the "patched" units, leaving behind the compiled dcus.
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.
I am currently working with 'inherited' code that has (scattered randomly throughout) a whole bunch of conditional compiler directives based on the version of Delphi, going back to Delphi 2 . From now on, all development will be with Delphi 2009 or future. Is there a tool in Delphi 2009 , or a plugin, that will automatically remove compiler conditional code segments based on a specified 'minimum' version?
I highly recommend the Delphi Inspiration Pascal Preprocessor (DIPP)
This can do a number of things with a source file in addition to removing conditional defines, including the "inlining" of include files and removing comments (all of course highly configurable and controllable by options supplied to the processor).
The conditional defines functionality is especially useful as you can either have all such conditionals simply removed or provide a set of DEFINE's that you wish to apply. DIPP will then emit a source file that reflects how it would appear to the compiler with those symbols DEFINED, but without the conditional directives themselves.
So in your case you would simply defined the symbols appropriate to your "baseline" Delphi version.
You should give JEDI PreProcessor (Pascal PreProcessor) in the JCL a try.
In the trunk in our SVN the source can be found in the dir jcl/devtools/jpp and in our latest release (2.1) zip-file the jpp.exe can be found in the dir devtools.
I don't know of such a tool but it should be relatively straight-forward to write it.
Loop through all files in the directory using FindFirst and FindNext
Use TStringList.LoadFromFile to read all pas files.
Loop through the strings and look for {$IfDef} directives. If the version specified in the conditional section is older than D2009 remove all text until the {$EndIf}.
Use TStringList.SaveToFile to write the modified file to disk.
My advice would be to ONLY change code you completely manage. If however you are also going to modify existing 3rd party code, then I suggest you go through each IFDEF defined for validation. Some vendors do not use the standard IFDEF VERxxx calls, but create their own which might be called something like VER70UP or such. The most common place for this would be in include files, so look for a {$I ???.INC} file near the beginning of each file, then analyze this for what is being used and how.
The other reason to analyze each $DEFINE/$UNDEF is the fact that a version specific one might turn on a new define that your previously not checking...one that ultimately leads into dead code.
Use GExperts, you can use both GrepSearch or GrepRegularExpressions to search in your code and then use the Replace tool in the GrepResults to remove whatever you need.
You can do a search and replace
operation on all of the matches in the
list or only the selected file/match.
When you choose one of those options,
a dialog appears prompting for the
string to use in place of the matched
text. Note that forms that are
currently open can not have their text
replaced, due to limitations in the
IDE. Please close all forms before
trying to replace text in them.