Skip to content

Commit 9bf8841

Browse files
1.2.7: kernel types, data source properties, extension members in find
- index the X++ kernel types (QueryBuildDataSource, FormDataObject, xRecord...) from the resources of bin\Microsoft.Dynamics.AX.Metadata.dll as the compiled model Kernel, with complete method signatures - xpp_object: data source behaviour properties and field count; parent=<data source> lists its fields - xpp_find "Table.member" also matches members added in extensions of the table; the base object's members come first
1 parent 78e5ae0 commit 9bf8841

13 files changed

Lines changed: 400 additions & 16 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33
All notable changes to xpp-lens (called xpp-graft up to 1.2.0). Versions follow `<Version>` in
44
`src/XppLens/XppLens.csproj`; release tags are `vX.Y.Z`.
55

6+
## 1.2.7 — 2026-10-13
7+
8+
### Added
9+
- X++ kernel types are indexed as the compiled model `Kernel`: `QueryBuildDataSource`, `QueryBuildRange`,
10+
`FormDataObject`, `xFormRun`, `xRecord`, `Map` and the other system classes with complete method signatures
11+
(parameter types, defaults, static / final), base classes, system enums, EDTs and tables — about 3 400 objects read
12+
from the resources of `bin\Microsoft.Dynamics.AX.Metadata.dll` (the metadata the X++ compiler uses), without
13+
loading the assembly. Indexed in the background with the standard tier; re-read when the assembly changes.
14+
- `xpp_object` data sources show their behaviour properties (`InsertIfEmpty`, `InsertAtEnd`, `AllowCreate` /
15+
`AllowEdit` / `AllowDelete`, `LinkType`, `OnlyFetchActive`, `DelayActive`, `Index`, `CounterField`…) and the
16+
number of fields; `parent=<data source>` shows one data source with all its fields.
17+
18+
### Fixed
19+
- `xpp_find "Table.member"` did not find fields and methods added in extensions of the table (found only with
20+
`*.member` or the extension name). The object part now also matches extensions that name the object as their
21+
target; the base object's own members come first.
22+
623
## 1.2.6 — 2026-10-13
724

825
### Changed

‎README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Settings live in `xpplens.json` next to the `bin` folder and can also be edited
8484
| full | all non-Microsoft models (detected by `Publisher` in the descriptor) + those in `extraFullModels` | objects, members, method signatures and source, code references (calls incl. chained, types, fields, intrinsics, labels), metadata references |
8585
| standard | Microsoft models | objects, fields/indexes/relations, method signatures with line ranges, `extends`, CoC and event handlers, and **calls** from method bodies (calls, `new`, intrinsics — no field reads, types or labels; switch off with `--standard-code false`) |
8686
| compiled | packages deployed without XML (e.g. country localizations or ISV modules shipped in compiled form only) | object names from `bin\*.md`, methods, fields, field groups, relations and **compiler references** from `.xref`, CoC from `ChainOfCommand.xml`, inheritance from `ClassExtends.runtime`, labels from `Resources\<language>\*.resources.dll` — no source code |
87+
| compiled: `Kernel` | X++ kernel types without XML (`QueryBuildDataSource`, `FormDataObject`, `xRecord`, `Map`, system enums, EDTs and tables) | classes with complete method signatures, base classes, enum values, fields — from the resources of `bin\Microsoft.Dynamics.AX.Metadata.dll`, the metadata the compiler uses |
8788

