Skip to content

Release 2.11.1 - Delphi 11 and 12, a new Missing-const check, and everything since 2.0.1

Choose a tag to compare

@jaenicke jaenicke released this 29 Oct 10:25
· 20 commits to main since this release

2.11.1 - 2026-10-29

The first release since 2.0.1, so it carries everything from 2.0.2 on. The
notes below cover 2.10.0 to 2.11.1; the per-version entries for 2.0.2 to
2.9.6 are in
CHANGELOG.md.

Note: The binaries are for Delphi 13.2.

What is new since 2.0.1

  • Delphi 11 and 12 are supported (PR #55 by alexeydott), with one
    install script per version - install_D11.cmd / install_D12.cmd pass
    their version and nothing else, and which platforms are built is probed
    on the installation rather than derived from the version number.
  • A rename is ONE undo step again, for every file it touches.
  • New project check "Missing const (string parameters)": string
    parameters passed by value although the routine only reads them. A list
    of proposals with a reason each, never a sweep.
  • New tools for the MCP bridge: guide (what this server can do, in
    one call), settings (read and write the plugin's settings, permanently
    or for this IDE session only), lsp_restart, project_open /
    project_close / project_files, and const_params.
  • debug_consistency looks at the DCU output the LSP configuration
    names: a directory that does not match the sources is what makes a
    cross-unit "go to definition" answer nothing.
  • "Move to unit" and "Move to new unit" are one entry with one dialog.
  • Renaming a parameter changes BOTH of its declarations (issues #49,
    #50 and #54 by stepand76 and Ian Branch) - before, the class declaration
    could stay behind, which does not compile.
  • Installing from inside the IDE no longer demands a restart it does
    not need, no longer hangs the IDE, and the status window comes back where
    it was - docked, and as a tab beside its neighbour.
  • Plus the Extract-Method and MCP-answer fixes of 2.0.3 to 2.6.10.

The check found nothing at all

The first live call of "Missing const (string parameters)" answered 0
proposals AND 0 refusals for 113 project files - so nothing had been looked
at, rather than nothing being there.

A parameter group ends at a ;, and in a WRAPPED parameter list that ;
stands at the end of the PREVIOUS line. The group scan walked back only
within the name's own line, so the first parameter of every continuation
line was merged into the group above it: AFile: string; and the next
line's ACache: TDictionary<...> became one group, which is then no
candidate at all because ACache is no string - and a group that is not a
candidate is skipped before any reason is recorded, which is why there were
no refusals either.

Every fixture of the suite had its parameter list on one line, which is how
four green tests sat over a check that answered nothing. The new one carries
the real shape, in both directions: a ; at the end of a line ends the
group, a , continues it.

2.11.0 - 2026-10-29

Project check "Missing const (string parameters)"

TurboMagic's idea from the forum: find the string parameters a project
passes BY VALUE although the routine only reads them. Every one of those
copies the string on every call.

It is a LIST, not a sweep, and that is the design rather than caution. What
the check can prove is that the body does not write the parameter and that
both of its headers are known. What it cannot prove is that no CALLER
releases the variable it passes: a const string parameter aliases that
reference without raising its count, so such a case dies with
EInvalidPointer and no compiler warning - measured with dcc32 37.0 before
a line of this was written. So each row is a proposal with its reason, and
nothing is written until you tick it.

Refused and SAID, each with its own reason instead of a silent skip: a body
that writes or takes the address of the parameter, a virtual / override
family (a descendant's override must keep the signature), a method an
interface declares (const is part of it - E2291, measured), a
published method a .dfm may bind, a routine whose name is used as a
procedural VALUE (procedure(S: string) and procedure(const S: string)
are incompatible types - E2009, measured), and anything whose two headers
cannot both be read. A parameter GROUP (A, B: string) is the unit of work,
because one modifier serves all of it.

Reachable from Refactoring Light -> Project checks -> Missing const (string
parameters)...
and as the MCP tool const_params, which lists by default
and writes only the ids you name.

2.10.1 - 2026-10-29

Which platforms an install builds comes from the installation

The Delphi 12 install failed because it tried to build a Win64 package.
install.cmd decided that from the version number, on the claim that Delphi
12 was the first with a 64-bit IDE - which was wrong, so Delphi 11 got
Win32 and everything newer got both.

A design-time package is built for the IDE it is loaded INTO, so Win64 is
only worth a round when that installation HAS a 64-bit IDE, and it is only
possible when it also ships the Win64 designide.dcp the package requires -
without it the Win64 round fails at the compiler. The new platforms.cmd
probes both and answers per installation, so a Delphi 12 that ships them is
served just as a Delphi 13 is, and one that does not is built for Win32
alone with the reason printed. install_D11.cmd and its siblings pass their
version and nothing else now; a second argument still pins the list by hand.

Also

install.cmd carried a BACKSPACE character in a comment ("bin64ds.exe")

  • a backslash eaten by a shell heredoc while the script was written. Nothing
    shipped may carry such a byte, and a test now sweeps every script, source and
    .md file for them.

2.10.0 - 2026-10-29

One install script per Delphi version (PR #55, alexeydott)

install.cmd takes the version its registry branch is named after and
stays Delphi 13 without an argument, so install_D11.cmd and
install_D12.cmd do nothing but pass theirs - and there is one install to
keep working rather than three. The same for uninstall and rebuild, and
Standalone\build.bat [config] [version] [directory] follows the rule.
The PR's own scripts hard-coded Delphi 12 instead, which is what made them
unusable for a Delphi 13 install.

What a registration points at can no longer be derived from the version
either: {$LIBSUFFIX AUTO} appends the PRODUCT suffix, and only Delphi 13
has it equal to its registry number. It is read from the TARGET
installation now - the suffix of the rtl*.bpl that IDE ships - so it is
right whatever the two numbers are, and on Delphi 13 it is the 370 it
always was.

Delphi 11 and 12: contributed compatibility code

The {$IF CompilerVersion < 36.0} branches of PR #55 are in: the older
line-editing API, no INTAEditorLocalMenu, a paint state without
CharWidth, the PrivateUsge typo of the older Winapi.PsAPI, and the
async code-insight manager behind {$IF Declared(...)}. None of it is
tested here - no Delphi 11 or 12 is installed - and none of it can affect a
Delphi 13 build: for the five units whose only change is such a branch, the
text the 37.0 compiler reads is byte-for-byte what it read before
(measured with a preprocessor that evaluates exactly those directives).

One Undo step per file after a rename

A rename used to write one editor operation per occurrence, so taking a
30-occurrence rename back needed 30 times Ctrl+Z. The token edits of one
file go through a single undoable writer now, validated as a batch against
one snapshot of the buffer before anything is written - so a file is
renamed completely or not at all, and one Undo takes it back.

Tests

Two fixtures built their own input through TEncoding.ANSI, which means
the fixture loses characters before the test runs on a Windows whose ANSI
code page is not the one that was assumed - the bytes are explicit now.
Two new cases for DecodeVcsOutput (a last line without a newline, and
that the byte COUNT rather than the buffer capacity decides) pass as they
are. And the two script sweeps of the hygiene tests DISCOVER the scripts
instead of walking a list of five, which had left Standalone\build.bat
out of both rules and would have left this round's new scripts out as well.

Not taken from the PR

Its project-file changes: the package's DCC_UnitSearchPath, the dropped
Win64x configuration group, the flipped IMPLICITBUILDING options and the
standalone's own .dproj. The build needs none of them (every unit is
referenced with its path), and a project file is the one place where a
change nobody needs can quietly cost a platform.