Repository navigation
v1.15.0-alpha -- generic names resolve by arity, nested locals, inherited fields (schema v23, re-parse required)
·
1255 commits
to main
since this release
Archives below are self-contained: the exe, the rules\ folder, and (win64 only) the component converter.
Provenance: engine (
drag-lint.exe, Win64 and Win32) andConvRulesEditor.exewere built from a clean git worktree at2793f206; nothing uncommitted went into either archive.
REQUIRED after installing: rebuild every existing index. This release moves the index format (schema v22 -> v23, extractor 1.16.0 -> 1.17.0, resolver 1.3.0 -> 1.4.0). A v23 engine refuses a v22 database with index schema v22 < v23 and does not migrate it in place -- run drag-lint index --all --rebuild (or index --project <X.dproj> --db <db> --rebuild per project) before querying, linting or starting the LSP against an existing index.
v1.15.0-alpha -- 2026-09-17
Added
glyph-vacuum --root <dir> --out <dir> [--db <db>] [--append](converter):
walks every.dfm/.fmxunder the root, decodes every streamed graphic
(a binary.dfmis converted in memory), and writesinstances.tsv, the
decoded images, a per-classclasses.tsv(count property, inferred strip N,
agreement, kind, format and distinct-payload distributions,runtime_refs
counted through resolved property refs when--dbis given) and a
gallery.htmlwith one card per distinct payload per class, slot separators
overlaid at width div N. Unparseable files are listed inskipped.tsv, never
dropped;--appendmerges a rescan by (dfm_path, object_path, property), so
a second run is idempotent. The input todocs\GLYPH-CLASSES.mdand the
G[I/N]grammar.- ConvRulesEditor: the Unit Rules tab lists each used unit with the section it
is declared in (interface / implementation) and fills the moment a unit is
picked -- Browse, combo select or Fill, form or not. The declared-class list
on the same tab was empty for every input (ScanClassesDeclaredstarted its
backtrack past the keyword and never met the=).
Changed -- extractor 1.17.0-alpha / schema v23 (re-parses every index)
- Generic types and methods are indexed under their BARE name; the parameter
list is insymbols.generic_params. Ancestor edges carry
ancestor_type_argsand resolve by arity before the scope rules:
TObjectList<T: class>now climbs toSystem.Generics.Collections.TList<T>
(wasSystem.Classes.TList); ORM3's 134TMicObjectBase<I>descendants
resolve their base.query --nameacceptsTList<T>, and a dotted name is
stripped per segment, soUnit.TList<T>.Addfinds the METHOD (was the class).
Arity counts PARAMETERS, not commas:<T: class, constructor>is 1 and
<S: IUnknown; I: IUnknown>is 2, so edges onto constrained generics resolve. - Nested-routine locals and inline
var/for vardeclarations are
local_varsymbols parented to the innermost routine. Two sibling
for var Item: T inloops of DIFFERENT element types leaveItem.Mcalls
unresolved (decline) rather than typing both from the first loop. symbol_facts.reads_fields/writes_fieldsinclude INHERITED fields
(own first, nearest ancestor next) via the newfacts-inheritedindex stage.query ancestors --jsonrows carrytype_args('' on a plain edge). The
LSP's ephemeral store for a file no index owns now runs thefacts-inherited
stage too, so hover on such a file shows a same-unit inherited field in
Writes:.
Fixed
context --task "modify Class.Member"resolves when exactly one symbol's
qualified name ends with that dotted suffix (segment-aligned; an ambiguous
Class.Memberstill declines). A RECORD's class surface lists every field:
the lean DFM-component filter now runs only when the owner is a class, so
modify TTypeAncestorno longer prints one field of eight.- A property whose accessor is OVERLOADED (
read GetItembeside twoGetItem
declarations) binds the overload whose parameter count is the property's index
count (+1 for a setter); when the count leaves several, the access records no
accessor and no call edge instead of the first-declared one (resolver 1.4.0, re-pinned). FindSymbolsByExactName(query --name) splits a dotted input per segment:
TList<T>.Addfinds the METHODgnB.TList.Add, not the class, and a dotted
path keeps only rows whose qualified name ends with it.dataset-open-without-closeignores a member namedOpenthat is indexed, passed as
an argument or assigned -- only a bareX.Open;/X.Open();statement is a
dataset open. A record fieldOpen: TArray<...>read asAState.Open[i]fired
eight times on drag-lint's own source (INBOX 2026-09-17, section 2).GetSymbolFacts/GetSymbolDocinitialise a managedResultwith
Default(), notFillChar(leak when a caller reused the variable).uses-report --name <pattern>matching NO source unit now exits 2 with
ERROR: uses-report: no index passed contains a source unit named <pattern>
on stderr and writes no output file (an existing--outputis left
untouched). It used to print0 source units, 0 rows writtenand exit 0 --
a complete-looking report against a corpus that did not contain the subject,
whileoutlineon the same file and DB refused. Converter gap 2026-09-16
(stats\draglint-gaps.log, classwrong). Guard:
tests\autotest\run_uses_report_name_no_match.ps1.