Delphi-RAG-Lint

drag-lint help

Chart questions

Since: 1.20.2-alpha

Every chart question of the Reports submenu and drag-lint ask, imported from REPORT_QUESTIONS.

Put the caret on a routine, field, type or unit and pick a question from drag-lint > Reports, or run drag-lint ask <id> --target <name> --project <dproj>; you get a clickable chart and a DocInsight text answer. Needs a fresh project index and Graphviz for the pictures.

How to run it

drag-lint ask <question> --target <T> [--project <P.dproj> | --in <U.pas> | --db <idx>] [--to <B>] [--server-db <idx>]

Example:

drag-lint ask butterfly --target U.TForm.Method --project P.dproj

Full flag list: ask in the CLI reference.

Flags

FlagArgumentMeaningDefault
--target<T>
--project<P.dproj>
--in<U.pas>
--db<idx>
--to<B>
--server-db<idx>
--sql-db<idx>
--counterpart-db<idx>
--depthN
--capN
--surface-capN
--control<C>
--mode
--max-rowsN
--out-root<dir>
--pairs-file<f.json>
--allow-stale
--plain
--open
--resolve-only

Where to click

  • RAD Studio main menu: drag-lint > Reports
    1. Put the caret on the routine, field, type or unit you are asking about
    2. drag-lint > Reports, then pick the question from its group
    3. The chart opens in the browser; a chart row opens its line in RAD Studio

Needs: index, graphviz

Details

Ask the index a question, get a chart back. A chart question turns one formal question about one selected symbol into a clickable diagram: who calls this, what breaks if I change it, which tests reach it, what does this form wire, where does this protocol command travel. **In RAD Studio, ask from drag-lint > Reports** with the caret on the symbol. Outside the IDE the questions are answered in-process by the engine (drag-lint ask); no PowerShell is needed (see Charts and the IDE). The engine verb drag-lint ask ships; the full call design is below.

drag-lint is not a model, and these charts are not drawn from prose. Every diagram comes from a FORMAL CALL -- a question id, a selection and parameters -- and every row in it is a fact from the index with a file and a line.

The call (design; see the ask page for the flags that ship)

drag-lint ask --list --at <file.pas>:<line>:<col> --db <project.sqlite> --json
drag-lint ask --question <id> --at <file.pas>:<line>:<col> --db <project.sqlite>
              [--depth N] [--format svg|mermaid|json]
  • --list resolves the selection and returns ONLY the questions valid for its kind -- a method gets butterfly, who-calls, effects...; a unit gets deps and cycles; a form class gets lifecycle and event-wiring. An editor never hard-codes the menu; it asks and renders what comes back.
  • --at is a caret position, resolved exactly as Type at Cursor (typeat) resolves one.
  • --db is the project index, as everywhere else -- and the platform library index after it when an RTL/VCL ancestor or type should resolve.

What runs TODAY -- the same questions by NAME, through the chart pipeline:

drag-lint ask <id> --target <Unit.TType.Member | Unit | project> --db <project.sqlite>
               [--depth N] [--cap N] [--out-root <dir>] [--open]

The questions

QuestionYou selectThe chart shows
butterflymethodcallers and callees in one chart
who-callsmethodN-deep caller tree, cycle-guarded
what-it-callsmethodN-deep callee tree
pathmethod A + method B (-To)every shortest call path A -> B, each call with its site and grade
who-writesfield / propertyevery routine that assigns it
who-readsfield / propertyevery routine that reads it
change-impactmethod / typeeverything a change here could break, by zone and hop
tested-byany symbolthe DUnitX tests whose call trees reach it
effectsmethodwhat it mutates, and whether it is Effect-free (proven)
touches-tablesmethodwhich database tables it reads and writes
class-surfacetypemembers by visibility
hierarchytypeancestors above, descendants below
depsunitused-by and uses, grouped by source directory
cyclesunit / projectcircular dependencies, every edge drawn
wiringinterfaceSpring4D registrations and resolve sites
lifecycleform classcreate -> show -> destroy: wired / implemented-not-wired / absent
event-wiringform classwhich handler runs on which control event
architectureprojectunits as source-directory zones, back-edges in red
protocol-tracecommand constant / methodwhere a protocol command travels
crosses-boundarymethodwhether and where the work leaves the process
shown-wheredatabase columnwhich forms and controls display it
exception-pathsmethodwhat it raises, what it handles, and where each exception is caught up the caller chain
consumerstable / columnthe routines that read and write it, plus its triggers, procedures and indexes
feeds-fromform controlthe chain that feeds it: control -> datasource -> dataset -> view-model -> table.column
lands-whereORM property / field / form controlwhere its value lands: TABLE.COLUMN, the server code that writes and reads it, and the triggers that use it

