Skip to content

v1.14.0-alpha -- Catches: (exceptions a routine handles), property/field refs resolve

Choose a tag to compare

@Alexl-git Alexl-git released this 17 Sep 09:08
· 1284 commits to main since this release

Archives below are self-contained: the exe, the rules\ folder, and (win64 only) the component converter.

Note: the win64 archive's ConvRulesEditor.exe was built from the converter stream's working tree, which held four uncommitted src\tools\convrules-editor edits at cut time (ConvRules.Engine/MainForm/Usage.pas, ConvRulesModelTests.dpr). The engine (drag-lint.exe) is exactly 377be3e5.

v1.14.0-alpha -- 2026-09-17

Catches: -- the exceptions a routine HANDLES (INBOX-report-exceptions-raised-and-handled, gap 3)

The managed facts block gains one line per routine with a try..except:
Catches: EConvertError (dialog: ShowMessage); Exception (re-raise) -- one
entry per (class, disposition), sorted by class name, deduped, capped at
docs.max_handles (default 8) with a visible (+N more). An else arm
and a bare except .. end both count as Exception. Dispositions, first
match wins: re-raise (a bare raise; or raise of the handler's own
variable), raises X (the handler raises a DIFFERENT class -- the plan's four
did not cover the translation shape, and swallowed would misdescribe it),
dialog: <name> (a call on docs.dialog_routines, the witness spelled as
the source spells it), empty, else swallowed. Mined from SOURCE at doc
time on the raise miners' own comment/literal scan state (TDocFactsBuilder. MineHandlers / RenderCatches), NOT an index-time symbol_facts column
-- no extractor bump, no reindex, and a handler in a comment or string literal
is never reported. The label is Catches:, not a second Handles::
Doc.SharedFacts bounds a fact's slice in the flattened stored block by
label, so two lines under one label would collide there. New manifest keys
docs.dialog_routines (default the VCL four; [] is the off switch) and
docs.max_handles, read by document, doc-drift, hover and the
LSP through one TDocHandlesOptions threaded like the caps, so the writer
and the checker cannot disagree. document --project was run to a fixed
point on this repo in the same change (76 Catches: lines). Guard:
tests\autodoc\run_doc_exception_handles.ps1 (27 assertions, RED-first).

Property and field references RESOLVE (resolver 1.3.0-alpha; re-resolve every index)

A member-access ref naming a PROPERTY or FIELD (FConnection.Connected)
reached the resolve pass since v20b and was discarded there, because only a
routine could own a call_edges row -- so find-callers --resolved answered 0
for a property that a method on the same receiver answered 4 for, and
lint-tree reported "0 place(s)" when a public property with 207 dependents
was removed. Per the owner's ruling: the ref now binds to the member
(refs.symbol_id); a READ is also a resolved call to the read accessor and a
WRITE to the write accessor (a call_edges row when the accessor is a method
-- call_edges stays routine-only); a FIELD-backed accessor lists the access
as a use of that field. New member_accesses table (additive, no schema bump;
readers probe for it). find-callers --resolved on a property or field prints
[certain, read] / [certain, write] (JSON mode); lint-tree reports a
removed property's stale references and property/field leave
not_reportable. Every index resolved before 1.3.0-alpha answers 0 for
properties until index --all --resolve-only (or its next index).
A bare
property access inside its own class (if Flag then) is a read ref, not
member-access, and is not bound by this change.

convert-apply: unlinked source properties are warned by default, as "N of M instances", keyed by (source type, property)

A source property some converted instance carries that no #link carries and
no #ignore acknowledges is now warned ONCE per (source type, property):

TabcToggleBtn.Style: no #link carries it -- dropped on 20 of 20 converted instance(s); add a #link, or #ignore Style to accept the drop

Read the fraction, not the count: 2 of 20 is the two controls somebody
deliberately styled (ParentFont = False) and is the STRONGER signal; 20 of 20 is a structural non-mapping. Keyed by source type so two #convert blocks
both dropping Style are two rows, not one. --format json carries
unlinked_source_properties (rows), unlinked_source_property_sites (sum of
sites -- both keep their step-1 meaning) and an additive unlinked[]
(from_type, path, sites, instances); the warnings are items[] of kind
unlinked-source-property. --no-warn-unlinked drops the warnings and keeps
the count. Default-on because the number earned it: 2 distinct / 22 sites on a
real 36-link book.

convert: #link between class-typed properties carries sub-leaves on TYPE IDENTITY

#link Font <- Font with TFont on both sides now carries every sub-leaf the
.dfm streams (Font.Charset, Font.Name, ...) automatically -- the five
hand-written Font.* lines become one. When the types DIFFER
(OptionsImage.Glyph <- Picture, TdxSmartGlyph <- TPicture) nothing is
carried implicitly and every dotted leaf must still be named, because an
invented target path is how a form stops loading. An explicit per-leaf #link
/ #ignore / #remove always wins over the carry; a carried leaf is reported
(sub-leaf-carried with path and rule_line in apply/1; report.carried[]
in convert-reemit) so the leaves nobody typed are visible. Not implemented:
the "target type is an ancestor of the source type" case. Two step-4b defects
fixed alongside: VCL-shaped dotted leaves (Font.Size = 9 as one child) were
reported "absent from the F DFM", and class-typed containers were listed under
"defaults may diverge".

duplicate-global-decl: LIBRARY tier

A project global whose NAME is also an interface-level global of a library
unit that the declaring file USES (interface or implementation uses;
SysUtils matches System.SysUtils) is reported -- masking an RTL name is
almost always a naming error. 2+ project units AND the library is the stronger
three-declaration message. Severity warning, NO autofix (only you know which
declaration is meant). Measured before the severity was final: 44 findings on
ORM3 CLIENT (every one a genuine RTL/WinAPI re-declaration), rule cost 1.6 s
against the 3.7 GB Win32 library.

lint: two false positives fixed

  • hardcoded-ip-address no longer reads a dotted-quad VERSION const
    (YADF_MIN_VERSION = '1.0.6.6') as an IPv4 address. New rule predicate
    (#in? @cap "nodeType" ["nameRegex"]) / #not-in? -- "some ancestor of the
    captured node has that type and its name: matches" -- documented in
    rules\README.md.
  • review-marker-unused no longer fires on a dl:ok that IS suppressing a
    store-backed (project-scope) finding: the marker join keyed the finding's
    ABSOLUTE path against the scanned file's path as typed, so a relative lint src\X.pas never matched. Both sides are now normalised.