Add xaflogic wiki — every project in one page, and what they share - #49
Merged
Conversation
An explainer answers "how does this application work". A developer with ten years of client work has a question no single-application tool can be asked: have I built this before? Somewhere there is the class about to be modelled again — not a similar one, the same one, thought through properly, with the two properties this time will forget. `xaflogic wiki` reads every configured project and computes what they have in common. There is nowhere in the page to type a sentence about the collection. That is deliberate: a hand-written summary of nine applications is wrong the day the tenth is added, and nobody notices. What it computes: - Classes modelled more than once, property by property with a column per application, so the richest version is the one opened before writing it again. - The layer written here and reused: base classes carried between applications. A base type qualifies only when its own source was read in one of the projects, so no list of DevExpress type names is involved and nothing rots when DevExpress renames something. On six real applications this returned zero, which is itself the finding — everything is rebuilt from XPO primitives. - The same name, two shapes: `Total` a decimal here and a double there. - Names kept, and modules more than one application requires. Two decisions came from running it over six real applications rather than fixtures. `Double` and `double` are one type and reporting them as a disagreement is a false accusation — a tool that makes one stops being believed about the true ones; so are nullable annotations on reference types. And a name holding a different collection per entity is vocabulary, not a conflict: `XPCollection<Cobro>` beside `XPCollection<CobroDetalle>` buried `decimal` beside `double` until they were separated. Also from opening the page rather than reading the diff: the comparison silently cropped its last column, which is the failure that matters — a reader would have believed the columns they could see. `projects add` no longer requires `--resource-name`. It names a PeopleWorks Copilot resource, which is one publishing target among several and irrelevant to wiki, explain, agents and mcp; requiring it made the multi-project list unreachable without an account somewhere. 40 tests: 28 on the analysis, 12 against the generated HTML — that it asks the network for nothing, that citations never carry a machine path, and that each empty state reads as a finding rather than a heading over nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W45tzJFX3NoSrk7svtQeKT
|
|
||
| var wikiCorpus = CorpusAnalyzer.Analyze(wikiApplications); | ||
| var wikiHtml = new WikiGenerator(ThisAssemblyVersion()).Generate(wikiCorpus, wikiTitle); | ||
| var wikiFile = wikiOutput ?? Path.Combine(Directory.GetCurrentDirectory(), "xaf-wiki.html"); |
Comment on lines
+144
to
+153
| foreach (var entity in app.Project.Entities) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(entity.ClassName) || !seen.Add(entity.ClassName)) | ||
| continue; | ||
|
|
||
| if (!byName.TryGetValue(entity.ClassName, out var list)) | ||
| byName[entity.ClassName] = list = []; | ||
|
|
||
| list.Add((app, entity)); | ||
| } |
Comment on lines
+278
to
+290
| foreach (var declaration in declarations(app)) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(declaration.ClassName)) | ||
| continue; | ||
|
|
||
| declaredAt.TryAdd(declaration.ClassName, new CorpusSite | ||
| { | ||
| Application = app.Name, | ||
| Slug = app.Slug, | ||
| Owner = declaration.Owner, | ||
| Citation = SourceCitation.Of(app.Project, declaration.FilePath, declaration.Line), | ||
| }); | ||
| } |
Comment on lines
+359
to
+368
| foreach (var action in controller.Actions) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(action.ActionId)) | ||
| continue; | ||
|
|
||
| if (!byId.TryGetValue(action.ActionId, out var list)) | ||
| byId[action.ActionId] = list = []; | ||
|
|
||
| list.Add((app, controller, action)); | ||
| } |
Comment on lines
+420
to
+429
| foreach (var property in Declared(entity)) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(property.Name)) | ||
| continue; | ||
|
|
||
| if (!byName.TryGetValue(property.Name, out var list)) | ||
| byName[property.Name] = list = []; | ||
|
|
||
| list.Add((app, property)); | ||
| } |
Comment on lines
+518
to
+527
| foreach (var name in declared(app).Distinct(StringComparer.OrdinalIgnoreCase)) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(name)) | ||
| continue; | ||
|
|
||
| if (!byName.TryGetValue(name, out var list)) | ||
| byName[name] = list = []; | ||
|
|
||
| list.Add(app.Name); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An explainer answers how does this application work. Someone who has delivered XAF applications to clients for ten years has a question that cannot be asked of one application at a time: have I built this before?
xaflogic wikireads every configured project into one self-contained HTML page and computes what they have in common. There is nowhere in that page to type a sentence about the collection — deliberately. A hand-written summary of nine applications is wrong the day the tenth is added, and nobody notices.What it computes
Totaladecimalhere and adoublethereRequiredModuleTypessays they all needPlus per-application detail, search across everything, and a filter that shows only what touches one project.
Two decisions that came from real projects, not fixtures
Run over six real XAF applications (405 entities, 111 controllers), the first output had the signal buried:
Doubleanddoubleare one type. Reporting them as a disagreement is a false accusation, and a tool that makes one stops being believed about the true ones. Same for a nullable annotation on a reference type.decimal?besidedecimalis a real difference and is kept.XPCollection<Cobro>besideXPCollection<CobroDetalle>is what ordinary words do. It was buryingTotal: decimal vs double,UnitPrice: double vs decimalandActivo: string vs bool— the ones somebody would act on. Scalar disagreements now sort first, so the cap can never be what removes them.One more came from opening the page rather than reading the diff: the comparison table silently cropped its last column. That is the failure that matters — a reader would have believed the columns they could see.
A rule worth stating
A base class is listed as yours only when its own source was read in one of the projects. No list of DevExpress type names is involved, so nothing rots when DevExpress renames something. On the six real applications this returned zero — everything derives straight from
XPObject,XPCustomObject,XPLiteObject. That is itself the finding, and the page says it rather than showing a heading over nothing.The limits section says the rest out loud: classes are matched by name, so the wiki knows they share a name and the comparison is what tells you whether they share an idea; a base class in a library you did not add to the wiki is absent, not framework; and report counts stay lower bounds, per application, exactly as in 0.16.0.
Also
projects addno longer requires--resource-name. It names a PeopleWorks Copilot resource — one publishing target among several, and irrelevant towiki,explain,agentsandmcp, all of which read the configured list and write locally. Requiring it made the multi-project list unreachable without an account somewhere. Defaults to the profile name.Verification
🤖 Generated with Claude Code