v0.16.0 — what we cannot see, said out loud
What we cannot see, said out loud.
Every release so far made the same kind of promise: here is something in your application you could
not see from the code. This one keeps that promise — reports are read now, the largest gap left in
the extraction — and then does the opposite thing, which turns out to matter more.
An XAF application's reports are frequently not in its repository at all. With ReportsModuleV2
registered, users design reports at run time and they are stored as rows in a database, out of reach
of anything that reads source. An application with forty reports and none in its code is not an edge
case; it is what a reporting setup looks like once people use it. So the answer had to stop being a
list and start being three different sentences: the list is all of them, the list is a lower
bound, or the number is unknown rather than zero — and that last one is the common case, the
one where a tool that answers confidently does real damage. An agent told an application has no
reports designs as though none can exist.
The same correction landed on the framework catalog, where it had been wrong for three releases.
The newest catalog on the machine was used for every application whatever version it targeted, and
the result said "these controllers load onto this screen" in one confident sentence either way. On a
machine holding a single 26.1 catalog that sentence was produced for a 23.2 application and for a
17.1 one, unqualified. It now asks for the release the application declares, still falls back when
that catalog is absent, and says which wherever a framework fact is reported.
Both halves of the reports work are a collaboration: [@MBrekhof] extracted them, this side rendered
them and wrote the bound. Two things only the generated document could show were caught that way —
a citation printing an absolute path from the machine that ran the extraction, and one layout's
filter and GetCriteria() printed twice when two registrations shared it.
Five spellings of a DevExpress version are read now, because seven real applications were checked
instead of fixtures: PackageReference, a floating 25.2.*-*, an MSBuild property (what
DevExpress's current template generates), and a pre-NuGet assembly reference from 17.1. Three of
those seven module folders hold more than one .csproj, which had been resolved by whatever order
the file system returned.
457 tests, zero warnings.
Added
-
The reports are written down, and the list says what it is ([#37], the rendering half). They
now appear in the Markdown pages, inAGENTS.md, and through a newxaf_reportsMCP tool — each
with what it is over, the filter inside its layout, its calculated fields and bound expressions,
and the parameters dialog it opens with, including theGetCriteria()that turns the answers into
a filter.The sentence under the heading carries more than the list. With
ReportsModuleV2registered,
users design reports at run time and those are stored as database rows, so an application with
forty of them and none in its repository is the ordinary case: checked against a production
application that registers the module, setsReportStoreMode.XML, and contains no report in
source at all. Printing "no reports" there is not an incomplete answer but a wrong one, and the
more use an application makes of reports the wronger it gets. Three states are told apart — the
module absent and the list complete, the module present and the list a lower bound, and the
module present with nothing in source, where the number is reported as unknown rather than zero.
An application that registers nothing and ships no layout gets no section, because there "no
reports" is the default rather than a finding.Two things the generated document showed that reading the code would not have. A layout kept
beside the module rather than inside it was cited by its absolute path — the drive of whichever
machine ran the extraction, in a file meant to be committed; citations now fall back to the
solution root and then to the file name, never to a path that is wrong everywhere but here. And
two registrations sharing one.repxprinted the filter, the bindings and the whole of
GetCriteria()twice, burying the only thing that differs between them; the second now points at
the first. -
The reports an application declares are read ([#37], phases 1–3 — the extraction; the
Markdown and MCP rendering follow separately). Reports V2 leaves four kinds of trace in a
repository, all syntax, and none of them was read: the registration
(PredefinedReportsUpdater.AddPredefinedReport<T>, in the sameGetModuleUpdatersthe updater
already lives in), the layout (designer code, a.repx, or a constructor), and the parameters
dialog (ReportParametersObjectBase, whoseGetCriteria()is business logic in the plainest
sense).ExtractedProject.Reportsnow carries each registration with what the call says and
nothing it does not —IsInplaceReportis null when the overload is silent — plus the layout's
filter, bound expressions, grouping, calculated fields and parameters, and the dialog's fields
and criteria source.ReferencesReportsModuleis the flag the rendering needs for the sentence
that makes the list safe to believe: withReportsModuleV2in, users build reports at run time
that live only in the database, and the list is a lower bound.
Three things the real files taught, each pinned by the newReportsSolutionfixture: a.repx
parameter's type resolves through<ObjectStorage>; a layout exported from the running
application keeps its data source there too; and a shop that designs reports outside Visual
Studio keeps the exports beside the module, registered by nothing — so every.repxin the
solution is read, and the unclaimed ones are listed as unregistered rather than skipped.
Checked against three licensed applications, one of which registers through reflection over a
catalog: a syntactic reader correctly sees zero registrations there, the module referenced, and
the fourteen layouts and two parameters objects it would otherwise have hidden.
Fixed
-
The framework catalog is chosen by the version the application declares, not by file date.
LoadLatest()took the newest catalog on the machine whatever the application targeted, and the
output then reported which framework controllers load onto a screen in the same confident sentence
either way. On a machine holding a single 26.1 catalog, that sentence was produced for a 23.2
application and for a 17.1 one — three releases and nine years out — with nothing to tell the
reader. Reported by the external review at 0.12.0 and live until now.Extraction now reads the DevExpress
major.minorfrom the project file and asks for that
release's catalog. When it is not on the machine the newest is still used — most of the framework
is stable across releases, and withholding it would trade real information for a small error — but
the difference is now stated wherever a framework fact is reported: the Markdown and HTML pages,
theAGENTS.mdheader, and the MCP view detail.Both project-file spellings are read. A pre-NuGet XAF project has no
PackageReferenceat all and
names its version only inside the assembly reference (DevExpress.ExpressApp.Xpo.v17.1) — which is
exactly the case where the mismatch is widest, so reading only the modern spelling would have
missed the applications that need this most.Two further spellings were found by running this against seven real applications rather than
against fixtures, and both returned "declares nothing" until they were handled. A version written
as an MSBuild property —<DevExpressVersion>25.2.7</DevExpressVersion>with
Version="$(DevExpressVersion)"— is what DevExpress's current template generates, so it is not
an exotic case to tolerate but what a project created today looks like; properties a project file
sets are now resolved before anything reads a version, which also stops$(DevExpressVersion)
reaching the rendered package list. A floating25.2.*-*already worked and is now pinned. -
The project file a module folder is named for is the one that is read. With several
.csprojside by side — a.Net10.csprojfrom a framework migration, a hand-made
" - Backup.Module.csproj"— extraction took whichever the file system returned first, so the
target framework, the package list and the DevExpress version could come from a backup, and two
machines could describe one repository differently with nothing in the output to say why. Three
of the seven applications checked have more than one.Verified end to end against applications declaring 17.1, 23.2, 25.1, 25.2 and 26.1 — including
every case above, and one whose version matches the installed catalog, where the new sentence
correctly says nothing at all.