8889
A standard package can be promoted to the full tier (`--add-full-model ApplicationSuite`) if you need every reference
8990
there (fields, types, labels) and instant `xpp_grep`. The cost is a longer build and a larger database.
@@ -125,7 +126,7 @@ What each MCP tool answers, when Claude should reach for it, and the CLI equival
125126
| Tool | Answers | Use it when | CLI example |
126127
|---|---|---|---|
127128
| `xpp_find` | where objects, methods, fields are (`*`, `?`, `Object.member`, dotted extension names); with `property`: a root property of every object of a type / model | you know a name or part of it; "PublicEntityName of all our entities" | `xpplens find "Cust*Invoice*; SalesLine.createLine"`, `xpplens find "*" --type entity --model Contoso --property PublicEntityName` |
128-
| `xpp_object` | skeleton of an object: properties with labels, fields, indexes, relations, data sources, control/menu tree, methods with line ranges, extensions | you need the structure, not the code | `xpplens object CustTable --type table` |
129+
| `xpp_object` | skeleton of an object: properties with labels, fields, indexes, relations, data sources (join, `InsertIfEmpty`, `Allow*`, `LinkType`…, field count; `parent=<data source>` lists its fields), control/menu tree, methods with line ranges, extensions | you need the structure, not the code | `xpplens object CustTable --type table`, `xpplens object SalesTable --type form --parent SalesLine` |
129130
| `xpp_method` | the source of a method with file path and line range, CoC wrappers and handlers of it | you need the code; for long methods with `match`/`lines` | `xpplens method SalesTable validateWrite --match "checkFailed" --context 2` |
130131
| `xpp_callers` | who calls a method — custom code first, then compiled packages and Microsoft code; chained calls (`Table::find().m()`) included | impact of a change, "where is this used" | `xpplens callers CustTable creditMax` |
131132
| `xpp_callees` | what a method uses: calls (chained receivers typed), new, fields, enums, intrinsics, labels | understanding a method without reading it | `xpplens callees SalesFormLetter run` |

‎README.pl.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ Ustawienia siedzą w `xpplens.json` obok katalogu `bin` — można je też edyto
8484
| pełny | wszystkie niemicrosoftowe (wykrywane po `Publisher` w deskryptorze) + te z `extraFullModels` | obiekty, składowe, sygnatury i kod metod, referencje w kodzie (wywołania, także łańcuchowe, typy, pola, intrinsics, etykiety), referencje z metadanych |
8585
| standardowy | modele Microsoftu | obiekty, pola/indeksy/relacje, sygnatury metod z zakresami linii, `extends`, CoC i event handlery oraz **wywołania** z ciał metod (wywołania, `new`, intrinsics — bez odczytów pól, typów i etykiet; wyłączasz przez `--standard-code false`) |
8686
| skompilowany | pakiety wdrożone bez XML (np. lokalizacje krajowe albo moduły ISV dostarczone tylko w postaci skompilowanej) | nazwy obiektów z `bin\*.md`, metody, pola, grupy pól, relacje i **odwołania z kompilatora** z `.xref`, CoC z `ChainOfCommand.xml`, dziedziczenie z `ClassExtends.runtime`, etykiety z `Resources\<język>\*.resources.dll` — bez kodu źródłowego |
87+
| skompilowany: `Kernel` | typy jądra X++ bez XML (`QueryBuildDataSource`, `FormDataObject`, `xRecord`, `Map`, systemowe enumy, EDT i tabele) | klasy z pełnymi sygnaturami metod, klasy bazowe, wartości enumów, pola — z zasobów `bin\Microsoft.Dynamics.AX.Metadata.dll`, czyli metadanych, z których korzysta kompilator |
8788

8889
Pakiet standardowy można awansować do pełnego (`--add-full-model ApplicationSuite`), jeśli potrzebne są tam wszystkie
8990
referencje (pola, typy, etykiety) i natychmiastowy `xpp_grep`. Kosztem jest dłuższa budowa i większa baza.
@@ -126,7 +127,7 @@ Na co odpowiada każde narzędzie MCP, kiedy Claude powinien po nie sięgnąć i
126127
| Narzędzie | Odpowiada na | Kiedy używać | Przykład w CLI |
127128
|---|---|---|---|
128129
| `xpp_find` | gdzie są obiekty, metody, pola (`*`, `?`, `Obiekt.składowa`, nazwy rozszerzeń z kropką); z `property`: właściwość główna każdego obiektu danego typu / modelu | znasz nazwę albo jej fragment; „PublicEntityName wszystkich naszych encji” | `xpplens find "Cust*Invoice*; SalesLine.createLine"`, `xpplens find "*" --type entity --model Contoso --property PublicEntityName` |
129-
| `xpp_object` | szkielet obiektu: właściwości z etykietami, pola, indeksy, relacje, źródła danych, drzewo kontrolek/menu, metody z zakresami linii, rozszerzenia | potrzebna struktura, nie kod | `xpplens object CustTable --type table` |
130+
| `xpp_object` | szkielet obiektu: właściwości z etykietami, pola, indeksy, relacje, źródła danych (złączenie, `InsertIfEmpty`, `Allow*`, `LinkType`…, liczba pól; `parent=<źródło danych>` wypisuje jego pola), drzewo kontrolek/menu, metody z zakresami linii, rozszerzenia | potrzebna struktura, nie kod | `xpplens object CustTable --type table`, `xpplens object SalesTable --type form --parent SalesLine` |
130131
| `xpp_method` | kod metody ze ścieżką pliku i zakresem linii, jej wrappery CoC i handlery | potrzebny kod; przy długich metodach z `match`/`lines` | `xpplens method SalesTable validateWrite --match "checkFailed" --context 2` |
131132
| `xpp_callers` | kto wywołuje metodę — najpierw kod własny, potem pakiety skompilowane i kod Microsoftu; z wywołaniami łańcuchowymi (`Table::find().m()`) | wpływ zmiany, „gdzie to jest używane” | `xpplens callers CustTable creditMax` |
132133
| `xpp_callees` | czego używa metoda: wywołania (z typem odbiorcy w łańcuchach), new, pola, enumy, intrinsics, etykiety | zrozumienie metody bez czytania jej | `xpplens callees SalesFormLetter run` |