What you get

Every answer is a bundle written to one folder named after the question and the selection:

FileWhat it is
graph.svgThe chart. Every row is a real link (see Click to source)
graph.png, graph.pdfRaster and document exports of the SAME layout
graph.dot, graph.plainThe Graphviz input and the layout geometry. One dot run writes all four outputs, so the picture and its hit-test geometry cannot drift
index.htmlA browser shell around the chart, with the counts in its header
meta.jsonThe index fingerprint (path, size, mtime), every count the question produced, and the exact command that regenerates the bundle -- so a stale chart is DETECTABLE, not merely suspected
xref.txtA DocInsight <remarks> block to paste into the unit, pointing at the chart

These are not autodocumentation. A chart is large, slow to produce and stable over time, so nothing generates one on a build. You ask deliberately and paste the REFERENCE; the volatility lives in the file (a stable path plus a regenerated artifact), never in the comment.

How to read one

  • Rows, not nodes. Symbols are clickable text rows inside one rounded box per unit (or per source directory), so 30 routines read as 6 boxes and every row keeps its own file and line.
  • Nothing is dropped silently. When a cap hides rows the chart says +N more ... not shown; the header always carries the totals.
  • Certain vs inferred. A row reached by a resolved edge is certain; a row reached only by NAME (another routine that happens to share the name) is marked, and an inferred edge is drawn dashed.
  • A refusal is an answer. touches-tables on an index that owns no database connection, or wiring on a class, refuses with the reason instead of drawing an empty chart that would read as "nothing".

Click to source

Each row in graph.svg links to draglint://open?file=<path>&line=<n>. With the protocol registered (one HKCU key, no elevation: drag-lint protocol register; drag-lint protocol unregister undoes it), a click opens the line in RAD Studio through the drag-lint IDE plugin's open-source pipe (\\.\pipe\drag-lint-open-source), or in Notepad when no IDE is listening. See the handler.

Requirements

  • A project index (<project folder>\_D-RAG\<project>.sqlite), fresh -- a stale index draws a stale chart, and meta.json records which one was used.
  • Graphviz dot (layout engine) on the machine.
  • protocol-trace and crosses-boundary need an index resolved at resolver 1.6.0-alpha or later (enum-value binding); run index --all --resolve-only once on an older index.

Samples -- drag-lint's own code

All three were produced by the chart pipeline against a COPY of drag-lint's self-index (src\cli\_D-RAG\drag-lint.sqlite, engine 1.17.0-alpha, resolver 1.6.0-alpha). The SVG files are in the repository under docs/Images/charts/; their rows link back to the source.

change-impact: one function feeds closure, parse and lint

change-impact of ProfileFromDproj

Question change-impact, target DRagLint.Preprocess.Profile.ProfileFromDproj, depth 3: 15 routines over 1 unit reach it within 3 caller hops -- pp-profile and ResolveIndexProfile directly, then the project closure (BuildProjectFileScope), index, lint, lint-all, reconcile-project and document --project. That is why the platform-PropertyGroup fix to this one function moved the extractor version. Command: drag-lint ask change-impact --target DRagLint.Preprocess.Profile.ProfileFromDproj --db <drag-lint.sqlite> --depth 3 --cap 16 (--cap 16 so all 16 rows show; the default draws 8 rows per zone and discloses the rest). SVG

deps: where the linter sits in the layering

deps of DRagLint.Lint.Linter

Question deps, target DRagLint.Lint.Linter: 6 units use it (the CLI unit and program file, two LSP units, the MCP server, one lint unit) and it uses 9 (core, parser, diagnostics, tree-sitter, three lint units), each grouped by src\ folder. Dashed = an implementation-section uses. Command: drag-lint ask deps --target DRagLint.Lint.Linter --db <drag-lint.sqlite>. The whole-project architecture question on the same index draws 129 units in 23 zones with 598 internal edges -- accurate and too dense to read at page size, which is why a one-unit deps is the sample here. SVG

butterfly: the enum-value binding entry point

butterfly of ResolveEnumValueRead

Question butterfly, target DRagLint.Index.CallResolver.TCallResolver.ResolveEnumValueRead, depth 2: 2 callers (the store's enum-value and call-target resolve passes) and 14 callee rows (scope checks, the identical-copy collapse, and the symbol store lookups). Command: drag-lint ask butterfly --target DRagLint.Index.CallResolver.TCallResolver.ResolveEnumValueRead --db <drag-lint.sqlite> --depth 2. SVG

butterfly, callgraph, reverse-calltree, graph --format dot|mermaid, cycles, deps-report and impact print the underlying data as dot, mermaid, text or JSON. The ask questions render it -- grouped, capped with disclosure, and clickable.


All features | CLI reference | IDE menus