The Rename Identifier editor expert has received several improvements that make it smarter and safer. Here’s an overview.
Identifier info display
The rename dialog now shows detailed information about the identifier under the cursor:
- Kind: variable, constant, type, parameter, field, property, method, or external identifier
- Type: the declared type (e.g.
Integer,TStringList,array of string), including generics likeTList<Integer> - Scope: where the identifier lives: local in a procedure, member of a class, or unit-level, with interface/implementation distinction for unit-level identifiers
This lets you check that you’re renaming the right thing.
Conflict detection
When you type a new name, Rename Identifier checks in real time (with a 200ms debounce) whether the name already exists as a visible identifier in the same scope. For example, if you’re renaming a local variable and type a name that’s already used by another local variable, a parameter, a class member, or a unit-level identifier, a red warning is shown. The warning is informational only: it doesn’t block the rename, since there are legitimate reasons to introduce shadowing.
Component coordination
Rename Identifier now works together with Rename Components (Shift+F2):
- Source to DFM: When you rename a component field in the source editor (e.g.
Button1), the component is also renamed in the form designer. A warning label reminds you that the DFM will be affected. Renaming the form itself is blocked with a message directing you to the Object Inspector. - DFM to Source: When you rename a component via Rename Components in the form designer, source code references are also updated. This is controlled by a new “Also rename source code references” checkbox in the Rename Components configuration (enabled by default).
- Shared shortcut: Shift+F2 now forwards to Rename Identifier when the code editor is focused, so the same shortcut works in both the form designer and the code editor.
Method parameter fix
When renaming a method parameter, the rename now correctly propagates between the class declaration and the implementation. Previously, only the scope where the cursor was located got renamed, and the other half was missed. For example, renaming AValue in the implementation of TMyClass.SetValue now also renames it in the class declaration, and vice versa.
Implicit Result variable
In Delphi, every function has an implicit Result variable that is never explicitly declared. Previously, placing the cursor on Result and invoking Rename Identifier treated it as a unit-level identifier and would have renamed every Result across the entire unit.
Result is now recognized as an implicit local variable belonging to its enclosing function (or constructor/destructor). The dialog shows it as:
- Kind: implicit function result
- Type: the function’s return type
A warning is displayed: ‘Result’ is a compiler-managed implicit variable. Renaming it may cause unexpected behavior.
The implementation correctly handles Delphi’s scoping rules for nested routines:
function Outer: Integer;
procedure Inner; // NOT a function, no own Result
begin
Result := 1; // refers to Outer's Result
end;
function InnerFunc: string;
begin
Result := 'x'; // refers to InnerFunc's Result
end;
begin
Result := 42; // refers to Outer's Result
end;
- Renaming
ResultinsideInner(a procedure, not a function) renames it in the enclosing functionOuter‘s scope, includingResult := 42inOuter‘s body. - Renaming
ResultinsideInnerFunconly affectsInnerFunc, because a nested function has its ownResultthat shadows the outer one.
Tests
The Rename Identifier engine now has 69 unit tests covering local variables, parameters, class members, records, unit-level identifiers, shadowing, nested procedures, forward declarations, class methods, component coordination, identifier info, conflict detection, implicit Result, and various edge cases.
As usual, if you want to try this before the next official release, you can compile your own DLL.
Discussion about this in the corresponding post in the international Delphi Praxis forum.