‎src/XppLens/Catalog.cs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public static List<ModelInfo> Discover(Config cfg)
6666
}
6767
}
6868
}
69+
// X++ kernel types (QueryBuildDataSource, FormDataObject, Args…): compiled-only model read from the
70+
// metadata assembly in bin (see KernelMetadata).
71+
if (KernelMetadata.DllPath(cfg.PackagesDir) is { } kernel && !result.Any(m => m.Package.Equals(KernelMetadata.Package, StringComparison.OrdinalIgnoreCase)))
72+
result.Add(new ModelInfo(KernelMetadata.Package, KernelMetadata.Package, "Microsoft (kernel)", 0, Path.GetDirectoryName(kernel)!, Full: false, Binary: true));
6973
return result;
7074
}
7175

‎src/XppLens/Indexer.cs‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,23 +177,27 @@ void Flush()
177177
public SyncStats SyncBinaryModel(Store s, ModelInfo m, bool force, Func<IDisposable> writeLock)
178178
{
179179
var stats = new SyncStats();
180-
var fp = BinaryPackage.Fingerprint(m, cfg.LabelLanguages);
180+
bool kernel = KernelMetadata.IsKernel(m);
181+
var fp = kernel ? KernelMetadata.Fingerprint(m) : BinaryPackage.Fingerprint(m, cfg.LabelLanguages);
181182
if (!force && s.Scalar("SELECT fingerprint FROM models WHERE id=$id", ("$id", m.Id)) as string == fp)
182183
return stats;
183184

184-
var objects = BinaryPackage.ReadObjects(m);
185-
var labels = BinaryPackage.ReadLabels(m, cfg.LabelLanguages).ToList();
186-
var xref = BinaryPackage.XrefPath(m.Dir, m.Package);
187-
var fi = xref != null ? new FileInfo(xref) : null;
185+
var kernelDll = Path.Combine(m.Dir, KernelMetadata.Assembly);
186+
var objects = kernel ? KernelMetadata.ReadObjects(kernelDll) : BinaryPackage.ReadObjects(m);
187+
var labels = kernel ? [] : BinaryPackage.ReadLabels(m, cfg.LabelLanguages).ToList();
188+
var source = kernel ? kernelDll : BinaryPackage.XrefPath(m.Dir, m.Package);
189+
var fi = source != null ? new FileInfo(source) : null;
188190
long size = fi?.Length ?? 0, mtime = fi?.LastWriteTimeUtc.Ticks ?? 0;
191+
string ObjectPath(ParsedObject o) =>
192+
kernel ? $"{kernelDll}{BinaryPackage.Marker}{o.Type}/{o.Name}" : BinaryPackage.ObjectPath(m, o.Type, o.Name);
189193

190194
using (writeLock())
191195
{
192196
s.DeleteModelData(m.Id);
193197
using (var w = new Store.Writer(s))
194198
{
195199
foreach (var o in objects)
196-
w.WriteObject(m.Id, BinaryPackage.ObjectPath(m, o.Type, o.Name), size, mtime, o, storeSources: false);
200+
w.WriteObject(m.Id, ObjectPath(o), size, mtime, o, storeSources: false);
197201
foreach (var (path, labelFile, lang, list) in labels)
198202
{
199203
var lfi = new FileInfo(path);

0 commit comments

Comments
 (0)